/** * Build the test category * $session_id, $course_code, $with_base_content, $this->specific_id_list[$tool] * @todo add course session */ public function build_test_category($session_id = 0, $course_code = '', $with_base_content = false, $id_list = array()) { $course_id = api_get_course_int_id(); // get all test category in course $tab_test_categories_id = Testcategory::getCategoryListInfo("id", $course_id); foreach ($tab_test_categories_id as $test_category_id) { $test_category = new Testcategory($test_category_id); $copy_course_test_category = new CourseCopyTestcategory($test_category_id, $test_category->name, $test_category->description); $this->course->add_resource($copy_course_test_category); } }
/** * @param Application $app * @param int $id * * @return Response */ public function deleteCategoryAction(Application $app, $id) { $repo = $app['orm.ems']['db_write']->getRepository('Entity\\CQuizCategory'); $category = $repo->find($id); if (empty($category)) { $app->abort(404); } $count = $repo->childCount($category); if ($count == 0) { $testCategory = new \Testcategory($id); $count = $testCategory->getCategoryQuestionsNumber(); if ($count == 0) { $objcat = new \Testcategory($id); $objcat->removeCategory(); $url = $app['url_generator']->generate('admin_questions'); } return $app->redirect($url); } else { $app->abort(401); } }
/** * Returns a category summary report * * @param int exercise id * @param array prefilled array with the category_id, score, and weight example: array(1 => array('score' => '10', 'total' => 20)); * @param bool $categoryMinusOne shows category - 1 see BT#6540 * @return string */ public static function get_stats_table_by_attempt($exercise_id, $category_list = array(), $categoryMinusOne = false) { if (empty($category_list)) { return null; } $category_name_list = Testcategory::getListOfCategoriesNameForTest($exercise_id, false); $table = new HTML_Table(array('class' => 'data_table')); $table->setHeaderContents(0, 0, get_lang('Categories')); $table->setHeaderContents(0, 1, get_lang('AbsoluteScore')); $table->setHeaderContents(0, 2, get_lang('RelativeScore')); $row = 1; $none_category = array(); if (isset($category_list['none'])) { $none_category = $category_list['none']; unset($category_list['none']); } $total = array(); if (isset($category_list['total'])) { $total = $category_list['total']; unset($category_list['total']); } $em = Database::getManager(); $repo = $em->getRepository('ChamiloCoreBundle:CQuizCategory'); $redefineCategoryList = array(); if (!empty($category_list) && count($category_list) > 1) { $globalCategoryScore = array(); foreach ($category_list as $category_id => $category_item) { $cat = $em->find('ChamiloCoreBundle:CQuizCategory', $category_id); $path = $repo->getPath($cat); $categoryName = $category_name_list[$category_id]; $index = 0; if ($categoryMinusOne) { $index = 1; } if (isset($path[$index])) { $category_id = $path[$index]->getIid(); $categoryName = $path[$index]->getTitle(); } if (!isset($globalCategoryScore[$category_id])) { $globalCategoryScore[$category_id] = array(); $globalCategoryScore[$category_id]['score'] = 0; $globalCategoryScore[$category_id]['total'] = 0; $globalCategoryScore[$category_id]['title'] = ''; } $globalCategoryScore[$category_id]['score'] += $category_item['score']; $globalCategoryScore[$category_id]['total'] += $category_item['total']; $globalCategoryScore[$category_id]['title'] = $categoryName; } foreach ($globalCategoryScore as $category_item) { $table->setCellContents($row, 0, $category_item['title']); $table->setCellContents($row, 1, ExerciseLib::show_score($category_item['score'], $category_item['total'], false)); $table->setCellContents($row, 2, ExerciseLib::show_score($category_item['score'], $category_item['total'], true, false, true)); $class = 'class="row_odd"'; if ($row % 2) { $class = 'class="row_even"'; } $table->setRowAttributes($row, $class, true); $row++; } if (!empty($none_category)) { $table->setCellContents($row, 0, get_lang('None')); $table->setCellContents($row, 1, ExerciseLib::show_score($none_category['score'], $none_category['total'], false)); $table->setCellContents($row, 2, ExerciseLib::show_score($none_category['score'], $none_category['total'], true, false, true)); $row++; } if (!empty($total)) { $table->setCellContents($row, 0, get_lang('Total')); $table->setCellContents($row, 1, ExerciseLib::show_score($total['score'], $total['total'], false)); $table->setCellContents($row, 2, ExerciseLib::show_score($total['score'], $total['total'], true, false, true)); $table->setRowAttributes($row, 'class="row_total"', true); } return $table->toHtml(); } return null; }
/** * form to add a category * @todo move to testcategory.class.php * @param string $in_action */ function add_category_form($in_action) { $in_action = Security::remove_XSS($in_action); // initiate the object $form = new FormValidator('note', 'post', api_get_self() . '?action=' . $in_action); // Setting the form elements $form->addElement('header', get_lang('AddACategory')); $form->addElement('text', 'category_name', get_lang('CategoryName'), array('size' => '95')); $form->add_html_editor('category_description', get_lang('CategoryDescription'), false, false, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200')); $form->addElement('style_submit_button', 'SubmitNote', get_lang('AddTestCategory'), 'class="add"'); // setting the rules $form->addRule('category_name', get_lang('ThisFieldIsRequired'), 'required'); // The validation or display if ($form->validate()) { $check = Security::check_token('post'); if ($check) { $values = $form->exportValues(); $v_name = Security::remove_XSS($values['category_name'], COURSEMANAGER); $v_description = Security::remove_XSS($values['category_description'], COURSEMANAGER); $objcat = new Testcategory(0, $v_name, $v_description); if ($objcat->addCategoryInBDD()) { Display::display_confirmation_message(get_lang('AddCategoryDone')); } else { Display::display_confirmation_message(get_lang('AddCategoryNameAlreadyExists')); } } Security::clear_token(); } else { display_goback(); $token = Security::get_token(); $form->addElement('hidden', 'sec_token'); $form->setConstants(array('sec_token' => $token)); $form->display(); } }
if ($objExercise->edit_exercise_in_lp == true) { $delete_link = '<a id="delete_' . $id . '" class="opener" href="' . api_get_self() . '?' . api_get_cidreq() . '&exerciseId=' . $exerciseId . '&deleteQuestion=' . $id . '" >' . Display::return_icon('delete.png', get_lang('RemoveFromTest'), array(), ICON_SIZE_SMALL) . '</a>'; } $edit_link = Display::tag('div', $edit_link, array('style' => 'float:left; padding:0px; margin:0px')); $clone_link = Display::tag('div', $clone_link, array('style' => 'float:left; padding:0px; margin:0px')); $delete_link = Display::tag('div', $delete_link, array('style' => 'float:left; padding:0px; margin:0px')); $actions = Display::tag('div', $edit_link . $clone_link . $delete_link, array('class' => 'edition', 'style' => 'width:100px; right:10px; margin-top: 0px; position: absolute; top: 10%;')); $title = Security::remove_XSS($objQuestionTmp->selectTitle()); $move = Display::return_icon('all_directions.png', get_lang('Move'), array('class' => 'moved', 'style' => 'margin-bottom:-0.5em;')); // Question name $questionName = Display::tag('div', '<a href="#" title = "' . Security::remove_XSS($title) . '">' . $move . ' ' . cut($title, 42) . '</a>', array('style' => $styleQuestion)); // Question type list($typeImg, $typeExpl) = $objQuestionTmp->get_type_icon_html(); $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), ICON_SIZE_MEDIUM), array('style' => $styleType)); // Question category $txtQuestionCat = Security::remove_XSS(Testcategory::getCategoryNameForQuestion($objQuestionTmp->id)); if (empty($txtQuestionCat)) { $txtQuestionCat = "-"; } $questionCategory = Display::tag('div', '<a href="#" style="padding:0px; margin:0px;" title="' . $txtQuestionCat . '">' . cut($txtQuestionCat, 42) . '</a>', array('style' => $styleCat)); // Question level $txtQuestionLevel = $objQuestionTmp->level; if (empty($objQuestionTmp->level)) { $txtQuestionLevel = '-'; } $questionLevel = Display::tag('div', $txtQuestionLevel, array('style' => $styleLevel)); // Question score $questionScore = Display::tag('div', $objQuestionTmp->selectWeighting(), array('style' => $styleScore)); echo '<div id="question_id_list_' . $id . '" >'; echo '<div class="header_operations">'; echo $questionName;
/** * Restore quiz-questions * @params int question id */ function restore_quiz_question($id) { $resources = $this->course->resources; $question = isset($resources[RESOURCE_QUIZQUESTION][$id]) ? $resources[RESOURCE_QUIZQUESTION][$id] : null; $new_id = 0; if (is_object($question)) { if ($question->is_restored()) { return $question->destination_id; } $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION); $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER); $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); // check resources inside html from ckeditor tool and copy correct urls into recipient course $question->description = DocumentManager::replace_urls_inside_content_html_from_copy_course($question->description, $this->course->code, $this->course->destination_path); $parent_id = 0; if (isset($question->parent_info) && !empty($question->parent_info)) { $question_obj = Question::readByTitle($question->parent_info['question'], $this->destination_course_id); if ($question_obj) { // Reuse media. $parent_id = $question_obj->selectId(); } else { // Create media. $question_obj = new MediaQuestion(); $question_obj->updateCourse($this->destination_course_id); $parent_id = $question_obj->saveMedia(array('questionName' => $question->parent_info['question'], 'questionDescription' => $question->parent_info['description'])); } } $sql = "INSERT INTO " . $table_que . " SET\n c_id = " . $this->destination_course_id . " ,\n question = '" . self::DBUTF8escapestring($question->question) . "',\n description = '" . self::DBUTF8escapestring($question->description) . "',\n ponderation = '" . self::DBUTF8escapestring($question->ponderation) . "',\n position = '" . self::DBUTF8escapestring($question->position) . "',\n type='" . self::DBUTF8escapestring($question->quiz_type) . "',\n picture='" . self::DBUTF8escapestring($question->picture) . "',\n level='" . self::DBUTF8escapestring($question->level) . "',\n parent_id = '" . $parent_id . "',\n extra='" . self::DBUTF8escapestring($question->extra) . "'"; Database::query($sql); $new_id = Database::insert_id(); if ($new_id) { if (!empty($question->picture)) { $question_temp = Question::read($new_id, $this->destination_course_info['real_id']); $documentPath = api_get_path(SYS_COURSE_PATH) . $this->destination_course_info['path'] . '/document'; // picture path $picturePath = $documentPath . '/images'; $old_picture = api_get_path(SYS_COURSE_PATH) . $this->course->info['path'] . '/document/images/' . $question->picture; if (file_exists($old_picture)) { $picture_name = 'quiz-' . $new_id . '.jpg'; $result = $question_temp->uploadPicture($old_picture, $picture_name, $picturePath); if ($result) { $sql = "UPDATE {$table_que} SET picture = '{$picture_name}' WHERE c_id = " . $this->destination_course_id . " AND id = {$new_id} "; Database::query($sql); } } } } if ($question->type == MATCHING) { $temp = array(); $matching_list = array(); $matching_to_update = array(); foreach ($question->answers as $index => $answer) { $temp[$answer['position']] = $answer; if (!empty($answer['correct'])) { $matching_to_update[$answer['iid']] = $answer['correct']; } } foreach ($temp as $index => $answer) { $sql = "INSERT INTO " . $table_ans . " SET\n c_id = " . $this->destination_course_id . " ,\n question_id = '" . $new_id . "',\n answer = '" . self::DBUTF8escapestring($answer['answer']) . "',\n correct = '" . $answer['correct'] . "',\n comment = '" . self::DBUTF8escapestring($answer['comment']) . "',\n ponderation = '" . $answer['ponderation'] . "',\n position = '" . $answer['position'] . "',\n hotspot_coordinates = '" . $answer['hotspot_coordinates'] . "',\n hotspot_type = '" . $answer['hotspot_type'] . "'"; Database::query($sql); $new_answer_id = Database::insert_id(); $matching_list[$answer['iid']] = $new_answer_id; } foreach ($matching_to_update as $old_answer_id => $old_correct_id) { $new_correct = $matching_list[$old_correct_id]; $new_fixed_id = $matching_list[$old_answer_id]; $sql = "UPDATE {$table_ans} SET correct = '{$new_correct}' WHERE iid = {$new_fixed_id} "; Database::query($sql); } } else { $correct_answers = array(); foreach ($question->answers as $index => $answer) { // check resources inside html from fckeditor tool and copy correct urls into recipient course $answer['answer'] = DocumentManager::replace_urls_inside_content_html_from_copy_course($answer['answer'], $this->course->code, $this->course->destination_path, $this->course->backup_path, $this->course->info['path']); $answer['comment'] = DocumentManager::replace_urls_inside_content_html_from_copy_course($answer['comment'], $this->course->code, $this->course->destination_path, $this->course->backup_path, $this->course->info['path']); $sql = "INSERT INTO " . $table_ans . " SET\n c_id = " . $this->destination_course_id . " ,\n id = '" . ($index + 1) . "',\n question_id = '" . $new_id . "',\n answer = '" . self::DBUTF8escapestring($answer['answer']) . "',\n correct = '" . $answer['correct'] . "',\n comment = '" . self::DBUTF8escapestring($answer['comment']) . "',\n ponderation = '" . $answer['ponderation'] . "',\n position = '" . $answer['position'] . "',\n hotspot_coordinates = '" . $answer['hotspot_coordinates'] . "',\n hotspot_type = '" . $answer['hotspot_type'] . "'"; Database::query($sql); $new_answer_id = Database::insert_id(); $correct_answers[$new_answer_id] = $answer['correct']; } } //Current course id $course_id = api_get_course_int_id(); //Moving quiz_question_options if ($question->type == MULTIPLE_ANSWER_TRUE_FALSE) { $question_option_list = Question::readQuestionOption($id, $course_id); //Question copied from the current platform if ($question_option_list) { $old_option_ids = array(); foreach ($question_option_list as $item) { $old_id = $item['iid']; unset($item['iid']); $item['question_id'] = $new_id; $item['c_id'] = $this->destination_course_id; $question_option_id = Database::insert($table_options, $item); $old_option_ids[$old_id] = $question_option_id; } if ($old_option_ids) { $new_answers = Database::select('iid, correct', $table_ans, array('WHERE' => array('question_id = ? AND c_id = ? ' => array($new_id, $this->destination_course_id)))); foreach ($new_answers as $answer_item) { $params = array(); $params['correct'] = $old_option_ids[$answer_item['correct']]; $question_option_id = Database::update($table_ans, $params, array('iid = ? AND c_id = ? AND question_id = ? ' => array($answer_item['iid'], $this->destination_course_id, $new_id)), false); } } } else { $new_options = array(); if (isset($question->question_options)) { foreach ($question->question_options as $obj) { $item = array(); $item['question_id'] = $new_id; $item['c_id'] = $this->destination_course_id; $item['name'] = $obj->obj->name; $item['position'] = $obj->obj->position; $question_option_id = Database::insert($table_options, $item); $new_options[$obj->obj->iid] = $question_option_id; } foreach ($correct_answers as $answer_id => $correct_answer) { $params = array(); $params['correct'] = $new_options[$correct_answer]; Database::update($table_ans, $params, array('iid = ? AND c_id = ? AND question_id = ? ' => array($answer_id, $this->destination_course_id, $new_id)), false); } } } } if ($question->categories) { $cats = array(); foreach ($question->categories as $cat) { $new_category = new Testcategory($cat['category_id']); $new_category = $new_category->get_category_by_title($cat['title'], $this->destination_course_id); if (empty($new_category)) { //Create a new category in this portal if ($cat['category_id'] == 0) { $category_c_id = 0; } else { $category_c_id = $this->destination_course_id; } $new_cat = new Testcategory(null, $cat['title'], $cat['description'], null, 'simple', $category_c_id); $new_cat_id = $new_cat->addCategoryInBDD(); $cats[] = $new_cat_id; } else { $cats[] = $new_category['iid']; } } $question = Question::read($new_id, $this->destination_course_id); if (!empty($cats)) { $question->saveCategories($cats); } } $this->course->resources[RESOURCE_QUIZQUESTION][$id]->destination_id = $new_id; } return $new_id; }
/** * Calculate the max_score of the quiz, depending of question inside, and quiz advanced option */ public function get_max_score() { $out_max_score = 0; $tab_question_list = $this->selectQuestionList(true); // list of question's id !!! the array key start at 1 !!! // test is randomQuestions - see field random of test if ($this->random > 0 && $this->randomByCat == 0) { $nb_random_questions = $this->random; $tab_questions_score = array(); for ($i = 1; $i <= count($tab_question_list); $i++) { $tmpobj_question = Question::read($tab_question_list[$i]); $tab_questions_score[] = $tmpobj_question->weighting; } rsort($tab_questions_score); // add the first $nb_random_questions value of score array to get max_score for ($i = 0; $i < min($nb_random_questions, count($tab_questions_score)); $i++) { $out_max_score += $tab_questions_score[$i]; } } else { if ($this->random > 0 && $this->randomByCat > 0) { $nb_random_questions = $this->random; $tab_categories_scores = array(); for ($i = 1; $i <= count($tab_question_list); $i++) { $question_category_id = Testcategory::getCategoryForQuestion($tab_question_list[$i]); if (!is_array($tab_categories_scores[$question_category_id])) { $tab_categories_scores[$question_category_id] = array(); } $tmpobj_question = Question::read($tab_question_list[$i]); $tab_categories_scores[$question_category_id][] = $tmpobj_question->weighting; } // here we've got an array with first key, the category_id, second key, score of question for this cat while (list($key, $tab_scores) = each($tab_categories_scores)) { rsort($tab_scores); for ($i = 0; $i < min($nb_random_questions, count($tab_scores)); $i++) { $out_max_score += $tab_scores[$i]; } } } else { for ($i = 1; $i <= count($tab_question_list); $i++) { $tmpobj_question = Question::read($tab_question_list[$i]); $out_max_score += $tmpobj_question->weighting; } } } return $out_max_score; }
//Total score if ($origin != 'learnpath' || $origin == 'learnpath' && isset($_GET['fb_type'])) { if ($show_results || $show_only_total_score) { $total_score_text .= '<div class="question_row">'; $my_total_score_temp = $totalScore; if ($objExercise->selectPropagateNeg() == 0 && $my_total_score_temp < 0) { $my_total_score_temp = 0; } $total_score_text .= get_question_ribbon($objExercise, $my_total_score_temp, $totalWeighting, true); $total_score_text .= '</div>'; } } if (!empty($category_list) && ($show_results || $show_only_total_score)) { //Adding total $category_list['total'] = array('score' => $my_total_score_temp, 'total' => $totalWeighting); echo Testcategory::get_stats_table_by_attempt($objExercise->id, $category_list); } echo $total_score_text; echo $exercise_content; echo $total_score_text; if (is_array($arrid) && is_array($arrmarks)) { $strids = implode(",", $arrid); $marksid = implode(",", $arrmarks); } if ($is_allowedToEdit && $locked == false && !api_is_drh()) { if (in_array($origin, array('tracking_course', 'user_course', 'correct_exercise_in_lp'))) { echo ' <form name="myform" id="myform" action="exercise_report.php?exerciseId=' . $exercise_id . '&filter=2&comments=update&exeid=' . $id . '&origin=' . $origin . '&details=true&course=' . Security::remove_XSS($_GET['cidReq']) . $fromlink . '" method="post">'; echo '<input type = "hidden" name="lp_item_id" value="' . $learnpath_id . '">'; echo '<input type = "hidden" name="lp_item_view_id" value="' . $lp_item_view_id . '">'; echo '<input type = "hidden" name="student_id" value="' . $student_id . '">'; echo '<input type = "hidden" name="total_score" value="' . $totalScore . '"> ';
/** * @Route("/delete_category") * @Method({"GET"}) * @param int $id * * @return Response */ public function deleteCategoryAction($id) { $repo = $this->getManager()->getRepository('Chamilo\\CoreBundle\\Entity\\CQuizCategory'); $category = $repo->find($id); if (empty($category)) { $this->abort(404); } $count = $repo->childCount($category); if ($count == 0) { $testCategory = new \Testcategory($id); $count = $testCategory->getCategoryQuestionsNumber(); if ($count == 0) { $objcat = new \Testcategory($id); $objcat->removeCategory(); $url = $this->generateUrl('admin_questions'); } return $this->redirect($url); } else { $this->abort(401); } }
} } // Number of questions $random_label = null; if ($row['random'] > 0 || $row['random'] == -1) { // if random == -1 means use random questions with all questions $random_number_of_question = $row['random']; if ($random_number_of_question == -1) { $random_number_of_question = $rowi; } if ($row['random_by_category'] > 0) { $nbQuestionsTotal = Testcategory::getNumberOfQuestionRandomByCategory($my_exercise_id, $random_number_of_question); $number_of_questions = $nbQuestionsTotal . " "; $number_of_questions .= $nbQuestionsTotal > 1 ? get_lang("QuestionsLowerCase") : get_lang("QuestionLowerCase"); $number_of_questions .= " - "; $number_of_questions .= min(Testcategory::getNumberMaxQuestionByCat($my_exercise_id), $random_number_of_question) . ' ' . get_lang('QuestionByCategory'); } else { $random_label = ' (' . get_lang('Random') . ') '; $number_of_questions = $random_number_of_question . ' ' . $random_label; //Bug if we set a random value bigger than the real number of questions if ($random_number_of_question > $rowi) { $number_of_questions = $rowi . ' ' . $random_label; } } } else { $number_of_questions = $rowi; } //Attempts //$attempts = get_count_exam_results($row['id']).' '.get_lang('Attempts'); //$item .= Display::tag('td',$attempts); $item .= Display::tag('td align="center"', $number_of_questions);
/** * Shows question title an description * * @param string $feedback_type * @param int $counter * @param float $score */ function return_header($feedback_type = null, $counter = null, $score = null) { $counter_label = ''; if (!empty($counter)) { $counter_label = intval($counter); } $score_label = get_lang('Wrong'); $class = 'error'; if ($score['pass'] == true) { $score_label = get_lang('Correct'); $class = 'success'; } if ($this->type == FREE_ANSWER || $this->type == ORAL_EXPRESSION) { $score['revised'] = isset($score['revised']) ? $score['revised'] : false; if ($score['revised'] == true) { $score_label = get_lang('Revised'); $class = ''; } else { $score_label = get_lang('NotRevised'); $class = 'error'; } } $question_title = $this->question; // display question category, if any $header = Testcategory::returnCategoryAndTitle($this->id); $show_media = null; if ($show_media) { $header .= $this->show_media_content(); } $header .= Display::page_subheader2($counter_label . ". " . $question_title); $header .= Display::div('<div class="rib rib-' . $class . '"><h3>' . $score_label . '</h3></div> <h4>' . $score['result'] . ' </h4>', array('class' => 'ribbon')); $header .= Display::div($this->description, array('id' => 'question_description')); return $header; }
/** * Handles a given Excel spreadsheets as in the template provided */ function lp_upload_quiz_action_handling() { global $debug; $_course = api_get_course_info(); $courseId = $_course['real_id']; if (!isset($_POST['submit_upload_quiz'])) { return; } // Get the extension of the document. $path_info = pathinfo($_FILES['user_upload_quiz']['name']); // Check if the document is an Excel document if ($path_info['extension'] != 'xls') { return; } // Read the Excel document $data = new Spreadsheet_Excel_Reader(); // Set output Encoding. $data->setOutputEncoding(api_get_system_encoding()); // Reading the xls document. $data->read($_FILES['user_upload_quiz']['tmp_name']); $correctScore = isset($_POST['correct_score']) ? $_POST['correct_score'] : null; $incorrectScore = isset($_POST['incorrect_score']) ? $_POST['incorrect_score'] : null; $useCustomScore = isset($_POST['user_custom_score']) ? true : false; $propagateNegative = 0; if ($useCustomScore && !empty($incorrectScore)) { if ($incorrectScore < 0) { $propagateNegative = 1; } } // Variables $quiz_index = 0; $question_title_index = array(); $question_name_index_init = array(); $question_name_index_end = array(); $score_index = array(); $feedback_true_index = array(); $feedback_false_index = array(); $number_questions = 0; $question_description_index = array(); $noNegativeScoreIndex = array(); $questionTypeList = array(); $questionTypeIndex = array(); $categoryList = array(); // Reading all the first column items sequentially to create breakpoints for ($i = 1; $i <= $data->sheets[0]['numRows']; $i++) { if ($data->sheets[0]['cells'][$i][1] == 'Quiz' && $i == 1) { $quiz_index = $i; // Quiz title position, only occurs once } elseif ($data->sheets[0]['cells'][$i][1] == 'Question') { $question_title_index[] = $i; // Question title position line $question_name_index_init[] = $i + 1; // Questions name 1st position line $number_questions++; } elseif ($data->sheets[0]['cells'][$i][1] == 'Score') { $question_name_index_end[] = $i - 1; // Question name position $score_index[] = $i; // Question score position } elseif ($data->sheets[0]['cells'][$i][1] == 'FeedbackTrue') { $feedback_true_index[] = $i; // FeedbackTrue position (line) } elseif ($data->sheets[0]['cells'][$i][1] == 'FeedbackFalse') { $feedback_false_index[] = $i; // FeedbackFalse position (line) } elseif ($data->sheets[0]['cells'][$i][1] == 'EnrichQuestion') { $question_description_index[] = $i; } elseif ($data->sheets[0]['cells'][$i][1] == 'NoNegativeScore') { $noNegativeScoreIndex[] = $i; } elseif ($data->sheets[0]['cells'][$i][1] == 'QuestionType') { $questionTypeIndex[] = $i; } } // Variables $quiz = array(); $question = array(); $new_answer = array(); $score_list = array(); $feedback_true_list = array(); $feedback_false_list = array(); $question_description = array(); $noNegativeScoreList = array(); // Getting questions. $k = $z = $q = $l = $m = $n = 0; for ($i = 1; $i <= $data->sheets[0]['numRows']; $i++) { if (is_array($data->sheets[0]['cells'][$i])) { $column_data = $data->sheets[0]['cells'][$i]; // Fill all column with data to have a full array for ($x = 1; $x <= $data->sheets[0]['numCols']; $x++) { if (empty($column_data[$x])) { $data->sheets[0]['cells'][$i][$x] = ''; } } // Array filled with data $column_data = $data->sheets[0]['cells'][$i]; } else { $column_data = ''; } // Fill quiz data if ($quiz_index == $i) { // The title always in the first position $quiz = $column_data; } elseif (in_array($i, $question_title_index)) { //a complete line where 1st column is 'Question' $question[$k] = $column_data; for ($counter = 0; $counter < 12; $counter++) { $myData = isset($data->sheets[0]['cells'][$i + $counter]) ? $data->sheets[0]['cells'][$i + $counter] : null; if (isset($myData[1]) && $myData[1] == 'QuestionType') { $questionTypeList[$k] = $myData[3]; } if (isset($myData[1]) && $myData[1] == 'Category') { $categoryList[$k] = $myData[2]; } } if (!isset($questionTypeList[$k])) { $questionTypeList[$k] = null; } $k++; } elseif (in_array($i, $score_index)) { //a complete line where 1st column is 'Score' $score_list[$z] = $column_data; $z++; } elseif (in_array($i, $feedback_true_index)) { //a complete line where 1st column is 'FeedbackTrue' $feedback_true_list[$q] = $column_data; $q++; } elseif (in_array($i, $feedback_false_index)) { //a complete line where 1st column is 'FeedbackFalse' for wrong answers $feedback_false_list[$l] = $column_data; $l++; } elseif (in_array($i, $question_description_index)) { //a complete line where 1st column is 'EnrichQuestion' $question_description[$m] = $column_data; $m++; } elseif (in_array($i, $noNegativeScoreIndex)) { //a complete line where 1st column is 'NoNegativeScore' $noNegativeScoreList[$z - 1] = $column_data; } } // Get answers for ($i = 0; $i < count($question_name_index_init); $i++) { for ($j = $question_name_index_init[$i]; $j <= $question_name_index_end[$i]; $j++) { if (is_array($data->sheets[0]['cells'][$j])) { $column_data = $data->sheets[0]['cells'][$j]; // Fill all column with data for ($x = 1; $x <= $data->sheets[0]['numCols']; $x++) { if (empty($column_data[$x])) { $data->sheets[0]['cells'][$j][$x] = ''; } } $column_data = $data->sheets[0]['cells'][$j]; // Array filled of data if (is_array($column_data) && count($column_data) > 0) { $new_answer[$i][$j] = $column_data; } } } } // Quiz title. $quiz_title = $quiz[2]; if ($quiz_title != '') { // Variables $type = 2; $random = $active = $results = $max_attempt = $expired_time = 0; // Make sure feedback is enabled (3 to disable), otherwise the fields // added to the XLS are not shown, which is confusing $feedback = 0; // Quiz object $exercise = new Exercise(); // $quiz_id = $exercise->createExercise($quiz_title, $expired_time, $type, $random, $active, $results, $max_attempt, $feedback, $propagateNegative); if ($quiz_id) { // insert into the item_property table api_item_property_update($_course, TOOL_QUIZ, $quiz_id, 'QuizAdded', api_get_user_id()); // Import questions. for ($i = 0; $i < $number_questions; $i++) { // Question name $question_title = $question[$i][2]; $description = isset($question_description[$i][2]) ? $question_description[$i][2] : ''; $categoryId = null; if (isset($categoryList[$i]) && !empty($categoryList[$i])) { $categoryName = $categoryList[$i]; $categoryId = Testcategory::get_category_id_for_title($categoryName, $courseId); if (empty($categoryId)) { $category = new TestCategory(null, $categoryName, ''); $categoryId = $category->addCategoryInBDD(); } } $question_description_text = "<p></p>"; if (!empty($description)) { // Question description. $question_description_text = "<p>" . $description . "</p>"; } // Unique answers are the only question types available for now // through xls-format import $answerList = isset($new_answer[$i]) ? $new_answer[$i] : ''; $question_id = null; if (isset($questionTypeList[$i])) { $detectQuestionType = intval($questionTypeList[$i]); } else { $detectQuestionType = detectQuestionType($answerList, $score_list); } /** @var Question $answer */ switch ($detectQuestionType) { case FREE_ANSWER: $answer = new FreeAnswer(); break; case GLOBAL_MULTIPLE_ANSWER: $answer = new GlobalMultipleAnswer(); break; case MULTIPLE_ANSWER: $answer = new MultipleAnswer(); break; case FILL_IN_BLANKS: $answer = new FillBlanks(); $question_description_text = ''; break; case MATCHING: $answer = new Matching(); break; case UNIQUE_ANSWER: default: $answer = new UniqueAnswer(); break; } if ($question_title != '') { $question_id = $answer->create_question($quiz_id, $question_title, $question_description_text, 0, $answer->type); if (!empty($categoryId)) { TestCategory::add_category_for_question_id($categoryId, $question_id, $courseId); } } switch ($detectQuestionType) { case GLOBAL_MULTIPLE_ANSWER: case MULTIPLE_ANSWER: case UNIQUE_ANSWER: $total = 0; if (is_array($answerList) && !empty($question_id)) { $id = 1; $globalScore = null; $objAnswer = new Answer($question_id, $courseId); $globalScore = $score_list[$i][3]; // Calculate the number of correct answers to divide the // score between them when importing from CSV $numberRightAnswers = 0; foreach ($answerList as $answer_data) { if (strtolower($answer_data[3]) == 'x') { $numberRightAnswers++; } } foreach ($answerList as $answer_data) { $answerValue = $answer_data[2]; $correct = 0; $score = 0; if (strtolower($answer_data[3]) == 'x') { $correct = 1; $score = $score_list[$i][3]; $comment = $feedback_true_list[$i][2]; } else { $comment = $feedback_false_list[$i][2]; $floatVal = (double) $answer_data[3]; if (is_numeric($floatVal)) { $score = $answer_data[3]; } } if ($useCustomScore) { if ($correct) { $score = $correctScore; } else { $score = $incorrectScore; } } // Fixing scores: switch ($detectQuestionType) { case GLOBAL_MULTIPLE_ANSWER: if (isset($noNegativeScoreList[$i][3])) { if (!(strtolower($noNegativeScoreList[$i][3]) == 'x') && !$correct) { $score = $score_list[$i][3] * -1; } } else { $score = $score_list[$i][3] * -1; } $score /= $numberRightAnswers; break; case UNIQUE_ANSWER: break; case MULTIPLE_ANSWER: if (!$correct) { //$total = $total - $score; } break; } $objAnswer->createAnswer($answerValue, $correct, $comment, $score, $id); $total += $score; $id++; } $objAnswer->save(); $questionObj = Question::read($question_id, $courseId); switch ($detectQuestionType) { case GLOBAL_MULTIPLE_ANSWER: $questionObj->updateWeighting($globalScore); break; case UNIQUE_ANSWER: case MULTIPLE_ANSWER: default: $questionObj->updateWeighting($total); break; } $questionObj->save(); } break; case FREE_ANSWER: $questionObj = Question::read($question_id, $courseId); $globalScore = $score_list[$i][3]; $questionObj->updateWeighting($globalScore); $questionObj->save(); break; case FILL_IN_BLANKS: $scoreList = array(); $size = array(); $globalScore = 0; foreach ($answerList as $data) { $score = isset($data[3]) ? $data[3] : 0; $globalScore += $score; $scoreList[] = $score; $size[] = 200; } $scoreToString = implode(',', $scoreList); $sizeToString = implode(',', $size); //<p>Texte long avec les [mots] à [remplir] mis entre [crochets]</p>::10,10,10:200.36363999999998,200,200:0@' $answerValue = $description . '::' . $scoreToString . ':' . $sizeToString . ':0@'; $objAnswer = new Answer($question_id, $courseId); $objAnswer->createAnswer($answerValue, '', '', $globalScore, 1); $objAnswer->save(); $questionObj = Question::read($question_id, $courseId); $questionObj->updateWeighting($globalScore); $questionObj->save(); break; case MATCHING: $globalScore = $score_list[$i][3]; $position = 1; $objAnswer = new Answer($question_id, $courseId); foreach ($answerList as $data) { $option = isset($data[3]) ? $data[3] : ''; $objAnswer->createAnswer($option, 0, '', 0, $position); $position++; } $counter = 1; foreach ($answerList as $data) { $value = isset($data[2]) ? $data[2] : ''; $position++; $objAnswer->createAnswer($value, $counter, ' ', $globalScore, $position); $counter++; } $objAnswer->save(); $questionObj = Question::read($question_id, $courseId); $questionObj->updateWeighting($globalScore); $questionObj->save(); break; } } } $lpFromSession = Session::read('lpobject'); if (isset($lpFromSession)) { if ($debug > 0) { error_log('New LP - SESSION[lpobject] is defined', 0); } $oLP = unserialize($lpFromSession); if (is_object($oLP)) { if ($debug > 0) { error_log('New LP - oLP is object', 0); } if (empty($oLP->cc) or $oLP->cc != api_get_course_id()) { if ($debug > 0) { error_log('New LP - Course has changed, discard lp object', 0); } $oLP = null; Session::erase('oLP'); Session::erase('lpobject'); } else { Session::write('oLP', $oLP); } } } /** @var learnpath $lpFromSession */ $lpFromSession = Session::read('oLP'); if (isset($lpFromSession) && isset($_GET['lp_id'])) { $previous = $lpFromSession->select_previous_item_id(); $parent = 0; // Add a Quiz as Lp Item $lpFromSession->add_item($parent, $previous, TOOL_QUIZ, $quiz_id, $quiz_title, ''); // Redirect to home page for add more content header('location: ../newscorm/lp_controller.php?' . api_get_cidreq() . '&action=add_item&type=step&lp_id=' . intval($_GET['lp_id'])); exit; } else { echo '<script>window.location.href = "' . api_get_path(WEB_CODE_PATH) . 'exercice/admin.php?' . api_get_cidReq() . '&exerciseId=' . $quiz_id . '&session_id=' . api_get_session_id() . '"</script>'; } } }
/** * Shows a question * @param Question $objQuestionTmp * @param bool $only_questions if true only show the questions, no exercise title * @param bool $origin origin i.e = learnpath * @param string $current_item current item from the list of questions * @param bool $show_title * @param bool $freeze * @param array $user_choice * @param bool $show_comment * @param null $exercise_feedback * @param bool $show_answers * @param null $modelType * @param bool $categoryMinusOne * @return bool|null|string */ public function showQuestion(Question $objQuestionTmp, $only_questions = false, $origin = false, $current_item = '', $show_title = true, $freeze = false, $user_choice = array(), $show_comment = false, $exercise_feedback = null, $show_answers = false, $modelType = null, $categoryMinusOne = true) { // Text direction for the current language //$is_ltr_text_direction = api_get_text_direction() != 'rtl'; // Change false to true in the following line to enable answer hinting $debug_mark_answer = $show_answers; //api_is_allowed_to_edit() && false; // Reads question information if (!$objQuestionTmp) { // Question not found return false; } $html = null; $questionId = $objQuestionTmp->id; if ($exercise_feedback != EXERCISE_FEEDBACK_TYPE_END) { $show_comment = false; } $answerType = $objQuestionTmp->selectType(); $pictureName = $objQuestionTmp->selectPicture(); $s = null; $form = new FormValidator('question'); $renderer = $form->defaultRenderer(); $form_template = '{content}'; $renderer->setFormTemplate($form_template); if ($answerType != HOT_SPOT && $answerType != HOT_SPOT_DELINEATION) { // Question is not a hotspot if (!$only_questions) { $questionDescription = $objQuestionTmp->selectDescription(); if ($show_title) { $categoryName = Testcategory::getCategoryNamesForQuestion($objQuestionTmp->id, null, true, $categoryMinusOne); $html .= $categoryName; $html .= Display::div($current_item . '. ' . $objQuestionTmp->selectTitle(), array('class' => 'question_title')); if (!empty($questionDescription)) { $html .= Display::div($questionDescription, array('class' => 'question_description')); } } else { $html .= '<div class="media">'; $html .= '<div class="pull-left">'; $html .= '<div class="media-object">'; $html .= Display::div($current_item, array('class' => 'question_no_title')); $html .= '</div>'; $html .= '</div>'; $html .= '<div class="media-body">'; if (!empty($questionDescription)) { $html .= Display::div($questionDescription, array('class' => 'question_description')); } $html .= '</div>'; $html .= '</div>'; } } if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION)) && $freeze) { return null; } $html .= '<div class="question_options">'; // construction of the Answer object (also gets all answers details) $objAnswerTmp = new Answer($questionId, null, $this); $nbrAnswers = $objAnswerTmp->selectNbrAnswers(); $course_id = api_get_course_int_id(); $quiz_question_options = Question::readQuestionOption($questionId, $course_id); // For "matching" type here, we need something a little bit special // because the match between the suggestions and the answers cannot be // done easily (suggestions and answers are in the same table), so we // have to go through answers first (elems with "correct" value to 0). $select_items = array(); //This will contain the number of answers on the left side. We call them // suggestions here, for the sake of comprehensions, while the ones // on the right side are called answers $num_suggestions = 0; if ($answerType == MATCHING || $answerType == DRAGGABLE) { if ($answerType == DRAGGABLE) { $s .= '<div class="ui-widget ui-helper-clearfix"> <ul class="drag_question ui-helper-reset ui-helper-clearfix">'; } else { $s .= '<div id="drag' . $questionId . '_question" class="drag_question">'; $s .= '<table class="data_table">'; } $j = 1; //iterate through answers $letter = 'A'; //mark letters for each answer $answer_matching = array(); $capital_letter = array(); //for ($answerId=1; $answerId <= $nbrAnswers; $answerId++) { foreach ($objAnswerTmp->answer as $answerId => $answer_item) { $answerCorrect = $objAnswerTmp->isCorrect($answerId); $answer = $objAnswerTmp->selectAnswer($answerId); if ($answerCorrect == 0) { // options (A, B, C, ...) that will be put into the list-box // have the "correct" field set to 0 because they are answer $capital_letter[$j] = $letter; //$answer_matching[$j]=$objAnswerTmp->selectAnswerByAutoId($numAnswer); $answer_matching[$j] = array('id' => $answerId, 'answer' => $answer); $j++; $letter++; } } $i = 1; $select_items[0]['id'] = 0; $select_items[0]['letter'] = '--'; $select_items[0]['answer'] = ''; foreach ($answer_matching as $id => $value) { $select_items[$i]['id'] = $value['id']; $select_items[$i]['letter'] = $capital_letter[$id]; $select_items[$i]['answer'] = $value['answer']; $i++; } $num_suggestions = $nbrAnswers - $j + 1; } elseif ($answerType == FREE_ANSWER) { $content = isset($user_choice[0]) && !empty($user_choice[0]['answer']) ? $user_choice[0]['answer'] : null; $toolBar = 'TestFreeAnswer'; if ($modelType == EXERCISE_MODEL_TYPE_COMMITTEE) { $toolBar = 'TestFreeAnswerStrict'; } $form->addElement('html_editor', "choice[" . $questionId . "]", null, array('id' => "choice[" . $questionId . "]"), array('ToolbarSet' => $toolBar)); $form->setDefaults(array("choice[" . $questionId . "]" => $content)); $s .= $form->return_form(); } elseif ($answerType == ORAL_EXPRESSION) { // Add nanogong if (api_get_setting('enable_nanogong') == 'true') { //@todo pass this as a parameter global $exercise_stat_info, $exerciseId; if (!empty($exercise_stat_info)) { $params = array('exercise_id' => $exercise_stat_info['exe_exo_id'], 'exe_id' => $exercise_stat_info['exe_id'], 'question_id' => $questionId); } else { $params = array('exercise_id' => $exerciseId, 'exe_id' => 'temp_exe', 'question_id' => $questionId); } $nano = new Nanogong($params); $s .= $nano->show_button(); } $form->addElement('html_editor', "choice[" . $questionId . "]", null, array('id' => "choice[" . $questionId . "]"), array('ToolbarSet' => 'TestFreeAnswer')); //$form->setDefaults(array("choice[".$questionId."]" => $content)); $s .= $form->return_form(); } // Now navigate through the possible answers, using the max number of // answers for the question as a limiter $lines_count = 1; // a counter for matching-type answers if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { $header = Display::tag('th', get_lang('Options')); foreach ($objQuestionTmp->options as $item) { $header .= Display::tag('th', $item); } if ($show_comment) { $header .= Display::tag('th', get_lang('Feedback')); } $s .= '<table class="data_table">'; $s .= Display::tag('tr', $header, array('style' => 'text-align:left;')); } if ($show_comment) { if (in_array($answerType, array(MULTIPLE_ANSWER, MULTIPLE_ANSWER_COMBINATION, UNIQUE_ANSWER, UNIQUE_ANSWER_NO_OPTION, GLOBAL_MULTIPLE_ANSWER))) { $header = Display::tag('th', get_lang('Options')); if ($exercise_feedback == EXERCISE_FEEDBACK_TYPE_END) { $header .= Display::tag('th', get_lang('Feedback')); } $s .= '<table class="data_table">'; $s .= Display::tag('tr', $header, array('style' => 'text-align:left;')); } } $matching_correct_answer = 0; $user_choice_array = array(); if (!empty($user_choice)) { foreach ($user_choice as $item) { $user_choice_array[] = $item['answer']; } } foreach ($objAnswerTmp->answer as $answerId => $answer_item) { $answer = $objAnswerTmp->selectAnswer($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId); $comment = $objAnswerTmp->selectComment($answerId); //$numAnswer = $objAnswerTmp->selectAutoId($answerId); $numAnswer = $answerId; $attributes = array(); // Unique answer if (in_array($answerType, array(UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION))) { $input_id = 'choice-' . $questionId . '-' . $answerId; if (isset($user_choice[0]['answer']) && $user_choice[0]['answer'] == $numAnswer) { $attributes = array('id' => $input_id, 'checked' => 1, 'selected' => 1); } else { $attributes = array('id' => $input_id); } if ($debug_mark_answer) { if ($answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $answer = Security::remove_XSS($answer); $s .= Display::input('hidden', 'choice2[' . $questionId . ']', '0'); $answer_input = null; if ($answerType == UNIQUE_ANSWER_IMAGE) { $attributes['style'] = 'display:none'; $answer_input .= '<div id="answer' . $questionId . $numAnswer . '" style="float:left" class="highlight_image_default highlight_image">'; } $answer_input .= '<label class="radio">'; $answer_input .= Display::input('radio', 'choice[' . $questionId . ']', $numAnswer, $attributes); $answer_input .= $answer; $answer_input .= '</label>'; if ($answerType == UNIQUE_ANSWER_IMAGE) { $answer_input .= "</div>"; } if ($show_comment) { $s .= '<tr><td>'; $s .= $answer_input; $s .= '</td>'; $s .= '<td>'; $s .= $comment; $s .= '</td>'; $s .= '</tr>'; } else { $s .= $answer_input; } } elseif (in_array($answerType, array(MULTIPLE_ANSWER, MULTIPLE_ANSWER_TRUE_FALSE, GLOBAL_MULTIPLE_ANSWER))) { $input_id = 'choice-' . $questionId . '-' . $answerId; $answer = Security::remove_XSS($answer); if (in_array($numAnswer, $user_choice_array)) { $attributes = array('id' => $input_id, 'checked' => 1, 'selected' => 1); } else { $attributes = array('id' => $input_id); } if ($debug_mark_answer) { if ($answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } if ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { $s .= '<input type="hidden" name="choice2[' . $questionId . ']" value="0" />'; $answer_input = '<label class="checkbox">'; $answer_input .= Display::input('checkbox', 'choice[' . $questionId . '][' . $numAnswer . ']', $numAnswer, $attributes); $answer_input .= $answer; $answer_input .= '</label>'; if ($show_comment) { $s .= '<tr><td>'; $s .= $answer_input; $s .= '</td>'; $s .= '<td>'; $s .= $comment; $s .= '</td>'; $s .= '</tr>'; } else { $s .= $answer_input; } } elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE) { $my_choice = array(); if (!empty($user_choice_array)) { foreach ($user_choice_array as $item) { $item = explode(':', $item); $my_choice[$item[0]] = $item[1]; } } $s .= '<tr>'; $s .= Display::tag('td', $answer); if (!empty($quiz_question_options)) { foreach ($quiz_question_options as $id => $item) { $id = $item['iid']; if (isset($my_choice[$numAnswer]) && $id == $my_choice[$numAnswer]) { $attributes = array('checked' => 1, 'selected' => 1); } else { $attributes = array(); } if ($debug_mark_answer) { if ($id == $answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $s .= Display::tag('td', Display::input('radio', 'choice[' . $questionId . '][' . $numAnswer . ']', $id, $attributes), array('style' => '')); } } if ($show_comment) { $s .= '<td>'; $s .= $comment; $s .= '</td>'; } $s .= '</tr>'; } } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION) { // multiple answers $input_id = 'choice-' . $questionId . '-' . $answerId; if (in_array($numAnswer, $user_choice_array)) { $attributes = array('id' => $input_id, 'checked' => 1, 'selected' => 1); } else { $attributes = array('id' => $input_id); } if ($debug_mark_answer) { if ($answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $answer = Security::remove_XSS($answer); $answer_input = '<input type="hidden" name="choice2[' . $questionId . ']" value="0" />'; $answer_input .= '<label class="checkbox">'; $answer_input .= Display::input('checkbox', 'choice[' . $questionId . '][' . $numAnswer . ']', 1, $attributes); $answer_input .= $answer; $answer_input .= '</label>'; if ($show_comment) { $s .= '<tr>'; $s .= '<td>'; $s .= $answer_input; $s .= '</td>'; $s .= '<td>'; $s .= $comment; $s .= '</td>'; $s .= '</tr>'; } else { $s .= $answer_input; } } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { $s .= '<input type="hidden" name="choice2[' . $questionId . ']" value="0" />'; $my_choice = array(); if (!empty($user_choice_array)) { foreach ($user_choice_array as $item) { $item = explode(':', $item); $my_choice[$item[0]] = $item[1]; } } $answer = Security::remove_XSS($answer); $s .= '<tr>'; $s .= Display::tag('td', $answer); foreach ($objQuestionTmp->options as $key => $item) { if (isset($my_choice[$numAnswer]) && $key == $my_choice[$numAnswer]) { $attributes = array('checked' => 1, 'selected' => 1); } else { $attributes = array(); } if ($debug_mark_answer) { if ($key == $answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $s .= Display::tag('td', Display::input('radio', 'choice[' . $questionId . '][' . $numAnswer . ']', $key, $attributes)); } if ($show_comment) { $s .= '<td>'; $s .= $comment; $s .= '</td>'; } $s .= '</tr>'; } elseif ($answerType == FILL_IN_BLANKS) { list($answer) = explode('::', $answer); //Correct answer api_preg_match_all('/\\[[^]]+\\]/', $answer, $correct_answer_list); //Student's answezr if (isset($user_choice[0]['answer'])) { api_preg_match_all('/\\[[^]]+\\]/', $user_choice[0]['answer'], $student_answer_list); $student_answer_list = $student_answer_list[0]; } //If debug if ($debug_mark_answer) { $student_answer_list = $correct_answer_list[0]; } if (!empty($correct_answer_list) && !empty($student_answer_list)) { $correct_answer_list = $correct_answer_list[0]; $i = 0; foreach ($correct_answer_list as $correct_item) { $value = null; if (isset($student_answer_list[$i]) && !empty($student_answer_list[$i])) { //Cleaning student answer list $value = strip_tags($student_answer_list[$i]); $value = api_substr($value, 1, api_strlen($value) - 2); $value = explode('/', $value); if (!empty($value[0])) { $value = str_replace(' ', '', trim($value[0])); } $correct_item = preg_quote($correct_item); $correct_item = api_preg_replace('|/|', '\\/', $correct_item); // to prevent error if there is a / in the text to find $answer = api_preg_replace('/' . $correct_item . '/', Display::input('text', "choice[{$questionId}][]", $value), $answer, 1); } $i++; } } else { $answer = api_preg_replace('/\\[[^]]+\\]/', Display::input('text', "choice[{$questionId}][]", '', $attributes), $answer); } $s .= $answer; } elseif ($answerType == MATCHING) { // matching type, showing suggestions and answers // TODO: replace $answerId by $numAnswer if ($lines_count == 1) { $s .= $objAnswerTmp->getJs(); } if ($answerCorrect != 0) { // only show elements to be answered (not the contents of // the select boxes, who are correct = 0) $s .= '<tr><td width="45%">'; $parsed_answer = $answer; $windowId = $questionId . '_' . $lines_count; //left part questions $s .= ' <div id="window_' . $windowId . '" class="window window_left_question window' . $questionId . '_question"> <b>' . $lines_count . '</b>. ' . $parsed_answer . ' </div> </td>'; // middle part (matches selects) $s .= '<td width="10%" align="center"> '; $s .= '<div style="display:block">'; $s .= '<select id="window_' . $windowId . '_select" name="choice[' . $questionId . '][' . $numAnswer . ']">'; $selectedValue = 0; // fills the list-box $item = 0; foreach ($select_items as $val) { // set $debug_mark_answer to true at public static function start to // show the correct answer with a suffix '-x' $selected = ''; if ($debug_mark_answer) { if ($val['id'] == $answerCorrect) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } } if (isset($user_choice[$matching_correct_answer]) && $val['id'] == $user_choice[$matching_correct_answer]['answer']) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } //$s .= '<option value="'.$val['id'].'" '.$selected.'>'.$val['letter'].'</option>'; $s .= '<option value="' . $item . '" ' . $selected . '>' . $val['letter'] . '</option>'; $item++; } if (!empty($answerCorrect) && !empty($selectedValue)) { $s .= '<script> jsPlumb.ready(function() { jsPlumb.connect({ source: "window_' . $windowId . '", target: "window_' . $questionId . '_' . $selectedValue . '_answer", endpoint:["Blank", { radius:15 }], anchor:["RightMiddle","LeftMiddle"], paintStyle:{ strokeStyle:"#8a8888" , lineWidth:8 }, connector: [connectorType, { curviness: curvinessValue } ], }) }); </script>'; } $s .= '</select></div></td>'; $s .= '<td width="45%" valign="top" >'; if (isset($select_items[$lines_count])) { $s .= '<div id="window_' . $windowId . '_answer" class="window window_right_question"> <b>' . $select_items[$lines_count]['letter'] . '.</b> ' . $select_items[$lines_count]['answer'] . ' </div>'; } else { $s .= ' '; } $s .= '</td>'; $s .= '</tr>'; $lines_count++; //if the left side of the "matching" has been completely // shown but the right side still has values to show... if ($lines_count - 1 == $num_suggestions) { // if it remains answers to shown at the right side while (isset($select_items[$lines_count])) { $s .= '<tr> <td colspan="2"></td> <td valign="top">'; $s .= '<b>' . $select_items[$lines_count]['letter'] . '.</b>'; $s .= $select_items[$lines_count]['answer']; $s .= "</td>\n </tr>"; $lines_count++; } // end while() } // end if() $matching_correct_answer++; } } elseif ($answerType == DRAGGABLE) { // matching type, showing suggestions and answers // TODO: replace $answerId by $numAnswer if ($answerCorrect != 0) { // only show elements to be answered (not the contents of // the select boxes, who are correct = 0) $s .= '<td>'; $parsed_answer = $answer; $windowId = $questionId . '_' . $numAnswer; //67_293 - 67_294 //left part questions $s .= '<li class="ui-state-default" id="' . $windowId . '">'; $s .= ' <div id="window_' . $windowId . '" class="window' . $questionId . '_question_draggable question_draggable"> ' . $parsed_answer . ' </div>'; $s .= '<div style="display:none">'; $s .= '<select id="window_' . $windowId . '_select" name="choice[' . $questionId . '][' . $numAnswer . ']" class="select_option">'; $selectedValue = 0; // fills the list-box $item = 0; foreach ($select_items as $val) { // set $debug_mark_answer to true at function start to // show the correct answer with a suffix '-x' $selected = ''; if ($debug_mark_answer) { if ($val['id'] == $answerCorrect) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } } if (isset($user_choice[$matching_correct_answer]) && $val['id'] == $user_choice[$matching_correct_answer]['answer']) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } //$s .= '<option value="'.$val['id'].'" '.$selected.'>'.$val['letter'].'</option>'; $s .= '<option value="' . $item . '" ' . $selected . '>' . $val['letter'] . '</option>'; $item++; } $s .= '</select>'; if (!empty($answerCorrect) && !empty($selectedValue)) { $s .= '<script> $(function() { deleteItem($("#' . $questionId . '_' . $selectedValue . '"), $("#drop_' . $windowId . '")); }); </script>'; } if (isset($select_items[$lines_count])) { $s .= '<div id="window_' . $windowId . '_answer" class=""> <b>' . $select_items[$lines_count]['letter'] . '.</b> ' . $select_items[$lines_count]['answer'] . ' </div>'; } else { $s .= ' '; } $lines_count++; //if the left side of the "matching" has been completely // shown but the right side still has values to show... if ($lines_count - 1 == $num_suggestions) { // if it remains answers to shown at the right side while (isset($select_items[$lines_count])) { $s .= '<b>' . $select_items[$lines_count]['letter'] . '.</b>'; $s .= $select_items[$lines_count]['answer']; $lines_count++; } } $s .= '</div>'; $matching_correct_answer++; $s .= '</li>'; } } } // end for() if ($show_comment) { $s .= '</table>'; } else { if ($answerType == MATCHING || $answerType == UNIQUE_ANSWER_NO_OPTION || $answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { $s .= '</table>'; } } if ($answerType == DRAGGABLE) { $s .= '</ul><div class="clear"></div>'; $counterAnswer = 1; foreach ($objAnswerTmp->answer as $answerId => $answer_item) { $answerCorrect = $objAnswerTmp->isCorrect($answerId); $windowId = $questionId . '_' . $counterAnswer; if ($answerCorrect == 0) { $s .= '<div id="drop_' . $windowId . '" class="droppable ui-state-default">' . $counterAnswer . '</div>'; $counterAnswer++; } } } if ($answerType == MATCHING) { $s .= '</div>'; } $s .= '</div>'; // destruction of the Answer object unset($objAnswerTmp); // destruction of the Question object unset($objQuestionTmp); $html .= $s; return $html; } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) { // Question is a HOT_SPOT //checking document/images visibility if (api_is_platform_admin() || api_is_course_admin()) { $course = api_get_course_info(); $doc_id = DocumentManager::get_document_id($course, '/images/' . $pictureName); if (is_numeric($doc_id)) { $images_folder_visibility = api_get_item_visibility($course, 'document', $doc_id, api_get_session_id()); if (!$images_folder_visibility) { //This message is shown only to the course/platform admin if the image is set to visibility = false Display::display_warning_message(get_lang('ChangeTheVisibilityOfTheCurrentImage')); } } } $questionName = $objQuestionTmp->selectTitle(); $questionDescription = $objQuestionTmp->selectDescription(); if ($freeze) { $s .= Display::img($objQuestionTmp->selectPicturePath()); $html .= $s; return $html; } // Get the answers, make a list $objAnswerTmp = new Answer($questionId); // get answers of hotpost $answers_hotspot = array(); foreach ($objAnswerTmp->answer as $answerId => $answer_item) { //$answers = $objAnswerTmp->selectAnswerByAutoId($objAnswerTmp->selectAutoId($answerId)); $answers_hotspot[$answerId] = $objAnswerTmp->selectAnswer($answerId); } // display answers of hotpost order by id $answer_list = '<div style="padding: 10px; margin-left: 0px; border: 1px solid #A4A4A4; height: 408px; width: 200px;"><b>' . get_lang('HotspotZones') . '</b><dl>'; if (!empty($answers_hotspot)) { ksort($answers_hotspot); foreach ($answers_hotspot as $key => $value) { $answer_list .= '<dt>' . $key . '.- ' . $value . '</dt><br />'; } } $answer_list .= '</dl></div>'; if ($answerType == HOT_SPOT_DELINEATION) { $answer_list = ''; $swf_file = 'hotspot_delineation_user'; $swf_height = 405; } else { $swf_file = 'hotspot_user'; $swf_height = 436; } if (!$only_questions) { if ($show_title) { $html .= Testcategory::getCategoryNamesForQuestion($objQuestionTmp->id); $html .= '<div class="question_title">' . $current_item . '. ' . $questionName . '</div>'; $html .= $questionDescription; } else { $html .= '<div class="media">'; $html .= '<div class="pull-left">'; $html .= '<div class="media-object">'; $html .= Display::div($current_item . '. ', array('class' => 'question_no_title')); $html .= '</div>'; $html .= '</div>'; $html .= '<div class="media-body">'; if (!empty($questionDescription)) { $html .= Display::div($questionDescription, array('class' => 'question_description')); } $html .= '</div>'; $html .= '</div>'; } //@todo I need to the get the feedback type $html .= '<input type="hidden" name="hidden_hotspot_id" value="' . $questionId . '" />'; $html .= '<table class="exercise_questions"> <tr> <td valign="top" colspan="2">'; $html .= '</td></tr>'; } $canClick = isset($_GET['editQuestion']) ? '0' : (isset($_GET['modifyAnswers']) ? '0' : '1'); $s .= ' <script type="text/javascript" src="../plugin/hotspot/JavaScriptFlashGateway.js"></script> <script src="../plugin/hotspot/hotspot.js" type="text/javascript" ></script> <script type="text/javascript"> <!-- // Globals // Major version of Flash required var requiredMajorVersion = 7; // Minor version of Flash required var requiredMinorVersion = 0; // Minor version of Flash required var requiredRevision = 0; // the version of javascript supported var jsVersion = 1.0; // --> </script> <script language="VBScript" type="text/vbscript"> <!-- // Visual basic helper required to detect Flash Player ActiveX control version information Function VBGetSwfVer(i) on error resume next Dim swControl, swVersion swVersion = 0 set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i)) if (IsObject(swControl)) then swVersion = swControl.GetVariable("$version") end if VBGetSwfVer = swVersion End Function // --> </script> <script language="JavaScript1.1" type="text/javascript"> <!-- // Detect Client Browser type var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; jsVersion = 1.1; // JavaScript helper required to detect Flash Player PlugIn version information function JSGetSwfVer(i) { // NS/Opera version >= 3 check for Flash plugin in plugin array if (navigator.plugins != null && navigator.plugins.length > 0) { if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; descArray = flashDescription.split(" "); tempArrayMajor = descArray[2].split("."); versionMajor = tempArrayMajor[0]; versionMinor = tempArrayMajor[1]; if ( descArray[3] != "" ) { tempArrayMinor = descArray[3].split("r"); } else { tempArrayMinor = descArray[4].split("r"); } versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0; flashVer = versionMajor + "." + versionMinor + "." + versionRevision; } else { flashVer = -1; } } // MSN/WebTV 2.6 supports Flash 4 else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; // WebTV 2.5 supports Flash 3 else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; // older WebTV supports Flash 2 else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; // Can\'t detect in all other cases else { flashVer = -1; } return flashVer; } // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) { reqVer = parseFloat(reqMajorVer + "." + reqRevision); // loop backwards through the versions until we find the newest version for (i=25;i>0;i--) { if (isIE && isWin && !isOpera) { versionStr = VBGetSwfVer(i); } else { versionStr = JSGetSwfVer(i); } if (versionStr == -1 ) { return false; } else if (versionStr != 0) { if(isIE && isWin && !isOpera) { tempArray = versionStr.split(" "); tempString = tempArray[1]; versionArray = tempString .split(","); } else { versionArray = versionStr.split("."); } versionMajor = versionArray[0]; versionMinor = versionArray[1]; versionRevision = versionArray[2]; versionString = versionMajor + "." + versionRevision; // 7.0r24 == 7.24 versionNum = parseFloat(versionString); // is the major.revision >= requested major.revision AND the minor version >= requested minor if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) { return true; } else { return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false ); } } } } // --> </script>'; $s .= '<tr><td valign="top" colspan="2" width="520"><table><tr><td width="520"> <script> // Version check based upon the values entered above in "Globals" var hasReqestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision); // Check to see if the version meets the requirements for playback if (hasReqestedVersion) { // if we\'ve detected an acceptable version var oeTags = \'<object type="application/x-shockwave-flash" data="../plugin/hotspot/' . $swf_file . '.swf?modifyAnswers=' . $questionId . '&canClick:' . $canClick . '" width="600" height="' . $swf_height . '">\' + \'<param name="wmode" value="transparent">\' + \'<param name="movie" value="../plugin/hotspot/' . $swf_file . '.swf?modifyAnswers=' . $questionId . '&canClick:' . $canClick . '" />\' + \'<\\/object>\'; document.write(oeTags); // embed the Flash Content SWF when all tests are passed } else { // flash is too old or we can\'t detect the plugin var alternateContent = "Error<br \\/>" + "Hotspots requires Macromedia Flash 7.<br \\/>" + "<a href=\\"http://www.macromedia.com/go/getflash/\\">Get Flash<\\/a>"; document.write(alternateContent); // insert non-flash content } </script> </td> <td valign="top" align="left">' . $answer_list . '</td></tr> </table> </td></tr>'; $html .= $s; $html .= '</table>'; return $html; } return $nbrAnswers; }
/** * Recycle tests categories */ public function recycle_test_category() { if (isset($this->course->resources[RESOURCE_TEST_CATEGORY])) { foreach ($this->course->resources[RESOURCE_TEST_CATEGORY] as $tab_test_cat) { $obj_cat = new Testcategory($tab_test_cat->source_id); $obj_cat->removeCategory(); } } }
$delete_link = Display::tag('div', $delete_link, array('style' => 'float:left; padding:0px; margin:0px')); $actions = Display::tag('div', $edit_link . $clone_link . $delete_link, array('class' => 'edition', 'style' => 'width:100px; right:10px; margin-top: 0px; position: absolute; top: 10%;')); $title = Security::remove_XSS($objQuestionTmp->selectTitle()); $move = Display::return_icon('all_directions.png', get_lang('Move'), array('class' => 'moved', 'style' => 'margin-bottom:-0.5em;')); // Question name $questionName = Display::tag('div', '<a href="#" title = "' . $title . '">' . $move . ' ' . Text::cut($title, 42) . '</a>', array('style' => $styleQuestion)); // Question type. list($typeImg, $typeExpl) = $objQuestionTmp->get_type_icon_html(); $question_media = null; if (!empty($objQuestionTmp->parent_id)) { $objQuestionMedia = Question::read($objQuestionTmp->parent_id); $question_media = ' ' . Question::getMediaLabel($objQuestionMedia->question); } $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), ICON_SIZE_MEDIUM), array('style' => $styleType)); // Question category. $category_labels = Testcategory::return_category_labels($objQuestionTmp->category_list, $category_list); if (empty($category_labels)) { $category_labels = ""; } $questionCategory = Display::tag('div', '<a href="#" style="padding:0px; margin:0px;">' . $category_labels . $question_media . '</a>', array('style' => $styleCat)); // Question level. $txtQuestionLevel = $objQuestionTmp->level; if (empty($objQuestionTmp->level)) { $txtQuestionLevel = '-'; } $questionLevel = Display::tag('div', $txtQuestionLevel, array('style' => $styleLevel)); // Question score $questionScore = Display::tag('div', $objQuestionTmp->selectWeighting(), array('style' => $styleScore)); echo '<div id="question_id_list_' . $id . '" >'; echo '<div class="header_operations">'; echo $questionName;
/** * Display the exercise results * @param Exercise $objExercise * @param int $exe_id * @param bool $save_user_result save users results (true) or just show the results (false) */ function display_question_list_by_attempt($objExercise, $exe_id, $save_user_result = false) { global $origin; // Getting attempt info $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exe_id); // Getting question list $question_list = array(); if (!empty($exercise_stat_info['data_tracking'])) { $question_list = explode(',', $exercise_stat_info['data_tracking']); } else { // Try getting the question list only if save result is off if ($save_user_result == false) { $question_list = $objExercise->get_validated_question_list(); } } $counter = 1; $total_score = $total_weight = 0; $exercise_content = null; // Hide results $show_results = false; $show_only_score = false; if ($objExercise->results_disabled == RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS) { $show_results = true; } if (in_array($objExercise->results_disabled, array(RESULT_DISABLE_SHOW_SCORE_ONLY, RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES))) { $show_only_score = true; } // Not display expected answer, but score, and feedback $show_all_but_expected_answer = false; if ($objExercise->results_disabled == RESULT_DISABLE_SHOW_SCORE_ONLY && $objExercise->feedback_type == EXERCISE_FEEDBACK_TYPE_END) { $show_all_but_expected_answer = true; $show_results = true; $show_only_score = false; } if ($show_results || $show_only_score) { $user_info = api_get_user_info($exercise_stat_info['exe_user_id']); //Shows exercise header echo $objExercise->show_exercise_result_header($user_info, api_convert_and_format_date($exercise_stat_info['start_date'], DATE_TIME_FORMAT_LONG), $exercise_stat_info['duration']); } // Display text when test is finished #4074 and for LP #4227 $end_of_message = $objExercise->selectTextWhenFinished(); if (!empty($end_of_message)) { Display::display_normal_message($end_of_message, false); echo "<div class='clear'> </div>"; } $question_list_answers = array(); $media_list = array(); $category_list = array(); // Loop over all question to show results for each of them, one by one if (!empty($question_list)) { foreach ($question_list as $questionId) { // creates a temporary Question object $objQuestionTmp = Question::read($questionId); // This variable came from exercise_submit_modal.php ob_start(); // We're inside *one* question. Go through each possible answer for this question $result = $objExercise->manage_answer($exercise_stat_info['exe_id'], $questionId, null, 'exercise_result', array(), $save_user_result, true, $show_results, $objExercise->selectPropagateNeg(), array()); if (empty($result)) { continue; } // In case of global score, make sure the calculated total score is integer /*if (!is_int($result['score'])) { $result['score'] = round($result['score']); }*/ $total_score += $result['score']; $total_weight += $result['weight']; $question_list_answers[] = array('question' => $result['open_question'], 'answer' => $result['open_answer'], 'answer_type' => $result['answer_type']); $my_total_score = $result['score']; $my_total_weight = $result['weight']; // Category report $category_was_added_for_this_test = false; if (isset($objQuestionTmp->category) && !empty($objQuestionTmp->category)) { $category_list[$objQuestionTmp->category]['score'] += $my_total_score; $category_list[$objQuestionTmp->category]['total'] += $my_total_weight; $category_was_added_for_this_test = true; } if (isset($objQuestionTmp->category_list) && !empty($objQuestionTmp->category_list)) { foreach ($objQuestionTmp->category_list as $category_id) { $category_list[$category_id]['score'] += $my_total_score; $category_list[$category_id]['total'] += $my_total_weight; $category_was_added_for_this_test = true; } } // No category for this question! if ($category_was_added_for_this_test == false) { if (!isset($category_list['none']['score'])) { $category_list['none']['score'] = 0; } if (!isset($category_list['none']['total'])) { $category_list['none']['total'] = 0; } $category_list['none']['score'] += $my_total_score; $category_list['none']['total'] += $my_total_weight; } if ($objExercise->selectPropagateNeg() == 0 && $my_total_score < 0) { $my_total_score = 0; } $comnt = null; if ($show_results) { $comnt = get_comments($exe_id, $questionId); if (!empty($comnt)) { echo '<b>' . get_lang('Feedback') . '</b>'; echo '<div id="question_feedback">' . $comnt . '</div>'; } } if ($show_results) { $score = array('result' => get_lang('Score') . " : " . show_score($my_total_score, $my_total_weight, false, true), 'pass' => $my_total_score >= $my_total_weight ? true : false, 'score' => $my_total_score, 'weight' => $my_total_weight, 'comments' => $comnt); } else { $score = array(); } $contents = ob_get_clean(); $question_content = '<div class="question_row">'; if ($show_results) { $show_media = false; /*if ($objQuestionTmp->parent_id != 0 && !in_array($objQuestionTmp->parent_id, $media_list)) { $show_media = true; $media_list[] = $objQuestionTmp->parent_id; }*/ //Shows question title an description $question_content .= $objQuestionTmp->return_header(null, $counter, $score); } $counter++; $question_content .= $contents; $question_content .= '</div>'; $exercise_content .= $question_content; } // end foreach() block that loops over all questions } $total_score_text = null; if ($origin != 'learnpath') { if ($show_results || $show_only_score) { $total_score_text .= '<div class="question_row">'; $total_score_text .= get_question_ribbon($objExercise, $total_score, $total_weight, true); $total_score_text .= '</div>'; } } if (!empty($category_list) && ($show_results || $show_only_score)) { //Adding total $category_list['total'] = array('score' => $total_score, 'total' => $total_weight); echo Testcategory::get_stats_table_by_attempt($objExercise->id, $category_list); } if ($show_all_but_expected_answer) { $exercise_content .= "<div class='normal-message'>" . get_lang("ExerciseWithFeedbackWithoutCorrectionComment") . "</div>"; } // Remove audio auto play from questions on results page - refs BT#7939 $exercise_content = preg_replace('/autoplay[\\=\\".+\\"]+/', '', $exercise_content); echo $total_score_text; echo $exercise_content; if (!$show_only_score) { echo $total_score_text; } if ($save_user_result) { // Tracking of results $learnpath_id = $exercise_stat_info['orig_lp_id']; $learnpath_item_id = $exercise_stat_info['orig_lp_item_id']; $learnpath_item_view_id = $exercise_stat_info['orig_lp_item_view_id']; if (api_is_allowed_to_session_edit()) { update_event_exercice($exercise_stat_info['exe_id'], $objExercise->selectId(), $total_score, $total_weight, api_get_session_id(), $learnpath_id, $learnpath_item_id, $learnpath_item_view_id, $exercise_stat_info['exe_duration'], $question_list, '', array()); } // Send notification .. if (!api_is_allowed_to_edit(null, true)) { if (api_get_course_setting('email_alert_manager_on_new_quiz') == 1) { $objExercise->send_mail_notification_for_exam($question_list_answers, $origin, $exe_id); } $objExercise->send_notification_for_open_questions($question_list_answers, $origin, $exe_id); $objExercise->send_notification_for_oral_questions($question_list_answers, $origin, $exe_id); } } }
$question = Question::read($questionId); if (empty($mediaId)) { echo 0; break; } $categoryId = $question->allQuestionWithMediaHaveTheSameCategory($exerciseId, $mediaId, null, null, true); if (!empty($categoryId)) { $category = new Testcategory($categoryId); echo json_encode(array('title' => $category->title, 'value' => $category->id)); } else { echo -1; } break; case 'exercise_category_exists': $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : 'simple'; $category = new Testcategory(null, null, null, null, $type); $category->getCategory($_REQUEST['id']); if (empty($category->id)) { echo 0; } else { $courseId = api_get_course_int_id(); if (isset($courseId)) { // Global if ($category->c_id == 0) { echo 1; exit; } else { // Local if ($category->c_id == $courseId) { echo 1; exit;
function display_categories($type = 'simple') { $options = array('decorate' => true, 'rootOpen' => '<ul>', 'rootClose' => '</ul>', 'childOpen' => '<li>', 'childClose' => '</li>', 'nodeDecorator' => function ($row) use($type) { $category_id = $row['iid']; $courseId = $row['cId']; $tmpobj = new Testcategory($category_id); $nb_question = $tmpobj->getCategoryQuestionsNumber(); $nb_question_label = $nb_question == 1 ? $nb_question . ' ' . get_lang('Question') : $nb_question . ' ' . get_lang('Questions'); $nb_question_label = Display::label($nb_question_label, 'info'); $actions = null; if ($courseId == 0 && $type == 'simple') { $actions .= Display::return_icon('edit_na.png', get_lang('Edit'), array(), ICON_SIZE_SMALL); } else { $actions .= '<a href="' . api_get_self() . '?action=editcategory&category_id=' . $category_id . '&type=' . $type . '">' . Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>'; } if ($nb_question > 0 && $courseId == 0 && $type == 'simple') { $actions .= '<a href="javascript:void(0)" onclick="alert(\'' . protectJSDialogQuote(get_lang('CannotDeleteCategory')) . '\')">'; $actions .= Display::return_icon('delete_na.png', get_lang('CannotDeleteCategory'), array(), ICON_SIZE_SMALL); $actions .= '</a>'; } else { $rowname = protectJSDialogQuote($row['title']); $actions .= ' <a href="' . api_get_self() . '?action=deletecategory&category_id=' . $category_id . '&type=' . $type . '"'; $actions .= 'onclick="return confirmDelete(\'' . protectJSDialogQuote(get_lang('DeleteCategoryAreYouSure') . '[' . $rowname) . '] ?\', \'id_cat' . $category_id . '\');">'; $actions .= Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>'; } return $row['title'] . ' ' . $nb_question_label . ' ' . $actions; }); // @todo put this in a function $repo = Database::getManager()->getRepository('ChamiloCoreBundle:CQuizCategory'); $query = null; if ($type == 'global') { $query = Database::getManager()->createQueryBuilder()->select('node')->from('ChamiloCoreBundle:CQuizCategory', 'node')->where('node.cId = 0')->orderBy('node.root, node.lft', 'ASC')->getQuery(); } else { $query = Database::getManager()->createQueryBuilder()->select('node')->from('ChamiloCoreBundle:CQuizCategory', 'node')->where('node.cId = :courseId')->orderBy('node.root, node.lft', 'ASC')->setParameter('courseId', api_get_course_int_id())->getQuery(); } $htmlTree = $repo->buildTree($query->getArrayResult(), $options); /* $htmlTree = $repo->childrenHierarchy( null, //starting from root nodes false, //load all children, not only direct $options );*/ echo $htmlTree; return true; }
/** * Build the Quiz-Questions */ function build_quiz_questions($course_code = null) { $course_info = api_get_course_info($course_code); $course_id = $course_info['real_id']; $table_qui = Database::get_course_table(TABLE_QUIZ_TEST); $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION); $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER); // Building normal tests. $sql = "SELECT * FROM {$table_que} WHERE c_id = {$course_id} "; $db_result = Database::query($sql); while ($obj = Database::fetch_object($db_result)) { $categories = Testcategory::getCategoryForQuestionWithCategoryData($obj->iid, $course_id, true); $parent_info = array(); if (isset($obj->parent_id) && !empty($obj->parent_id)) { $parent_info = (array) Question::read($obj->parent_id, $course_id); } $question = new QuizQuestion($obj->iid, $obj->question, $obj->description, $obj->ponderation, $obj->type, $obj->position, $obj->picture, $obj->level, $obj->extra, $parent_info, $categories); $sql = 'SELECT * FROM ' . $table_ans . ' WHERE question_id = ' . $obj->iid; $db_result2 = Database::query($sql); while ($obj2 = Database::fetch_object($db_result2)) { $question->add_answer($obj2->iid, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); if ($obj->type == MULTIPLE_ANSWER_TRUE_FALSE) { $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); $sql = 'SELECT * FROM ' . $table_options . ' WHERE c_id = ' . $course_id . ' AND question_id = ' . $obj->iid; $db_result3 = Database::query($sql); while ($obj3 = Database::fetch_object($db_result3)) { $question_option = new QuizQuestionOption($obj3); $question->add_option($question_option); } } } $this->course->add_resource($question); } // Building a fictional test for collecting orphan questions. $build_orphan_questions = !empty($_POST['recycle_option']); // When a course is emptied this option should be activated (true). //1st union gets the orphan questions from deleted exercises //2nd union gets the orphan questions from question that were deleted in a exercise. $sql = " (\n SELECT q.* FROM {$table_que} q INNER JOIN {$table_rel} r\n ON (q.c_id = r.c_id AND q.iid = r.question_id)\n INNER JOIN {$table_qui} ex\n ON (ex.iid = r.exercice_id AND ex.c_id = r.c_id )\n WHERE ex.c_id = {$course_id} AND ex.active = '-1'\n )\n UNION\n (\n SELECT q.* FROM {$table_que} q left\n OUTER JOIN {$table_rel} r\n ON (q.c_id = r.c_id AND q.iid = r.question_id)\n WHERE q.c_id = {$course_id} AND r.question_id is null\n )\n UNION\n (\n SELECT q.* FROM {$table_que} q\n INNER JOIN {$table_rel} r\n ON (q.c_id = r.c_id AND q.iid = r.question_id)\n WHERE r.c_id = {$course_id} AND (r.exercice_id = '-1' OR r.exercice_id = '0')\n )\n "; $db_result = Database::query($sql); if (Database::num_rows($db_result) > 0) { $build_orphan_questions = true; $orphanQuestionIds = array(); while ($obj = Database::fetch_object($db_result)) { $categories = Testcategory::getCategoryForQuestionWithCategoryData($obj->iid, $course_id, true); $parent_info = array(); if (isset($obj->parent_id) && !empty($obj->parent_id)) { $parent_info = (array) Question::read($obj->parent_id, $course_id); } //Avoid adding the same question twice if (!isset($this->course->resources[$obj->iid])) { $question = new QuizQuestion($obj->iid, $obj->question, $obj->description, $obj->ponderation, $obj->type, $obj->position, $obj->picture, $obj->level, $obj->extra, $parent_info, $categories); $sql = "SELECT * FROM {$table_ans} WHERE c_id = {$course_id} AND question_id = " . $obj->iid; $db_result2 = Database::query($sql); if (Database::num_rows($db_result2)) { while ($obj2 = Database::fetch_object($db_result2)) { $question->add_answer($obj2->iid, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); } $orphanQuestionIds[] = $obj->iid; } $this->course->add_resource($question); } } } if ($build_orphan_questions) { $obj = array('iid' => -1, 'title' => get_lang('OrphanQuestions', ''), 'type' => 2); $newQuiz = new Quiz((object) $obj); if (!empty($orphanQuestionIds)) { foreach ($orphanQuestionIds as $index => $orphanId) { $order = $index + 1; $newQuiz->add_question($orphanId, $order); } } $this->course->add_resource($newQuiz); } }
function get_question_category_for_question($course_id, $question_id) { global $all_category_list; $objQuestionTmp = Question::read($question_id, $course_id); return Testcategory::return_category_labels($objQuestionTmp->category_list, $all_category_list); }
/** * @Route("/score-attempt/{exeId}/jury/{juryId}") * @Method({"GET"}) */ public function scoreAttemptAction($exeId, $juryId) { $userId = $this->getUser()->getUserId(); $trackExercise = \ExerciseLib::get_exercise_track_exercise_info($exeId); if (empty($trackExercise)) { $this->createNotFoundException(); } /** @var \Chamilo\CoreBundle\Entity\Jury $jury */ $jury = $this->getRepository()->find($juryId); if (empty($jury)) { $this->createNotFoundException('Jury does not exists'); } if ($jury->getExerciseId() != $trackExercise['exe_exo_id']) { $this->createNotFoundException('Exercise attempt is not related with this jury.'); } $members = $jury->getMembers(); $criteria = Criteria::create()->where(Criteria::expr()->eq("userId", $userId))->setFirstResult(0)->setMaxResults(1); /** @var JuryMembers $member */ $member = $members->matching($criteria)->first(); if (empty($member)) { $this->createNotFoundException('You are not part of the jury.'); } $students = $member->getStudents(); $criteria = Criteria::create()->where(Criteria::expr()->eq("userId", $trackExercise['exe_user_id']))->setFirstResult(0)->setMaxResults(1); /** @var JuryMembers $member */ $student = $students->matching($criteria)->first(); if (empty($student)) { $this->createNotFoundException('You are not assigned to this user.'); } // Setting member only for president. if ($this->isGranted('ROLE_JURY_PRESIDENT')) { // Relating user with president if ($member) { $this->getManager()->getRepository('Chamilo\\CoreBundle\\Entity\\JuryMembers')->assignUserToJuryMember($trackExercise['exe_user_id'], $member->getId()); } } $questionScoreTypeModel = array(); $criteria = array('exeId' => $exeId, 'juryUserId' => $userId); $trackJury = $this->getManager()->getRepository('Chamilo\\CoreBundle\\Entity\\TrackAttemptJury')->findBy($criteria); if ($trackJury) { $this->get('session')->getFlashBag()->add('info', "You already review this exercise attempt."); /** @var TrackAttemptJury $track */ foreach ($trackJury as $track) { $questionScoreTypeModel[$track->getQuestionId()] = $track->getQuestionScoreNameId(); } } $questionList = explode(',', $trackExercise['data_tracking']); $exerciseResult = \ExerciseLib::getExerciseResult($trackExercise); $counter = 1; $objExercise = new \Exercise($trackExercise['c_id']); $objExercise->read($trackExercise['exe_exo_id']); $totalScore = $totalWeighting = 0; $show_media = true; $tempParentId = null; $mediaCounter = 0; $media_list = array(); $modelType = $objExercise->getScoreTypeModel(); $options = array(); if ($modelType) { /** @var \Chamilo\CoreBundle\Entity\QuestionScore $questionScoreName */ $questionScore = $this->get('orm.em')->getRepository('Chamilo\\CoreBundle\\Entity\\QuestionScore')->find($modelType); if ($questionScore) { $items = $questionScore->getItems(); /** @var \Chamilo\CoreBundle\Entity\QuestionScoreName $score */ foreach ($items as $score) { $options[$score->getId() . ':' . $score->getScore()] = $score; } } } else { return $this->createNotFoundException('The exercise does not contain a model type.'); } $exerciseContent = null; foreach ($questionList as $questionId) { ob_start(); $choice = isset($exerciseResult[$questionId]) ? $exerciseResult[$questionId] : null; // Creates a temporary Question object /** @var \Question $objQuestionTmp */ $objQuestionTmp = \Question::read($questionId); if ($objQuestionTmp->parent_id != 0) { if (!in_array($objQuestionTmp->parent_id, $media_list)) { $media_list[] = $objQuestionTmp->parent_id; $show_media = true; } if ($tempParentId == $objQuestionTmp->parent_id) { $mediaCounter++; } else { $mediaCounter = 0; } $counterToShow = chr(97 + $mediaCounter); $tempParentId = $objQuestionTmp->parent_id; } $questionWeighting = $objQuestionTmp->selectWeighting(); $answerType = $objQuestionTmp->selectType(); $question_result = $objExercise->manageAnswers($exeId, $questionId, $choice, 'exercise_show', array(), false, true, true); $questionScore = $question_result['score']; $totalScore += $question_result['score']; $my_total_score = $questionScore; $my_total_weight = $questionWeighting; $totalWeighting += $questionWeighting; $score = array(); $score['result'] = get_lang('Score') . " : " . \ExerciseLib::show_score($my_total_score, $my_total_weight, false, false); $score['pass'] = $my_total_score >= $my_total_weight ? true : false; $score['type'] = $answerType; $score['score'] = $my_total_score; $score['weight'] = $my_total_weight; $score['comments'] = isset($comnt) ? $comnt : null; $contents = ob_get_clean(); $question_content = '<div class="question_row">'; $question_content .= $objQuestionTmp->return_header($objExercise->feedback_type, $counter, $score, $show_media, $mediaCounter); $question_content .= '</table>'; // display question category, if any $question_content .= \Testcategory::getCategoryNamesForQuestion($questionId); $question_content .= $contents; $defaultValue = isset($questionScoreTypeModel[$questionId]) ? $questionScoreTypeModel[$questionId] : null; //$question_content .= \Display::select('options['.$questionId.']', $options, $defaultValue); foreach ($options as $value => $score) { $attributes = array(); if ($score->getId() == $defaultValue) { $attributes = array('checked' => 'checked'); } $question_content .= '<label>'; $question_content .= \Display::input('radio', 'options[' . $questionId . ']', $value, $attributes) . ' <span title="' . $score->getDescription() . '" data-toggle="tooltip" > ' . $score->getName() . ' </span>'; $question_content .= '</label>'; } $question_content .= '</div>'; $exerciseContent .= $question_content; $counter++; } $template = $this->get('template'); $template->assign('exercise', $exerciseContent); $template->assign('exe_id', $exeId); $template->assign('jury_id', $juryId); $response = $this->get('template')->render_template($this->getTemplatePath() . 'score_attempt.tpl'); return new Response($response, 200, array()); }
/** * Return the name of the category for the question in a course * @author hubert.borderiou 13-10-2011 */ function get_question_categorie_for_question($in_courseid, $in_questionid) { $cat = Testcategory::getCategoryNameForQuestion($in_questionid, $in_courseid); return $cat; }
/** * @todo : add session id when used for session */ public function restore_test_category($session_id, $respect_base_content, $destination_course_code) { $course_id = api_get_course_int_id(); // Let's restore the categories $tab_test_category_id_old_new = array(); // used to build the quiz_question_rel_category table if ($this->course->has_resources(RESOURCE_TEST_CATEGORY)) { $resources = $this->course->resources; foreach ($resources[RESOURCE_TEST_CATEGORY] as $id => $CourseCopyTestcategory) { $tab_test_category_id_old_new[$CourseCopyTestcategory->source_id] = $id; // check if this test_category already exist in the destination BDD // do not Database::escape_string $title and $description, it will be done later $title = $CourseCopyTestcategory->title; $description = $CourseCopyTestcategory->description; if (Testcategory::category_exists_with_title($title)) { switch ($this->file_option) { case FILE_SKIP: //Do nothing break; case FILE_RENAME: $new_title = $title . "_"; while (Testcategory::category_exists_with_title($new_title)) { $new_title .= "_"; } $test_category = new Testcategory(0, $new_title, $description); $new_id = $test_category->addCategoryInBDD(); $tab_test_category_id_old_new[$CourseCopyTestcategory->source_id] = $new_id; break; case FILE_OVERWRITE: $id = Testcategory::get_category_id_for_title($title); $my_cat = new Testcategory($id); $my_cat->name = $title; $my_cat->modifyCategory(); $tab_test_category_id_old_new[$CourseCopyTestcategory->source_id] = $id; break; } } else { // create a new test_category $test_category = new Testcategory(0, $title, $description); $new_id = $test_category->addCategoryInBDD(); $tab_test_category_id_old_new[$CourseCopyTestcategory->source_id] = $new_id; } $this->course->resources[RESOURCE_TEST_CATEGORY][$id]->destination_id = $tab_test_category_id_old_new[$CourseCopyTestcategory->source_id]; } } // lets check if quizzes-question are restored too, to redo the link between test_category and quizzes question for questions restored // we can use the source_id field // question source_id => category source_id if ($this->course->has_resources(RESOURCE_QUIZQUESTION)) { // check the category number of each question restored if (!empty($resources[RESOURCE_QUIZQUESTION])) { foreach ($resources[RESOURCE_QUIZQUESTION] as $id => $CourseCopyQuestion) { $new_quiz_question_id = $resources[RESOURCE_QUIZQUESTION][$id]->destination_id; $question_category = $CourseCopyQuestion->question_category; if ($question_category > 0) { Testcategory::add_category_for_question_id($tab_test_category_id_old_new[$question_category], $new_quiz_question_id, $course_id); } } } } }
/** * @param string $courseCode * @param array $rules * @param array $columns * @param array $column_model * @return array */ public static function getRules($courseCode, &$rules, &$columns, &$column_model, $questionFields, $checkFields = false) { // sessions // course // categories // exercises // difficult // type if (empty($courseCode)) { // Session. $sessionList = SessionManager::get_sessions_by_general_coach(api_get_user_id()); $fields = array(); if (!empty($sessionList)) { $new_options = array(); $new_options[] = "-1:" . get_lang('All'); foreach ($sessionList as $session) { $new_options[] = "{$session['id']}:{$session['name']}"; } $string = implode(';', $new_options); $fields[] = array('field_display_text' => get_lang('Session'), 'field_variable' => 'session_id', 'field_type' => ExtraField::FIELD_TYPE_SELECT, 'field_default_value' => null, 'field_options' => $string); } } else { // $courseList = array(api_get_course_info()); //$courseList = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id()); } // Courses. $courseList = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id()); if (!empty($courseList)) { $new_options = array(); $new_options[] = "-1:" . get_lang('All'); foreach ($courseList as $course) { $new_options[] = "{$course['id']}:{$course['title']}"; } $string = implode(';', $new_options); $fields[] = array('field_display_text' => get_lang('Course'), 'field_variable' => 'c_id', 'field_type' => ExtraField::FIELD_TYPE_SELECT, 'field_default_value' => null, 'field_options' => $string); } // Categories. $string = null; if (!empty($courseList)) { $new_options = array(); $new_options[] = "-1:" . get_lang('All'); // Global categories // @todo use tree view $categories = Testcategory::getCategoriesIdAndName(0); if (!empty($categories)) { foreach ($categories as $id => $category) { if (!empty($id)) { $new_options[] = "{$id}:[Global] - " . $category; } } } foreach ($courseList as $course) { $categories = Testcategory::getCategoriesIdAndName($course['real_id']); if (!empty($categories)) { foreach ($categories as $id => $category) { if (!empty($id)) { $new_options[] = "{$id}:" . $course['title'] . " - " . $category; } } } } $string = implode(';', $new_options); $fields[] = array('field_display_text' => get_lang('Category'), 'field_variable' => 'category_id', 'field_type' => ExtraField::FIELD_TYPE_SELECT, 'field_default_value' => null, 'field_options' => $string); } $course = api_get_course_int_id(); $sessionId = api_get_session_id(); // Exercises. $exerciseList = ExerciseLib::get_all_exercises_for_course_id($sessionId, $course); if (!empty($exerciseList)) { $new_options = array(); $new_options[] = "-1:" . get_lang('All'); $new_options[] = "0:" . get_lang('Orphan'); foreach ($exerciseList as $exercise) { $new_options[] = "{$exercise['iid']}:{$exercise['title']}"; } $string = implode(';', $new_options); $fields[] = array('field_display_text' => get_lang('Exercise'), 'field_variable' => 'exercise_id', 'field_type' => ExtraField::FIELD_TYPE_SELECT, 'field_default_value' => null, 'field_options' => $string); } // Question type. $questionList = Question::get_question_type_list(); if (!empty($questionList)) { $new_options = array(); $new_options[] = "-1:" . get_lang('All'); foreach ($questionList as $key => $question) { $new_options[] = "{$key}:" . get_lang($question['1']); } $string = implode(';', $new_options); $fields[] = array('field_display_text' => get_lang('AnswerType'), 'field_variable' => 'question_type', 'field_type' => ExtraField::FIELD_TYPE_SELECT, 'field_default_value' => null, 'field_options' => $string); } // Difficult. $levels = Question::get_default_levels(); if (!empty($levels)) { $new_options = array(); $new_options[] = "-1:" . get_lang('All'); foreach ($levels as $key => $level) { $new_options[] = "{$key}:{$level}"; } $string = implode(';', $new_options); $fields[] = array('field_display_text' => get_lang('Difficulty'), 'field_variable' => 'difficulty', 'field_type' => ExtraField::FIELD_TYPE_SELECT, 'field_default_value' => null, 'field_options' => $string); } $questionFieldsKeys = array(); if (!empty($questionFields)) { foreach ($questionFields as $question) { $questionFieldsKeys[] = $question['field']; } } if (!empty($fields)) { foreach ($fields as $field) { $search_options = array(); $type = 'text'; if (in_array($field['field_type'], array(ExtraField::FIELD_TYPE_SELECT, ExtraField::FIELD_TYPE_DOUBLE_SELECT))) { $type = 'select'; $search_options['sopt'] = array('eq', 'ne'); //equal not equal //$search_options['sopt'] = array('cn', 'nc'); //contains not contains } else { $search_options['sopt'] = array('cn', 'nc'); //contains not contains } $search_options['searchhidden'] = 'true'; $search_options['defaultValue'] = isset($search_options['field_default_value']) ? $search_options['field_default_value'] : null; $search_options['value'] = $field['field_options']; $column_model[] = array('name' => 'question_' . $field['field_variable'], 'index' => 'question_' . $field['field_variable'], 'width' => '100', 'hidden' => 'true', 'search' => 'true', 'stype' => $type, 'searchoptions' => $search_options); $columns[] = $field['field_display_text']; $rules[] = array('field' => 'question_' . $field['field_variable'], 'op' => 'eq'); } } return $rules; }
/** * @param int $courseId * @param int $sessionId * @return string */ public function displayCategories($courseId, $sessionId = 0) { $categories = $this->getCategories($courseId, $sessionId); $html = null; foreach ($categories as $category) { $tmpobj = new Testcategory($category['id']); $nb_question = $tmpobj->getCategoryQuestionsNumber(); $rowname = self::protectJSDialogQuote($category['title']); $nb_question_label = $nb_question == 1 ? $nb_question . ' ' . get_lang('Question') : $nb_question . ' ' . get_lang('Questions'); $html .= '<div class="sectiontitle" id="id_cat' . $category['id'] . '">'; $html .= "<span style='float:right'>" . $nb_question_label . "</span>"; $html .= $category['title']; $html .= '</div>'; $html .= '<div class="sectioncomment">'; $html .= $category['description']; $html .= '</div>'; $html .= '<div>'; $html .= '<a href="' . api_get_self() . '?action=editcategory&category_id=' . $category['id'] . '">' . Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>'; $html .= ' <a href="' . api_get_self() . '?action=deletecategory&category_id=' . $category['id'] . '" '; $html .= 'onclick="return confirmDelete(\'' . self::protectJSDialogQuote(get_lang('DeleteCategoryAreYouSure') . '[' . $rowname) . '] ?\', \'id_cat' . $category['id'] . '\');">'; $html .= Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>'; $html .= '</div>'; } return $html; }