diff --git a/main/exercise/question_pool.php b/main/exercise/question_pool.php index 06bfbec0570..209541f35f8 100755 --- a/main/exercise/question_pool.php +++ b/main/exercise/question_pool.php @@ -23,6 +23,19 @@ $is_allowedToEdit = api_is_allowed_to_edit(null, true); +$extended = api_get_plugin_setting('extendedquestionpool', 'enable_plugin'); + +if ($extended == 'true') { + $query = $_SERVER['QUERY_STRING'] ?? ''; + $urlDest = 'question_pool_extended.php'; + + if (!empty($query)) { + $urlDest .= '?' . $query; + } + header('Location: ' . $urlDest); + exit; +} + $delete = isset($_GET['delete']) ? (int) $_GET['delete'] : null; $recup = isset($_GET['recup']) ? (int) $_GET['recup'] : null; $fromExercise = isset($_REQUEST['fromExercise']) ? (int) $_REQUEST['fromExercise'] : null; @@ -510,7 +523,15 @@ function confirm_your_choice() { $form->addHidden('exercise_id_changed', '0'); $extraField = new ExtraField('question'); -$jsForExtraFields = $extraField->addElements($form, 0, [], true); +$extendedExtraFields = array( + "additional_question_category", + "question_data1", + "question_data2", + "question_data3", + "question_extra_info" + ); +$jsForExtraFields = $extraField->addElements($form, 0, $extendedExtraFields, true); + $form->addButtonFilter(get_lang('Filter'), 'name'); diff --git a/main/exercise/question_pool_extended.php b/main/exercise/question_pool_extended.php new file mode 100644 index 00000000000..c940dca3f04 --- /dev/null +++ b/main/exercise/question_pool_extended.php @@ -0,0 +1,1390 @@ +read($fromExercise, false); +} + +$nameTools = get_lang('QuestionPool'); +$interbreadcrumb[] = ['url' => 'exercise.php?'.api_get_cidreq(), 'name' => get_lang('Exercises')]; + +if (!empty($objExercise->iid)) { + $interbreadcrumb[] = [ + 'url' => 'admin.php?exerciseId='.$objExercise->iid.'&'.api_get_cidreq(), + 'name' => $objExercise->selectTitle(true), + ]; +} + +// message to be displayed if actions successful +$displayMessage = ''; +if ($is_allowedToEdit) { + // Duplicating a Question + if (!isset($_POST['recup']) && $question_copy != 0 && isset($fromExercise)) { + $origin_course_id = (int) $_GET['course_id']; + $origin_course_info = api_get_course_info_by_id($origin_course_id); + $current_course = api_get_course_info(); + $old_question_id = $question_copy; + // Reading the source question + $old_question_obj = Question::read($old_question_id, $origin_course_info); + $courseId = $current_course['real_id']; + if ($old_question_obj) { + $old_question_obj->updateTitle($old_question_obj->selectTitle().' - '.get_lang('Copy')); + //Duplicating the source question, in the current course + $new_id = $old_question_obj->duplicate($current_course); + //Reading new question + $new_question_obj = Question::read($new_id); + $new_question_obj->addToList($fromExercise); + //Reading Answers obj of the current course + $new_answer_obj = new Answer($old_question_id, $origin_course_id); + $new_answer_obj->read(); + //Duplicating the Answers in the current course + $new_answer_obj->duplicate($new_question_obj, $current_course); + // destruction of the Question object + unset($new_question_obj); + unset($old_question_obj); + + $objExercise = new Exercise($courseId); + $objExercise->read($fromExercise); + Session::write('objExercise', $objExercise); + } + + $nQuestions = $objExercise->getQuestionCount(); + $displayMessage = get_lang('ItemAdded').' ('.$nQuestions.' '.get_lang('Questions').')'; + + } + + // Deletes a question from the database and all exercises + if ($delete) { + $limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access'); + if ($limitTeacherAccess && !api_is_platform_admin()) { + api_not_allowed(true); + } + // Construction of the Question object + $objQuestionTmp = isQuestionInActiveQuiz($delete) ? false : Question::read($delete); + // if the question exists + if ($objQuestionTmp) { + // deletes the question from all exercises + $objQuestionTmp->delete(); + + // solving the error that when deleting a question from the question pool it is not displaying all questions + $exerciseId = null; + } + // destruction of the Question object + unset($objQuestionTmp); + } elseif ($recup && $fromExercise) { + // gets an existing question and copies it into a new exercise + $objQuestionTmp = Question::read($recup); + // if the question exists + if ($objQuestionTmp) { + /* Adds the exercise ID represented by $fromExercise into the list + of exercises for the current question */ + $objQuestionTmp->addToList($fromExercise); + } + // destruction of the Question object + unset($objQuestionTmp); + + if (!$objExercise instanceof Exercise) { + $objExercise = new Exercise(); + $objExercise->read($fromExercise); + } + // Adds the question ID represented by $recup into the list of questions for the current exercise + $objExercise->addToList($recup); + Session::write('objExercise', $objExercise); + $nQuestions = $objExercise->getQuestionCount(); + //Display::addFlash(Display::return_message(get_lang('ItemAdded'), 'success')); + Display::addFlash(Display::return_message(get_lang('ItemAdded').' ('.$nQuestions.' '.get_lang('Questions').')', 'success')); + } elseif (isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) { + $list_recup = $_POST['recup']; + foreach ($list_recup as $course_id => $question_data) { + $origin_course_id = (int) $course_id; + $origin_course_info = api_get_course_info_by_id($origin_course_id); + $current_course = api_get_course_info(); + foreach ($question_data as $old_question_id) { + // Reading the source question + $old_question_obj = Question::read($old_question_id, $origin_course_info); + if ($old_question_obj) { + $old_question_obj->updateTitle( + $old_question_obj->selectTitle().' - '.get_lang('Copy') + ); + + // Duplicating the source question, in the current course + $new_id = $old_question_obj->duplicate($current_course); + + // Reading new question + $new_question_obj = Question::read($new_id); + $new_question_obj->addToList($fromExercise); + + //Reading Answers obj of the current course + $new_answer_obj = new Answer($old_question_id, $origin_course_id); + $new_answer_obj->read(); + + //Duplicating the Answers in the current course + $new_answer_obj->duplicate($new_question_obj, $current_course); + + // destruction of the Question object + unset($new_question_obj); + unset($old_question_obj); + + if (!$objExercise instanceof Exercise) { + $objExercise = new Exercise(); + $objExercise->read($fromExercise); + } + } + } + } + Session::write('objExercise', $objExercise); + $nQuestions = $objExercise->getQuestionCount(); + Display::addFlash(Display::return_message(get_lang('Done').' ('.$nQuestions.' '.get_lang('Questions').')', 'success')); + } +} + +if (api_is_in_gradebook()) { + $interbreadcrumb[] = [ + 'url' => Category::getUrl(), + 'name' => get_lang('ToolGradebook'), + ]; +} + +// if admin of course +if (!$is_allowedToEdit) { + api_not_allowed(true); +} + +$confirmYourChoice = addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset)); +$htmlHeadXtra[] = " +"; + +$url = api_get_self().'?'.api_get_cidreq().'&'.http_build_query( + [ + 'fromExercise' => $fromExercise, + 'session_id' => $session_id, + 'selected_course' => $selected_course, + 'courseCategoryId' => $courseCategoryId, + 'exerciseId' => $exerciseId, + 'exerciseLevel' => $exerciseLevel, + 'answerType' => $answerType, + 'question_id' => $questionId, + 'description' => Security::remove_XSS($description), + 'course_id_changed' => $course_id_changed, + 'exercise_id_changed' => $exercise_id_changed, + ] +); + +if (isset($_REQUEST['action'])) { + switch ($_REQUEST['action']) { + case 'score': + if (!empty($_REQUEST['questions'])) { + $txtError = ''; + $questions = $_REQUEST['questions']; + $correctScore = api_get_plugin_setting('extendedquestionpool', 'correct_score'); + $errorScore = api_get_plugin_setting('extendedquestionpool', 'error_score'); + if (!is_numeric($correctScore) || $correctScore<=0) { + Display::addFlash(Display::return_message('Debe definir correctamente las puntuaciones en la configuración del plugin', 'error')); + } elseif (!empty($errorScore) && !is_numeric($errorScore)) { + Display::addFlash(Display::return_message('Debe definir correctamente las puntuaciones en la configuración del plugin', 'error')); + } elseif (count($questions) > 0) { + foreach ($questions as $questionId) { + $objQuestionTmp = Question::read($questionId); + if ($objQuestionTmp) { + if ($objQuestionTmp->selectType()==UNIQUE_ANSWER) { + $table = Database::get_course_table(TABLE_QUIZ_ANSWER); + $query1 = "UPDATE $table SET ponderation = $correctScore + WHERE question_id=$questionId AND correct = 1"; + $query2 = "UPDATE $table SET ponderation = $errorScore + WHERE question_id=$questionId AND correct = 0"; + $tableQ = Database::get_course_table(TABLE_QUIZ_QUESTION); + $query3 = "UPDATE $tableQ SET ponderation = $correctScore + WHERE iid=$questionId"; + Database::query($query1); + Database::query($query2); + Database::query($query3); + } + } + } + } + header('Location: '.$url); + exit; + } + break; + case 'reuse': + if (!empty($_REQUEST['questions']) && !empty($fromExercise)) { + $questions = $_REQUEST['questions']; + $objExercise = new Exercise(); + $objExercise->read($fromExercise, false); + + if (count($questions) > 0) { + foreach ($questions as $questionId) { + // gets an existing question and copies it into a new exercise + $objQuestionTmp = Question::read($questionId); + // if the question exists + if ($objQuestionTmp) { + if (false === $objExercise->hasQuestion($questionId)) { + $objExercise->addToList($questionId); + $objQuestionTmp->addToList($fromExercise); + } + } + } + } + + $nQuestions = $objExercise->getQuestionCount(); + Display::addFlash(Display::return_message(get_lang('Added').' ('.$nQuestions.' '.get_lang('Questions').')', 'success')); + + header('Location: '.$url); + exit; + } + break; + case 'clone': + if (!empty($_REQUEST['questions']) && !empty($fromExercise)) { + $questions = $_REQUEST['questions']; + $origin_course_id = (int) $_GET['course_id']; + + $origin_course_info = api_get_course_info_by_id($origin_course_id); + $current_course = api_get_course_info(); + + if (count($questions) > 0) { + foreach ($questions as $questionId) { + // gets an existing question and copies it into a new exercise + // Reading the source question + $old_question_obj = Question::read($questionId, $origin_course_info); + $courseId = $current_course['real_id']; + if ($old_question_obj) { + $old_question_obj->updateTitle($old_question_obj->selectTitle().' - '.get_lang('Copy')); + // Duplicating the source question, in the current course + $new_id = $old_question_obj->duplicate($current_course); + // Reading new question + $new_question_obj = Question::read($new_id); + $new_question_obj->addToList($fromExercise); + //Reading Answers obj of the current course + $new_answer_obj = new Answer($questionId, $origin_course_id); + $new_answer_obj->read(); + //Duplicating the Answers in the current course + $new_answer_obj->duplicate($new_question_obj, $current_course); + // destruction of the Question object + unset($new_question_obj); + unset($old_question_obj); + } + } + } + + Display::addFlash(Display::return_message(get_lang('Added'))); + header('Location: '.$url); + exit; + } + break; + } +} + +Display::display_header($nameTools, 'Exercise'); + +// Menu +echo '
'; +if (isset($fromExercise) && $fromExercise > 0) { + echo ''. + Display::return_icon('back.png', get_lang('GoBackToQuestionList'), '', ICON_SIZE_MEDIUM).''; + $titleAdd = get_lang('AddQuestionToTest'); +} else { + echo ''. + Display::return_icon('back.png', get_lang('BackToExercisesList'), '', ICON_SIZE_MEDIUM).''; + echo "". + Display::return_icon('add_question.gif', get_lang('NewQu'), '', ICON_SIZE_MEDIUM).''; + $titleAdd = get_lang('ManageAllQuestions'); +} +echo '
'; + +if ('' != $displayMessage) { + echo Display::return_message($displayMessage, 'confirm'); +} + +// Session list, if sessions are used. +$sessionList = SessionManager::get_sessions_by_user(api_get_user_id(), api_is_platform_admin()); +$session_select_list = ['-1' => get_lang('Select')]; +foreach ($sessionList as $item) { + $session_select_list[$item['session_id']] = $item['session_name']; +} + +// Course list, get course list of session, or for course where user is admin +$course_list = []; + +// Course list, get course list of session, or for course where user is admin +if (!empty($session_id) && $session_id != '-1' && !empty($sessionList)) { + $sessionInfo = []; + foreach ($sessionList as $session) { + if ($session['session_id'] == $session_id) { + $sessionInfo = $session; + } + } + $course_list = $sessionInfo['courses']; +} else { + if (api_is_platform_admin()) { + $course_list = CourseManager::get_courses_list(0, 0, 'title'); + } else { + $course_list = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id()); + } + + // Admin fix, add the current course in the question pool. + if (api_is_platform_admin()) { + $courseInfo = api_get_course_info(); + if (!empty($course_list)) { + if (!in_array($courseInfo['real_id'], $course_list)) { + $course_list = array_merge($course_list, [$courseInfo]); + } + } else { + $course_list = [$courseInfo]; + } + } +} + +$course_select_list = ['-1' => get_lang('Select')]; +foreach ($course_list as $item) { + $courseItemId = $item['real_id']; + $courseInfo = api_get_course_info_by_id($courseItemId); + $course_select_list[$courseItemId] = ''; + if ($courseItemId == api_get_course_int_id()) { + $course_select_list[$courseItemId] = '>    '; + } + $course_select_list[$courseItemId] .= $courseInfo['title']; +} + +if (empty($selected_course) || $selected_course == '-1') { + $course_info = api_get_course_info(); + // no course selected, reset menu test / difficult� / type de reponse + reset_menu_exo_lvl_type(); +} else { + $course_info = api_get_course_info_by_id($selected_course); +} +// If course has changed, reset the menu default +if ($course_id_changed) { + reset_menu_exo_lvl_type(); +} + +// Get category list for the course $selected_course +$categoryList = TestCategory::getCategoriesIdAndName($selected_course); + +// Get exercise list for this course +$exercise_list = ExerciseLib::get_all_exercises_for_course_id( + $course_info, + $session_id, + $selected_course, + false +); + +if (1 == $exercise_id_changed) { + reset_menu_lvl_type(); +} + +// Exercise List +$my_exercise_list = []; +$my_exercise_list['0'] = get_lang('AllExercises'); +$my_exercise_list['-1'] = get_lang('OrphanQuestions'); +$titleSavedAsHtml = api_get_configuration_value('save_titles_as_html'); +if (is_array($exercise_list)) { + foreach ($exercise_list as $row) { + $my_exercise_list[$row['iid']] = ''; + if ($row['iid'] == $fromExercise && $selected_course == api_get_course_int_id()) { + $my_exercise_list[$row['iid']] = ">    "; + } + + $exerciseTitle = $row['title']; + if ($titleSavedAsHtml) { + $exerciseTitle = strip_tags(api_html_entity_decode(trim($exerciseTitle))); + } + $my_exercise_list[$row['iid']] .= $exerciseTitle; + } +} + +// Difficulty list (only from 0 to 5) +$levels = [ + -1 => get_lang('All'), + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, +]; + +// Answer type +$question_list = Question::getQuestionTypeList(); + +$new_question_list = []; +$new_question_list['-1'] = get_lang('All'); +if (!empty($_course)) { + foreach ($question_list as $key => $item) { + if (in_array( + $objExercise->getFeedbackType(), + [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP] + )) { + if (!in_array($key, [HOT_SPOT_DELINEATION, UNIQUE_ANSWER])) { + continue; + } + $new_question_list[$key] = get_lang($item[1]); + } else { + if (HOT_SPOT_DELINEATION == $key) { + continue; + } + $new_question_list[$key] = get_lang($item[1]); + } + } +} + +// Form +$form = new FormValidator('question_pool', 'GET', $url); +$form->addHeader($nameTools.' - '.$titleAdd); +$form->addHidden('fromExercise', $fromExercise); +$form + ->addSelect( + 'session_id', + get_lang('Session'), + $session_select_list, + ['onchange' => 'submit_form(this)', 'id' => 'session_id'] + ) + ->setSelected($session_id); +$form + ->addSelect( + 'selected_course', + get_lang('Course'), + $course_select_list, + ['onchange' => 'mark_course_id_changed(); submit_form(this);', 'id' => 'selected_course'] + ) + ->setSelected($selected_course); +$form + ->addSelect( + 'courseCategoryId', + get_lang('QuestionCategory'), + $categoryList, + ['onchange' => 'submit_form(this);', 'id' => 'courseCategoryId'] + ) + ->setSelected($courseCategoryId); +$form + ->addSelect( + 'exerciseId', + get_lang('Exercise'), + $my_exercise_list, + ['onchange' => 'mark_exercise_id_changed(); submit_form(this);', 'id' => 'exerciseId'] + ) + ->setSelected($exerciseId); +$form + ->addSelect( + 'exerciseLevel', + get_lang('Difficulty'), + $levels, + ['onchange' => 'submit_form(this);', 'id' => 'exerciseLevel'] + ) + ->setSelected($exerciseLevel); +$form + ->addSelect( + 'answerType', + get_lang('AnswerType'), + $new_question_list, + ['onchange' => 'submit_form(this);', 'id' => 'answerType'] + ) + ->setSelected($answerType); +$form + ->addText('question_id', get_lang('Id'), false) + ->setValue($questionId); +$form + ->addText('description', get_lang('Description'), false) + ->setValue(Security::remove_XSS($description)); + +$form->addHidden('course_id_changed', '0'); +$form->addHidden('exercise_id_changed', '0'); + +$extraField = new ExtraField('question'); + +$jsForExtraFields = $extraField->addElements($form, 0, [], true); + +$form->addButtonFilter(get_lang('Filter'), 'name'); + +echo $form->display(); + +echo ''; +?> +
+validate() ? $form->exportValues() : []; +/** + * @return array + */ +function getExtraFieldConditions(array $formValues, $queryType = 'from') +{ + $extraField = new ExtraField('question'); + $fields = $extraField->get_all( + ['visible_to_self = ? AND filter = ?' => [1, 1]], + 'display_text' + ); + + $from = ''; + $where = ''; + + foreach ($fields as $field) { + $variable = $field['variable']; + + if (empty($formValues["extra_$variable"])) { + continue; + } + + $value = $formValues["extra_$variable"]; + + switch ($field['field_type']) { + case ExtraField::FIELD_TYPE_CHECKBOX: + $value = $value["extra_$variable"]; + break; + case ExtraField::FIELD_TYPE_DOUBLE_SELECT: + if (!isset($value["extra_{$variable}_second"])) { + $value = null; + break; + } + + $value = $value["extra_$variable"].'::'.$value["extra_{$variable}_second"]; + break; + } + + if (empty($value)) { + continue; + } + + if ($queryType === 'from') { + $from .= ", extra_field_values efv_$variable, extra_field ef_$variable"; + $where .= "AND ( + qu.iid = efv_$variable.item_id + AND efv_$variable.field_id = ef_$variable.id + AND ef_$variable.extra_field_type = ".ExtraFieldEntity::QUESTION_FIELD_TYPE." + AND ef_$variable.variable = '$variable' + AND efv_$variable.value = '$value' + )"; + } elseif ($queryType === 'join') { + $from .= " INNER JOIN extra_field_values efv_$variable ON qu.iid = efv_$variable.item_id + INNER JOIN extra_field ef_$variable ON efv_$variable.field_id = ef_$variable.id"; + $where .= "AND ( + ef_$variable.extra_field_type = ".ExtraFieldEntity::QUESTION_FIELD_TYPE." + AND ef_$variable.variable = '$variable' + AND efv_$variable.value = '$value' + )"; + } + } + + return [ + 'from' => $from, + 'where' => $where, + ]; +} +/** + * get question list for sortable table + */ +function getQuestions($from, $number_of_items, $column, $direction, $getCount = false) { + $start = (int) $from; + $length = (int) $number_of_items; + if (empty($length)) { + $length = 20; + } + global $exerciseId, + $courseCategoryId, + $selected_course, + $session_id, + $exerciseLevel, + $answerType, + $questionId, + $description, + $fromExercise, + $formValues, + $objExercise, + $actionIcon1, + $actionIcon2, + $questionTagA; + + $TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); + $TBL_EXERCISES = Database::get_course_table(TABLE_QUIZ_TEST); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); + $TBL_COURSE_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); + + $currentExerciseCondition = ''; + if (!empty($fromExercise)) { + $currentCourseId = api_get_course_int_id(); + $currentExerciseCondition = " + AND qu.iid NOT IN ( + SELECT question_id FROM $TBL_EXERCISE_QUESTION + WHERE exercice_id = $fromExercise AND c_id = $currentCourseId + )"; + } + + // if we have selected an exercise in the list-box 'Filter' + if ($exerciseId > 0) { + $efConditions = getExtraFieldConditions($formValues, 'from'); + + $where = ''; + $from = ''; + if (isset($courseCategoryId) && $courseCategoryId > 0) { + $from = ", $TBL_COURSE_REL_CATEGORY crc "; + $where .= " AND + crc.c_id = $selected_course AND + crc.question_id = qu.iid AND + crc.category_id = $courseCategoryId"; + } + if (isset($exerciseLevel) && -1 != $exerciseLevel) { + $where .= ' AND level = '.$exerciseLevel; + } + if (isset($answerType) && $answerType > 0) { + $where .= ' AND type = '.$answerType; + } + + if (!empty($questionId)) { + $where .= ' AND qu.iid = '.$questionId; + } + + if (!empty($description)) { + $where .= " AND qu.description LIKE '%$description%'"; + } + + $select = 'DISTINCT + qu.iid, + qu.question, + qu.type, + qu.level, + qt.exercice_id exerciseId'; + if ($getCount) { + //$select = 'count(qu.iid) as count'; + } + $sql = "SELECT $select + FROM + $TBL_EXERCISE_QUESTION qt + INNER JOIN $TBL_QUESTIONS qu + ON qt.question_id = qu.iid + $from + {$efConditions['from']} + WHERE + qt.exercice_id = $exerciseId AND + qt.c_id = $selected_course + $where + $currentExerciseCondition + {$efConditions['where']} + ORDER BY BINARY qu.question ASC + "; + } elseif ($exerciseId == -1) { + $efConditions = getExtraFieldConditions($formValues, 'join'); + // If we have selected the option 'Orphan questions' in the list-box 'Filter' + $level_where = ''; + $from = ''; + if (isset($courseCategoryId) && $courseCategoryId > 0) { + $from = " INNER JOIN $TBL_COURSE_REL_CATEGORY crc + ON crc.question_id = ex.iid "; + $level_where .= " AND + crc.c_id = $selected_course AND + crc.category_id = $courseCategoryId"; + } + if (isset($exerciseLevel) && -1 != $exerciseLevel) { + $level_where = ' AND level='.$exerciseLevel; + } + $answer_where = ''; + if (isset($answerType) && $answerType > 0 - 1) { + $answer_where = ' AND qu.type='.$answerType; + } + + if (!empty($questionId)) { + $answer_where .= ' AND ex.iid = '.$questionId; + } + + if (!empty($description)) { + $answer_where .= " AND ex.description LIKE '%$description%'"; + } + + $select = ' qu.*, r.exercice_id exerciseId '; + + $sql = " ( + SELECT $select + FROM $TBL_QUESTIONS qu + INNER JOIN $TBL_EXERCISE_QUESTION r + ON qu.iid = r.question_id + INNER JOIN $TBL_EXERCISES ex + ON ex.iid = r.exercice_id + $from + {$efConditions['from']} + WHERE + ex.c_id = $selected_course AND + ex.active = '-1' + $level_where + $answer_where + {$efConditions['where']} + ) + UNION + ( + SELECT $select + FROM $TBL_QUESTIONS qu + LEFT OUTER JOIN $TBL_EXERCISE_QUESTION r + ON qu.iid = r.question_id + $from + {$efConditions['from']} + WHERE + qu.c_id = $selected_course AND + r.question_id is null + $level_where + $answer_where + {$efConditions['where']} + ) + UNION + ( + SELECT $select + FROM $TBL_QUESTIONS qu + INNER JOIN $TBL_EXERCISE_QUESTION r + ON qu.iid = r.question_id + $from + {$efConditions['from']} + WHERE + r.c_id = $selected_course AND + (r.exercice_id = '-1' OR r.exercice_id = '0') + $level_where + $answer_where + {$efConditions['where']} + ) + "; + } else { + $efConditions = getExtraFieldConditions($formValues, 'from'); + // All tests for selected course + // If we have not selected any option in the list-box 'Filter' + $filter = ''; + $from = ''; + if (isset($courseCategoryId) && $courseCategoryId > 0) { + $from = ", $TBL_COURSE_REL_CATEGORY crc "; + $filter .= " AND + crc.c_id = $selected_course AND + crc.question_id = qu.iid AND + crc.category_id = $courseCategoryId"; + } + if (isset($exerciseLevel) && -1 != $exerciseLevel) { + $filter .= ' AND level = '.$exerciseLevel.' '; + } + if (isset($answerType) && $answerType > 0) { + $filter .= ' AND qu.type = '.$answerType.' '; + } + + if (!empty($questionId)) { + $filter .= ' AND qu.iid = '.$questionId; + } + + if (!empty($description)) { + $filter .= " AND qu.description LIKE '%$description%'"; + } + + if (-1 == $session_id || empty($session_id)) { + $session_id = 0; + } + $sessionCondition = api_get_session_condition($session_id, true, 'ex.session_id'); + + $select = 'qu.iid, question, qu.type, level, ex.session_id, qt.exercice_id exerciseId '; + + // All tests for the course selected, not in session + $sql = "SELECT DISTINCT + $select + FROM + $TBL_QUESTIONS as qu + INNER JOIN $TBL_EXERCISE_QUESTION as qt + ON qu.iid = qt.question_id + INNER JOIN $TBL_EXERCISES as ex + ON ex.iid = qt.exercice_id + {$efConditions['from']} + $from + WHERE + qt.c_id = $selected_course AND + ex.c_id = $selected_course + $sessionCondition + $filter + $currentExerciseCondition + {$efConditions['where']} + GROUP BY qu.iid + ORDER BY BINARY qu.question ASC + "; + } + + if ($getCount) { + $result = Database::query($sql); + return Database::num_rows($result); + } + //$sql .= " LIMIT $start, $length"; + $result = Database::query($sql); + + $mainQuestionList = []; + while ($row = Database::fetch_array($result, 'ASSOC')) { + if ($exerciseId == -1 && isQuestionInActiveQuiz($row['iid'])) { + continue; + } + + $mainQuestionList[] = $row; + } + + $QList = []; + foreach ($mainQuestionList as $question) { + $row = []; + // This function checks if the question can be read + $question_type = get_question_type_for_question($selected_course, $question['iid']); + + if (empty($question_type)) { + continue; + } + $sessionId = isset($question['session_id']) ? $question['session_id'] : null; + if (!$objExercise->hasQuestion($question['iid'])) { + $row[0] = Display::input( + 'checkbox', + 'questions[]', + $question['iid'], + ['class' => 'question_checkbox'] + ); + } else { + $row[1] = ''; + } + $row[1] = $question['iid']; + + $row[2] = getLinkForQuestion( + $questionTagA, + $fromExercise, + $question['iid'], + $question['type'], + $question['question'], + $sessionId, + $question['exerciseId'] + ); + + $row[3] = $question_type; + $row[4] = TestCategory::getCategoryNameForQuestion($question['iid'], $selected_course); + $row[5] = $question['level']; + + $row[6] = getQuestionOcurrences($question['iid']); + $row[7] = getQuestionFailures($question['iid']); + $row[8] = getQuestionSuccesses($question['iid']); + + $row[9] = get_action_icon_for_question( + $actionIcon1, + $fromExercise, + $question['iid'], + $question['type'], + $question['question'], + $selected_course, + $courseCategoryId, + $exerciseLevel, + $answerType, + $session_id, + $question['exerciseId'], + $objExercise + ).' '. + get_action_icon_for_question( + $actionIcon2, + $fromExercise, + $question['iid'], + $question['type'], + $question['question'], + $selected_course, + $courseCategoryId, + $exerciseLevel, + $answerType, + $session_id, + $question['exerciseId'], + $objExercise + ); + $QList[] = $row; + } + if(!empty($column)) { + $asc = $direction =='ASC' ? 1 : 0; + $QList = sortByCol($QList, $column, $asc); + } + $x = 0; + if (!empty($length)) { + $questionList = []; + $end = $start+$length; + foreach($QList as $question) { + if ($x>=$start && $x<$end) { + $questionList[] = $question; + } + $x++; + } + return $questionList; + } + return $QList; + +} +/** + * get number total of questions + */ +function getNbrQuestions() { + $res = getQuestions( + 0, + 0, + 0, + null, + true + ); + return $res; +} + + +$nbrQuestions = getQuestions( + 0, + 0, + 0, + null, + true + ); + + +$length = api_get_configuration_value('question_pagination_length'); +if (empty($length)) { + $length = 20; +} + +$start = ($page - 1) * $length; + +$paginator = new Paginator(); +$pagination = $paginator->paginate([]); +$pagination->setTotalItemCount($nbrQuestions); +$pagination->setItemNumberPerPage($length); +$pagination->setCurrentPageNumber($page); + +$pagination->renderer = function ($data) use ($url) { + $render = ''; + if ($data['pageCount'] > 1) { + $render = ''; + } + + return $render; +}; + +// build the line of the array to display questions +// Actions are different if you launch the question_pool page +// They are different too if you have displayed questions from your course +// Or from another course you are the admin(or session admin) +// from a test or not +/* ++--------------------------------------------+--------------------------------------------+ +| NOT IN A TEST | IN A TEST | ++----------------------+---------------------+---------------------+----------------------+ +|IN THE COURSE (*) "x | NOT IN THE COURSE o | IN THE COURSE + | NOT IN THE COURSE o | ++----------------------+---------------------+---------------------+----------------------+ +|Edit the question | Do nothing | Add question to test|Clone question in test| +|Delete the question | | | | +|(true delete) | | | | ++----------------------+---------------------+---------------------+----------------------+ +(*) this is the only way to delete or modify orphan questions +*/ + +if ($fromExercise <= 0) { + // NOT IN A TEST - NOT IN THE COURSE + $actionLabel = get_lang('Reuse'); + $actionIcon1 = get_lang('MustBeInATest'); + $actionIcon2 = ''; + // We are not in this course, to messy if we link to the question in another course + $questionTagA = 0; + if ($selected_course == api_get_course_int_id()) { + // NOT IN A TEST - IN THE COURSE + $actionLabel = get_lang('Modify'); + $actionIcon1 = 'edit'; + $actionIcon2 = 'delete'; + // We are in the course, question title can be a link to the question edit page + $questionTagA = 1; + } +} else { + // IN A TEST - NOT IN THE COURSE + $actionLabel = get_lang('ReUseACopyInCurrentTest'); + $actionIcon1 = 'clone'; + $actionIcon2 = ''; + $questionTagA = 0; + + if ($selected_course == api_get_course_int_id()) { + // IN A TEST - IN THE COURSE + $actionLabel = get_lang('Reuse'); + $actionIcon1 = 'add'; + $actionIcon2 = ''; + $questionTagA = 1; + } elseif (true === api_get_configuration_value('quiz_question_allow_inter_course_linking')) { + $actionIcon2 = 'add'; + } +} + + +$headers = []; + +//echo $pagination; + +$tableId = 'question_pool_id'; +echo '
'; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; + +//$parameters = []; +/*$vals = getQuestionsList(0,20,2, 'ASC'); +echo '
';
+echo var_dump($vals);
+echo '
'; +echo '
';
+echo var_dump(getNbrQuestions());
+echo '
';*/ + +$table = new SortableTable( + 'question-list', + 'getNbrQuestions', + 'getQuestions', + 2, + 20, + 'ASC' + ); +//$table->set_additional_parameters($parameters); +$row = 0; +$column = 0; +$table->set_header(0, '', false, 'width="8px"'); +$table->set_header(1, 'Id', true, 'width="60px"'); +$table->set_header(2, get_lang('QuestionUpperCaseFirstLetter'), true, null, ['class' => 'title']); +$table->set_header(3, get_lang('Type'), false); +$table->set_header(4, get_lang('QuestionCategory'), true); +$table->set_header(5, get_lang('Difficulty'), true); +$table->set_header(6, get_plugin_lang('Occurrences', ExtendedQuestionPoolPlugin::class), true); +$table->set_header(7, get_plugin_lang('Failures', ExtendedQuestionPoolPlugin::class), true); +$table->set_header(8, get_plugin_lang('Successes', ExtendedQuestionPoolPlugin::class), true); +$table->set_header(9, $actionLabel, false, 'width="70px"'); + +echo $table->return_table(); + +echo '
'; + +$html = '
'; +$html .= '
'; +$html .= ' + '.get_lang('SelectAll').''; +$html .= ' + '.get_lang('UnSelectAll').' '; +$html .= '
'; +$html .= '
+ + + '; +$html .= '
'; //btn-group +$html .= '
'; //toolbar + +echo $html; + +Display::display_footer(); + +/** + * Put the menu entry for level and type to default "Choice" + * It is useful if you change the exercise, you need to reset the other menus. + * + * @author hubert.borderiou 13-10-2011 + */ +function reset_menu_lvl_type() +{ + global $exerciseLevel, $answerType; + $answerType = -1; + $exerciseLevel = -1; +} + +/** + * Put the menu entry for exercise and level and type to default "Choice" + * It is useful if you change the course, you need to reset the other menus. + * + * @author hubert.borderiou 13-10-2011 + */ +function reset_menu_exo_lvl_type() +{ + global $exerciseId, $courseCategoryId; + reset_menu_lvl_type(); + $exerciseId = 0; + $courseCategoryId = 0; +} + +/** + * return the link to admin question, if needed. + * + * @param int $in_addA + * @param int $fromExercise + * @param int $questionId + * @param int $questionType + * @param string $questionName + * @param int $sessionId + * @param int $exerciseId + * + * @return string + * + * @author hubert.borderiou + */ +function getLinkForQuestion( + $in_addA, + $fromExercise, + $questionId, + $questionType, + $questionName, + $sessionId, + $exerciseId +) { + $result = $questionName; + if ($in_addA) { + $sessionIcon = ''; + if (!empty($sessionId) && -1 != $sessionId) { + $sessionIcon = ' '.Display::return_icon('star.png', get_lang('Session')); + } + $exerciseId = (int) $exerciseId; + $questionId = (int) $questionId; + $questionType = (int) $questionType; + $fromExercise = (int) $fromExercise; + $qOptions = getQuestionAnswers($questionId); + $result = Display::url( + $questionName.$sessionIcon, + 'admin.php?'.api_get_cidreq(). + "&exerciseId=$exerciseId&editQuestion=$questionId&type=$questionType&fromExercise=$fromExercise", + ['title' => $qOptions] + ); + } + + return $result; +} + +/** + Return the html code for delete, add, clone, edit a question + in_action = the code of the action triggered by the button + from_exercise = the id of the current exercise from which we click on question pool + in_questionid = the id of the current question + in_questiontype = the code of the type of the current question + in_questionname = the name of the question + in_selected_course = the if of the course chosen in the FILTERING MENU + in_courseCategoryId = the id of the category chosen in the FILTERING MENU + in_exerciseLevel = the level of the exercise chosen in the FILTERING MENU + in_answerType = the code of the type of the question chosen in the FILTERING MENU + in_session_id = the id of the session_id chosen in the FILTERING MENU + in_exercise_id = the id of the exercise chosen in the FILTERING MENU +*/ +function get_action_icon_for_question( + $in_action, + $from_exercise, + $in_questionid, + $in_questiontype, + $in_questionname, + $in_selected_course, + $in_courseCategoryId, + $in_exerciseLevel, + $in_answerType, + $in_session_id, + $in_exercise_id, + Exercise $myObjEx +) { + $limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access'); + $getParams = "&selected_course=$in_selected_course&courseCategoryId=$in_courseCategoryId&exerciseId=$in_exercise_id&exerciseLevel=$in_exerciseLevel&answerType=$in_answerType&session_id=$in_session_id"; + $res = ''; + switch ($in_action) { + case 'delete': + if ($limitTeacherAccess && !api_is_platform_admin()) { + break; + } + + if (isQuestionInActiveQuiz($in_questionid)) { + $res = Display::return_icon('delete_na.png', get_lang('ThisQuestionExistsInAnotherExercisesWarning')); + } else { + $res = ""; + $res .= Display::return_icon('delete.png', get_lang('Delete')); + $res .= ""; + } + + break; + case 'edit': + $res = getLinkForQuestion( + 1, + $from_exercise, + $in_questionid, + $in_questiontype, + Display::return_icon('edit.png', get_lang('Modify')), + $in_session_id, + $in_exercise_id + ); + break; + case 'add': + $res = '-'; + if (!$myObjEx->hasQuestion($in_questionid)) { + $res = ""; + $res .= Display::return_icon('view_more_stats.gif', get_lang('InsertALinkToThisQuestionInTheExercise')); + $res .= ''; + } + break; + case 'clone': + $url = api_get_self().'?'.api_get_cidreq().$getParams. + "&question_copy=$in_questionid&course_id=$in_selected_course&fromExercise=$from_exercise"; + $res = Display::url( + Display::return_icon('cd.png', get_lang('ReUseACopyInCurrentTest')), + $url + ); + break; + default: + $res = $in_action; + break; + } + + return $res; +} + +/** + * @param int $questionId + * + * @return bool + */ +function isQuestionInActiveQuiz($questionId) +{ + $tblQuizRelQuestion = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); + $tblQuiz = Database::get_course_table(TABLE_QUIZ_TEST); + + $questionId = (int) $questionId; + + if (empty($questionId)) { + return false; + } + + $result = Database::fetch_assoc( + Database::query( + "SELECT COUNT(qq.question_id) count + FROM $tblQuizRelQuestion qq + INNER JOIN $tblQuiz ex + ON qq.exercice_id = ex.iid + WHERE + ex.active = 1 AND + qq.question_id = $questionId" + ) + ); + + return $result['count'] > 0; +} + +/** + * Return the icon for the question type. + * + * @author hubert.borderiou 13-10-2011 + */ +function get_question_type_for_question($in_selectedcourse, $in_questionid) +{ + $courseInfo = api_get_course_info_by_id($in_selectedcourse); + $question = Question::read($in_questionid, $courseInfo); + $questionType = null; + if (!empty($question)) { + $typeImg = $question->getTypePicture(); + $typeExpl = $question->getExplanation(); + + $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, [], 32), []); + } + + return $questionType; +} diff --git a/plugin/extendedquestionpool/README.md b/plugin/extendedquestionpool/README.md new file mode 100644 index 00000000000..fc4e05bd90d --- /dev/null +++ b/plugin/extendedquestionpool/README.md @@ -0,0 +1,26 @@ +Extended Question Pool plugin +============================== +Este plugin amplía las funcionalidades del banco de preguntas. + +**Instrucciones de puesta en funcionamiento** + +- Habilitar el plugin en la administración de Chamilo. +- Configurar las opciones deseadas + +**Accesos a la herramienta** + +- Desde plugins, para configurar las opciones + +**Funcionalidades que incluye** + +- Mostrar el nº de preguntas total del ejercicio +- Campos extra en las preguntas para ampliar la clasificación +- Detectar preguntas ya utilizadas +- Asignar puntuaciones de preguntas de manera masiva +- Contador aciertos y fallos por preguntas +- Ordenar las preguntas por nombre, categoría, dificultad, nº de apariciones, aciertos, fallos + + +Credits +------- +Contributed by [Nosolored](https://www.nosolored.com/). \ No newline at end of file diff --git a/plugin/extendedquestionpool/config.php b/plugin/extendedquestionpool/config.php new file mode 100644 index 00000000000..94ca5e720db --- /dev/null +++ b/plugin/extendedquestionpool/config.php @@ -0,0 +1,12 @@ + + */ +require_once __DIR__.'/../../main/inc/global.inc.php'; +require_once api_get_path(SYS_PLUGIN_PATH).'extendedquestionpool/src/extendedquestionpool_plugin.class.php'; \ No newline at end of file diff --git a/plugin/extendedquestionpool/database.php b/plugin/extendedquestionpool/database.php new file mode 100644 index 00000000000..e2c02180075 --- /dev/null +++ b/plugin/extendedquestionpool/database.php @@ -0,0 +1,200 @@ +getConnection(); +$platform = $connection->getDatabasePlatform(); +$sm = $connection->getSchemaManager(); + +$extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD); + +$categoryExtraField = Database::select( + "*", + $extraFieldTable, + [ + 'where' => ['variable = ?' => 'additional_question_category'], + ], + 'first' +); + +if (!$categoryExtraField) { + Database::insert( + $extraFieldTable, + [ + 'extra_field_type' => 4, + 'field_type' => 1, + 'variable' => 'additional_question_category', + 'display_text' => 'Categoría adicional', + 'default_value' => '', + 'field_order' => 0, + 'visible_to_self' => 1, + 'changeable' => 1, + 'filter' => 1, + 'created_at' => api_get_utc_datetime(), + ] + ); +} else { + $query = "UPDATE $extraFieldTable + SET visible_to_self = 1, + visible_to_others = 1, + changeable = 1, + filter = 1 + WHERE variable = 'additional_question_category'"; + Database::query($query); +} + +$categoryExtraField = Database::select( + "*", + $extraFieldTable, + [ + 'where' => ['variable = ?' => 'question_data1'], + ], + 'first' +); + +if (!$categoryExtraField) { + Database::insert( + $extraFieldTable, + [ + 'extra_field_type' => 4, + 'field_type' => 1, + 'variable' => 'question_data1', + 'display_text' => 'Campo 1', + 'default_value' => '', + 'field_order' => 0, + 'visible_to_self' => 1, + 'changeable' => 1, + 'filter' => 1, + 'created_at' => api_get_utc_datetime(), + ] + ); +} else { + $query = "UPDATE $extraFieldTable + SET visible_to_self = 1, + visible_to_others = 1, + changeable = 1, + filter = 1 + WHERE variable = 'question_data1'"; + Database::query($query); +} + +$categoryExtraField = Database::select( + "*", + $extraFieldTable, + [ + 'where' => ['variable = ?' => 'question_data2'], + ], + 'first' +); + +if (!$categoryExtraField) { + Database::insert( + $extraFieldTable, + [ + 'extra_field_type' => 4, + 'field_type' => 1, + 'variable' => 'question_data2', + 'display_text' => 'Campo 2', + 'default_value' => '', + 'field_order' => 0, + 'visible_to_self' => 1, + 'changeable' => 1, + 'filter' => 1, + 'created_at' => api_get_utc_datetime(), + ] + ); +} else { + $query = "UPDATE $extraFieldTable + SET visible_to_self = 1, + visible_to_others = 1, + changeable = 1, + filter = 1 + WHERE variable = 'question_data2'"; + Database::query($query); +} + +$categoryExtraField = Database::select( + "*", + $extraFieldTable, + [ + 'where' => ['variable = ?' => 'question_data3'], + ], + 'first' +); + +if (!$categoryExtraField) { + Database::insert( + $extraFieldTable, + [ + 'extra_field_type' => 4, + 'field_type' => 1, + 'variable' => 'question_data3', + 'display_text' => 'Campo 3', + 'default_value' => '', + 'field_order' => 0, + 'visible_to_self' => 1, + 'changeable' => 1, + 'filter' => 1, + 'created_at' => api_get_utc_datetime(), + ] + ); +} else { + $query = "UPDATE $extraFieldTable + SET visible_to_self = 1, + visible_to_others = 1, + changeable = 1, + filter = 1 + WHERE variable = 'question_data3'"; + Database::query($query); +} + +$categoryExtraField = Database::select( + "*", + $extraFieldTable, + [ + 'where' => ['variable = ?' => 'question_extra_info'], + ], + 'first' +); + +if (!$categoryExtraField) { + Database::insert( + $extraFieldTable, + [ + 'extra_field_type' => 4, + 'field_type' => 2, + 'variable' => 'question_extra_info', + 'display_text' => 'Información adicional', + 'default_value' => '', + 'field_order' => 0, + 'visible_to_self' => 1, + 'changeable' => 1, + 'filter' => 1, + 'created_at' => api_get_utc_datetime(), + ] + ); +} else { + $query = "UPDATE $extraFieldTable + SET visible_to_self = 1, + visible_to_others = 1, + changeable = 1, + filter = 1 + WHERE variable = 'question_extra_info'"; + Database::query($query); +} \ No newline at end of file diff --git a/plugin/extendedquestionpool/index.php b/plugin/extendedquestionpool/index.php new file mode 100644 index 00000000000..e70cd86d150 --- /dev/null +++ b/plugin/extendedquestionpool/index.php @@ -0,0 +1,3 @@ +install(); diff --git a/plugin/extendedquestionpool/lang/english.php b/plugin/extendedquestionpool/lang/english.php new file mode 100644 index 00000000000..c15c5e79c41 --- /dev/null +++ b/plugin/extendedquestionpool/lang/english.php @@ -0,0 +1,12 @@ +Plugins). + * + * @package chamilo.plugin.extendedquestionpool + */ + +/** + * Plugin details (must be present). + */ +require_once __DIR__.'/config.php'; +$plugin_info = ExtendedQuestionPoolPlugin::create()->get_info(); diff --git a/plugin/extendedquestionpool/src/extendedquestionpool.lib.php b/plugin/extendedquestionpool/src/extendedquestionpool.lib.php new file mode 100644 index 00000000000..93c9090dab0 --- /dev/null +++ b/plugin/extendedquestionpool/src/extendedquestionpool.lib.php @@ -0,0 +1,126 @@ + + */ + +/** + * Get the number of occurrences of a question in quizzes + * @param int $questionId + * @return int + */ +function getQuestionOcurrences($questionId) { + $questionQuizTable = 'c_quiz_rel_question'; + if (empty($questionId)) { + return false; + } + $query = "SELECT count(iid) as nbr FROM $questionQuizTable + WHERE question_id = '$questionId'"; + $q = Database::query($query); + $row = Database::fetch_assoc($q); + $res = $row['nbr']; + + return $res; +} +/** + * Get the number of failures answers of a question in quizzes + * @param int $questionId + * @param int $c_id course id + * @return int + */ +function getQuestionFailures($questionId, $c_id = 0) +{ + $attemptTable = 'track_e_attempt'; + if (empty($questionId)) { + return false; + } + $query = "SELECT count(id) as nbr FROM $attemptTable + WHERE question_id = '$questionId' + AND marks <= 0"; + if (!empty($c_id)) { + $query .= " AND c_id='$c_id'"; + } + $q = Database::query($query); + $row = Database::fetch_assoc($q); + $res = $row['nbr']; + + return $res; +} +/** + * Get the number of successes answers of a question in quizzes + * @param int $questionId + * @param int $c_id course id + * @return int + */ +function getQuestionSuccesses($questionId, $c_id = 0) +{ + $attemptTable = 'track_e_attempt'; + if (empty($questionId)) { + return false; + } + $query = "SELECT count(id) as nbr FROM $attemptTable + WHERE question_id = '$questionId' + AND marks > 0"; + if (!empty($c_id)) { + $query .= " AND c_id='$c_id'"; + } + $q = Database::query($query); + $row = Database::fetch_assoc($q); + $res = $row['nbr']; + + return $res; +} +/** + * Sort array by column + * @param array $data + * @param string $col + * @param bool $asc + * @return array + */ +function sortByCol(array $data, string $col, bool $asc = true): array { + usort($data, function ($a, $b) use ($col, $asc) { + if (!isset($a[$col]) || !isset($b[$col])) { + return 0; // column doesn't exist, nothing to sort + } + + if ($a[$col] == $b[$col]) { + return 0; + } + + if ($asc) { + return (strip_tags($a[$col]) < strip_tags($b[$col])) ? -1 : 1; + } else { + return (strip_tags($a[$col]) > strip_tags($b[$col])) ? -1 : 1; + } + }); + + return $data; +} +/** + * Get answer options for a question + * @param int $questionId + * @return string + */ +function getQuestionAnswers(int $questionId) { + $table = Database::get_course_table(TABLE_QUIZ_ANSWER); + if (empty($questionId)) { + return false; + } + $res = ''; + $query = "SELECT * FROM $table WHERE question_id=$questionId ORDER BY position"; + $result = Database::query($query); + while ($row = Database::fetch_assoc($result)) { + $c = '- '; + if ($row['correct'] == 1) { + $c = '# '; + } + $answer = html_entity_decode(strip_tags($row['answer'])); + $res .= $c.$answer.chr(13).chr(10); + } + return $res; +} \ No newline at end of file diff --git a/plugin/extendedquestionpool/src/extendedquestionpool_plugin.class.php b/plugin/extendedquestionpool/src/extendedquestionpool_plugin.class.php new file mode 100644 index 00000000000..08817f99ac0 --- /dev/null +++ b/plugin/extendedquestionpool/src/extendedquestionpool_plugin.class.php @@ -0,0 +1,108 @@ + + */ +class ExtendedQuestionPoolPlugin extends Plugin +{ + //public $isCoursePlugin = true; + + /** + * Constructor. + */ + protected function __construct() + { + parent::__construct( + '1.0', + 'NoSoloRed', + [ + 'enable_plugin' => 'boolean', + 'correct_score' => 'text', + 'error_score' => 'text', + ] + ); + + $this->isAdminPlugin = true; + } + + /** + * Instance the plugin. + * + * @staticvar null $result + * + * @return ExtendedQuestionPool + */ + public static function create() + { + static $result = null; + + return $result ? $result : $result = new self(); + } + + /** + * This method creates the tables required to this plugin. + */ + public function install() + { + require_once api_get_path(SYS_PLUGIN_PATH).'extendedquestionpool/database.php'; + } + + /** + * This method drops the plugin tables. + */ + public function uninstall() + { + // Deleting course settings. + $this->uninstall_course_fields_in_all_courses(); + $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD); + $query = "UPDATE $extraFieldTable + SET visible_to_self = 0, + visible_to_others = 0, + changeable = 0, + filter = 0 + WHERE variable = 'additional_question_category'"; + Database::query($query); + $query = "UPDATE $extraFieldTable + SET visible_to_self = 0, + visible_to_others = 0, + changeable = 0, + filter = 0 + WHERE variable = 'question_data1'"; + Database::query($query); + $query = "UPDATE $extraFieldTable + SET visible_to_self = 0, + visible_to_others = 0, + changeable = 0, + filter = 0 + WHERE variable = 'question_data2'"; + Database::query($query); + $query = "UPDATE $extraFieldTable + SET visible_to_self = 0, + visible_to_others = 0, + changeable = 0, + filter = 0 + WHERE variable = 'question_data3'"; + Database::query($query); + $query = "UPDATE $extraFieldTable + SET visible_to_self = 0, + visible_to_others = 0, + changeable = 0, + filter = 0 + WHERE variable = 'question_extra_info'"; + Database::query($query); + $this->manageTab(false); + } + + /** + * This method updates plugin. + */ + public function update() + { + //update actions + } +} \ No newline at end of file diff --git a/plugin/extendedquestionpool/src/index.php b/plugin/extendedquestionpool/src/index.php new file mode 100644 index 00000000000..ddfd7d17566 --- /dev/null +++ b/plugin/extendedquestionpool/src/index.php @@ -0,0 +1,3 @@ +get('enable_plugin_extendedquestionpool') == 'true'; + +if ($enable) { + if (api_is_platform_admin() || api_is_teacher()) { + $url = 'src/index.php?'; + $url .= (isset($_GET['cidReq']) ? api_get_cidreq() : 'default=1'); + header('Location: '.$url); + exit; + } else { + $session = api_get_session_entity(api_get_session_id()); + $_course = api_get_course_info(); + $webCoursePath = api_get_path(WEB_COURSE_PATH); + $url = $webCoursePath.$_course['path'].'/index.php'.($session ? '?id_session='.$session->getId() : ''); + + Display::addFlash( + Display::return_message($plugin->get_lang('OnlyAdminPlatform')) + ); + + header('Location: '.$url); + exit; + } +} else { + api_not_allowed(true, $plugin->get_lang('ToolDisabled')); +} diff --git a/plugin/extendedquestionpool/uninstall.php b/plugin/extendedquestionpool/uninstall.php new file mode 100644 index 00000000000..4cd189a3910 --- /dev/null +++ b/plugin/extendedquestionpool/uninstall.php @@ -0,0 +1,12 @@ +uninstall(); diff --git a/plugin/extendedquestionpool/update.php b/plugin/extendedquestionpool/update.php new file mode 100644 index 00000000000..26c8d8b9935 --- /dev/null +++ b/plugin/extendedquestionpool/update.php @@ -0,0 +1,14 @@ +update();