MDL-20636 fix most of the remaining codechecker issues in mod/quiz and lib/questionlib.php.
This commit is contained in:
+205
-156
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -139,12 +138,13 @@ function question_save_qtype_order($neworder, $config = null) {
|
||||
* Returns an array of names of activity modules that use this question
|
||||
*
|
||||
* @deprecated since Moodle 2.1. Use {@link questions_in_use} instead.
|
||||
|
||||
*
|
||||
* @param object $questionid
|
||||
* @return array of strings
|
||||
*/
|
||||
function question_list_instances($questionid) {
|
||||
throw new coding_exception('question_list_instances has been deprectated. Please use questions_in_use instead.');
|
||||
throw new coding_exception('question_list_instances has been deprectated. ' .
|
||||
'Please use questions_in_use instead.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,21 +277,20 @@ function get_grade_options() {
|
||||
* @return mixed either 'fixed' value or false if erro
|
||||
*/
|
||||
function match_grade_options($gradeoptionsfull, $grade, $matchgrades='error') {
|
||||
// if we just need an error...
|
||||
if ($matchgrades=='error') {
|
||||
foreach($gradeoptionsfull as $value => $option) {
|
||||
if ($matchgrades == 'error') {
|
||||
// if we just need an error...
|
||||
foreach ($gradeoptionsfull as $value => $option) {
|
||||
// slightly fuzzy test, never check floats for equality :-)
|
||||
if (abs($grade-$value)<0.00001) {
|
||||
if (abs($grade - $value) < 0.00001) {
|
||||
return $grade;
|
||||
}
|
||||
}
|
||||
// didn't find a match so that's an error
|
||||
return false;
|
||||
}
|
||||
// work out nearest value
|
||||
else if ($matchgrades=='nearest') {
|
||||
} else if ($matchgrades == 'nearest') {
|
||||
// work out nearest value
|
||||
$hownear = array();
|
||||
foreach($gradeoptionsfull as $value => $option) {
|
||||
foreach ($gradeoptionsfull as $value => $option) {
|
||||
if ($grade==$value) {
|
||||
return $grade;
|
||||
}
|
||||
@@ -301,8 +300,7 @@ function match_grade_options($gradeoptionsfull, $grade, $matchgrades='error') {
|
||||
asort( $hownear, SORT_NUMERIC );
|
||||
reset( $hownear );
|
||||
return key( $hownear );
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -314,7 +312,8 @@ function match_grade_options($gradeoptionsfull, $grade, $matchgrades='error') {
|
||||
* @return boolean whether any question in this category is in use.
|
||||
*/
|
||||
function question_category_isused($categoryid, $recursive = false) {
|
||||
throw new coding_exception('question_category_isused has been deprectated. Please use question_category_in_use instead.');
|
||||
throw new coding_exception('question_category_isused has been deprectated. ' .
|
||||
'Please use question_category_in_use instead.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,7 +327,8 @@ function question_category_in_use($categoryid, $recursive = false) {
|
||||
global $DB;
|
||||
|
||||
//Look at each question in the category
|
||||
if ($questions = $DB->get_records_menu('question', array('category' => $categoryid), '', 'id,1')) {
|
||||
if ($questions = $DB->get_records_menu('question',
|
||||
array('category' => $categoryid), '', 'id, 1')) {
|
||||
if (questions_in_use(array_keys($questions))) {
|
||||
return true;
|
||||
}
|
||||
@@ -338,7 +338,8 @@ function question_category_in_use($categoryid, $recursive = false) {
|
||||
}
|
||||
|
||||
//Look under child categories recursively
|
||||
if ($children = $DB->get_records('question_categories', array('parent' => $categoryid), '', 'id,1')) {
|
||||
if ($children = $DB->get_records('question_categories',
|
||||
array('parent' => $categoryid), '', 'id, 1')) {
|
||||
foreach ($children as $child) {
|
||||
if (question_category_in_use($child->id, $recursive)) {
|
||||
return true;
|
||||
@@ -386,7 +387,8 @@ function question_delete_question($questionid) {
|
||||
$questionid, $question->contextid);
|
||||
|
||||
// Now recursively delete all child questions
|
||||
if ($children = $DB->get_records('question', array('parent' => $questionid), '', 'id,qtype')) {
|
||||
if ($children = $DB->get_records('question',
|
||||
array('parent' => $questionid), '', 'id, qtype')) {
|
||||
foreach ($children as $child) {
|
||||
if ($child->id != $questionid) {
|
||||
question_delete_question($child->id);
|
||||
@@ -414,7 +416,8 @@ function question_delete_course($course, $feedback=true) {
|
||||
//Cache some strings
|
||||
$strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
|
||||
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
|
||||
$categoriescourse = $DB->get_records('question_categories', array('contextid'=>$coursecontext->id), 'parent', 'id, parent, name, contextid');
|
||||
$categoriescourse = $DB->get_records('question_categories',
|
||||
array('contextid' => $coursecontext->id), 'parent', 'id, parent, name, contextid');
|
||||
|
||||
if ($categoriescourse) {
|
||||
|
||||
@@ -426,14 +429,15 @@ function question_delete_course($course, $feedback=true) {
|
||||
|
||||
//Delete it completely (questions and category itself)
|
||||
//deleting questions
|
||||
if ($questions = $DB->get_records('question', array('category' => $category->id), '', 'id,qtype')) {
|
||||
if ($questions = $DB->get_records('question',
|
||||
array('category' => $category->id), '', 'id,qtype')) {
|
||||
foreach ($questions as $question) {
|
||||
question_delete_question($question->id);
|
||||
}
|
||||
$DB->delete_records("question", array("category"=>$category->id));
|
||||
$DB->delete_records("question", array("category" => $category->id));
|
||||
}
|
||||
//delete the category
|
||||
$DB->delete_records('question_categories', array('id'=>$category->id));
|
||||
$DB->delete_records('question_categories', array('id' => $category->id));
|
||||
|
||||
//Fill feedback
|
||||
$feedbackdata[] = array($category->name, $strcatdeleted);
|
||||
@@ -441,7 +445,7 @@ function question_delete_course($course, $feedback=true) {
|
||||
//Inform about changes performed if feedback is enabled
|
||||
if ($feedback) {
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('category','quiz'), get_string('action'));
|
||||
$table->head = array(get_string('category', 'quiz'), get_string('action'));
|
||||
$table->data = $feedbackdata;
|
||||
echo html_writer::table($table);
|
||||
}
|
||||
@@ -455,7 +459,8 @@ function question_delete_course($course, $feedback=true) {
|
||||
* 2/ All questions are moved to new category
|
||||
*
|
||||
* @param object $category course category object
|
||||
* @param object $newcategory empty means everything deleted, otherwise id of category where content moved
|
||||
* @param object $newcategory empty means everything deleted, otherwise id of
|
||||
* category where content moved
|
||||
* @param boolean $feedback to specify if the process must output a summary of its work
|
||||
* @return boolean
|
||||
*/
|
||||
@@ -469,28 +474,34 @@ function question_delete_course_category($category, $newcategory, $feedback=true
|
||||
$strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
|
||||
|
||||
// Loop over question categories.
|
||||
if ($categories = $DB->get_records('question_categories', array('contextid'=>$context->id), 'parent', 'id, parent, name')) {
|
||||
if ($categories = $DB->get_records('question_categories',
|
||||
array('contextid'=>$context->id), 'parent', 'id, parent, name')) {
|
||||
foreach ($categories as $category) {
|
||||
|
||||
// Deal with any questions in the category.
|
||||
if ($questions = $DB->get_records('question', array('category' => $category->id), '', 'id,qtype')) {
|
||||
if ($questions = $DB->get_records('question',
|
||||
array('category' => $category->id), '', 'id,qtype')) {
|
||||
|
||||
// Try to delete each question.
|
||||
foreach ($questions as $question) {
|
||||
question_delete_question($question->id);
|
||||
}
|
||||
|
||||
// Check to see if there were any questions that were kept because they are
|
||||
// still in use somehow, even though quizzes in courses in this category will
|
||||
// already have been deteted. This could happen, for example, if questions are
|
||||
// added to a course, and then that course is moved to another category (MDL-14802).
|
||||
$questionids = $DB->get_records_menu('question', array('category'=>$category->id), '', 'id,1');
|
||||
// Check to see if there were any questions that were kept because
|
||||
// they are still in use somehow, even though quizzes in courses
|
||||
// in this category will already have been deteted. This could
|
||||
// happen, for example, if questions are added to a course,
|
||||
// and then that course is moved to another category (MDL-14802).
|
||||
$questionids = $DB->get_records_menu('question',
|
||||
array('category'=>$category->id), '', 'id, 1');
|
||||
if (!empty($questionids)) {
|
||||
if (!$rescueqcategory = question_save_from_deletion(array_keys($questionids),
|
||||
get_parent_contextid($context), print_context_name($context), $rescueqcategory)) {
|
||||
if (!$rescueqcategory = question_save_from_deletion(
|
||||
array_keys($questionids), get_parent_contextid($context),
|
||||
print_context_name($context), $rescueqcategory)) {
|
||||
return false;
|
||||
}
|
||||
$feedbackdata[] = array($category->name, get_string('questionsmovedto', 'question', $rescueqcategory->name));
|
||||
}
|
||||
$feedbackdata[] = array($category->name,
|
||||
get_string('questionsmovedto', 'question', $rescueqcategory->name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +517,7 @@ function question_delete_course_category($category, $newcategory, $feedback=true
|
||||
// Output feedback if requested.
|
||||
if ($feedback and $feedbackdata) {
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('questioncategory','question'), get_string('action'));
|
||||
$table->head = array(get_string('questioncategory', 'question'), get_string('action'));
|
||||
$table->data = $feedbackdata;
|
||||
echo html_writer::table($table);
|
||||
}
|
||||
@@ -516,12 +527,14 @@ function question_delete_course_category($category, $newcategory, $feedback=true
|
||||
if (!$newcontext = get_context_instance(CONTEXT_COURSECAT, $newcategory->id)) {
|
||||
return false;
|
||||
}
|
||||
$DB->set_field('question_categories', 'contextid', $newcontext->id, array('contextid'=>$context->id));
|
||||
$DB->set_field('question_categories', 'contextid', $newcontext->id,
|
||||
array('contextid'=>$context->id));
|
||||
if ($feedback) {
|
||||
$a = new stdClass();
|
||||
$a->oldplace = print_context_name($context);
|
||||
$a->newplace = print_context_name($newcontext);
|
||||
echo $OUTPUT->notification(get_string('movedquestionsandcategories', 'question', $a), 'notifysuccess');
|
||||
echo $OUTPUT->notification(
|
||||
get_string('movedquestionsandcategories', 'question', $a), 'notifysuccess');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,11 +546,13 @@ function question_delete_course_category($category, $newcategory, $feedback=true
|
||||
*
|
||||
* @param string $questionids list of questionids
|
||||
* @param object $newcontext the context to create the saved category in.
|
||||
* @param string $oldplace a textual description of the think being deleted, e.g. from get_context_name
|
||||
* @param string $oldplace a textual description of the think being deleted,
|
||||
* e.g. from get_context_name
|
||||
* @param object $newcategory
|
||||
* @return mixed false on
|
||||
*/
|
||||
function question_save_from_deletion($questionids, $newcontextid, $oldplace, $newcategory = null) {
|
||||
function question_save_from_deletion($questionids, $newcontextid, $oldplace,
|
||||
$newcategory = null) {
|
||||
global $DB;
|
||||
|
||||
// Make a category in the parent context to move the questions to.
|
||||
@@ -575,7 +590,8 @@ function question_delete_activity($cm, $feedback=true) {
|
||||
//Cache some strings
|
||||
$strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
|
||||
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
if ($categoriesmods = $DB->get_records('question_categories', array('contextid'=>$modcontext->id), 'parent', 'id, parent, name, contextid')){
|
||||
if ($categoriesmods = $DB->get_records('question_categories',
|
||||
array('contextid' => $modcontext->id), 'parent', 'id, parent, name, contextid')) {
|
||||
//Sort categories following their tree (parent-child) relationships
|
||||
//this will make the feedback more readable
|
||||
$categoriesmods = sort_categories_by_tree($categoriesmods);
|
||||
@@ -584,7 +600,8 @@ function question_delete_activity($cm, $feedback=true) {
|
||||
|
||||
//Delete it completely (questions and category itself)
|
||||
//deleting questions
|
||||
if ($questions = $DB->get_records('question', array('category' => $category->id), '', 'id,qtype')) {
|
||||
if ($questions = $DB->get_records('question',
|
||||
array('category' => $category->id), '', 'id,qtype')) {
|
||||
foreach ($questions as $question) {
|
||||
question_delete_question($question->id);
|
||||
}
|
||||
@@ -599,7 +616,7 @@ function question_delete_activity($cm, $feedback=true) {
|
||||
//Inform about changes performed if feedback is enabled
|
||||
if ($feedback) {
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('category','quiz'), get_string('action'));
|
||||
$table->head = array(get_string('category', 'quiz'), get_string('action'));
|
||||
$table->data = $feedbackdata;
|
||||
echo html_writer::table($table);
|
||||
}
|
||||
@@ -609,9 +626,10 @@ function question_delete_activity($cm, $feedback=true) {
|
||||
|
||||
/**
|
||||
* This function should be considered private to the question bank, it is called from
|
||||
* question/editlib.php question/contextmoveq.php and a few similar places to to the work of
|
||||
* acutally moving questions and associated data. However, callers of this function also have to
|
||||
* do other work, which is why you should not call this method directly from outside the questionbank.
|
||||
* question/editlib.php question/contextmoveq.php and a few similar places to to the
|
||||
* work of acutally moving questions and associated data. However, callers of this
|
||||
* function also have to do other work, which is why you should not call this method
|
||||
* directly from outside the questionbank.
|
||||
*
|
||||
* @param string $questionids a comma-separated list of question ids.
|
||||
* @param integer $newcategoryid the id of the category to move to.
|
||||
@@ -635,10 +653,12 @@ function question_move_questions_to_category($questionids, $newcategoryid) {
|
||||
}
|
||||
|
||||
// Move the questions themselves.
|
||||
$DB->set_field_select('question', 'category', $newcategoryid, "id $questionidcondition", $params);
|
||||
$DB->set_field_select('question', 'category', $newcategoryid,
|
||||
"id $questionidcondition", $params);
|
||||
|
||||
// Move any subquestions belonging to them.
|
||||
$DB->set_field_select('question', 'category', $newcategoryid, "parent $questionidcondition", $params);
|
||||
$DB->set_field_select('question', 'category', $newcategoryid,
|
||||
"parent $questionidcondition", $params);
|
||||
|
||||
// TODO Deal with datasets.
|
||||
|
||||
@@ -659,13 +679,15 @@ function question_move_category_to_context($categoryid, $oldcontextid, $newconte
|
||||
$questionids = $DB->get_records_menu('question',
|
||||
array('category' => $categoryid), '', 'id,qtype');
|
||||
foreach ($questionids as $questionid => $qtype) {
|
||||
question_bank::get_qtype($qtype)->move_files($questionid, $oldcontextid, $newcontextid);
|
||||
question_bank::get_qtype($qtype)->move_files(
|
||||
$questionid, $oldcontextid, $newcontextid);
|
||||
}
|
||||
|
||||
$subcatids = $DB->get_records_menu('question_categories',
|
||||
array('parent' => $categoryid), '', 'id,1');
|
||||
foreach ($subcatids as $subcatid => $notused) {
|
||||
$DB->set_field('question_categories', 'contextid', $newcontextid, array('id' => $subcatid));
|
||||
$DB->set_field('question_categories', 'contextid', $newcontextid,
|
||||
array('id' => $subcatid));
|
||||
question_move_category_to_context($subcatid, $oldcontextid, $newcontextid);
|
||||
}
|
||||
}
|
||||
@@ -693,9 +715,9 @@ function question_preview_url($questionid, $preferredbehaviour, $maxmark, $displ
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of ids, load the basic information about a set of questions from the questions table.
|
||||
* The $join and $extrafields arguments can be used together to pull in extra data.
|
||||
* See, for example, the usage in mod/quiz/attemptlib.php, and
|
||||
* Given a list of ids, load the basic information about a set of questions from
|
||||
* the questions table. The $join and $extrafields arguments can be used together
|
||||
* to pull in extra data. See, for example, the usage in mod/quiz/attemptlib.php, and
|
||||
* read the code below to see how the SQL is assembled. Throws exceptions on error.
|
||||
*
|
||||
* @global object
|
||||
@@ -709,7 +731,8 @@ function question_preview_url($questionid, $preferredbehaviour, $maxmark, $displ
|
||||
* @return array partially complete question objects. You need to call get_question_options
|
||||
* on them before they can be properly used.
|
||||
*/
|
||||
function question_preload_questions($questionids, $extrafields = '', $join = '', $extraparams = array()) {
|
||||
function question_preload_questions($questionids, $extrafields = '', $join = '',
|
||||
$extraparams = array()) {
|
||||
global $DB;
|
||||
if (empty($questionids)) {
|
||||
return array();
|
||||
@@ -815,12 +838,12 @@ function get_question_options(&$questions, $loadtags = false) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the icon for the question type
|
||||
*
|
||||
* @param object $question The question object for which the icon is required.
|
||||
* Only $question->qtype is used.
|
||||
* @return string the HTML for the img tag.
|
||||
*/
|
||||
* Print the icon for the question type
|
||||
*
|
||||
* @param object $question The question object for which the icon is required.
|
||||
* Only $question->qtype is used.
|
||||
* @return string the HTML for the img tag.
|
||||
*/
|
||||
function print_question_icon($question) {
|
||||
global $OUTPUT;
|
||||
|
||||
@@ -885,18 +908,23 @@ function sort_categories_by_tree(&$categories, $id = 0, $level = 1) {
|
||||
if (!isset($categories[$key]->processed) && $categories[$key]->parent == $id) {
|
||||
$children[$key] = $categories[$key];
|
||||
$categories[$key]->processed = true;
|
||||
$children = $children + sort_categories_by_tree($categories, $children[$key]->id, $level+1);
|
||||
$children = $children + sort_categories_by_tree(
|
||||
$categories, $children[$key]->id, $level+1);
|
||||
}
|
||||
}
|
||||
//If level = 1, we have finished, try to look for non processed categories (bad parent) and sort them too
|
||||
//If level = 1, we have finished, try to look for non processed categories
|
||||
// (bad parent) and sort them too
|
||||
if ($level == 1) {
|
||||
foreach ($keys as $key) {
|
||||
// If not processed and it's a good candidate to start (because its parent doesn't exist in the course)
|
||||
if (!isset($categories[$key]->processed) && !$DB->record_exists(
|
||||
'question_categories', array('contextid'=>$categories[$key]->contextid, 'id'=>$categories[$key]->parent))) {
|
||||
// If not processed and it's a good candidate to start (because its
|
||||
// parent doesn't exist in the course)
|
||||
if (!isset($categories[$key]->processed) && !$DB->record_exists('question_categories',
|
||||
array('contextid' => $categories[$key]->contextid,
|
||||
'id' => $categories[$key]->parent))) {
|
||||
$children[$key] = $categories[$key];
|
||||
$categories[$key]->processed = true;
|
||||
$children = $children + sort_categories_by_tree($categories, $children[$key]->id, $level+1);
|
||||
$children = $children + sort_categories_by_tree(
|
||||
$categories, $children[$key]->id, $level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -922,12 +950,14 @@ function flatten_category_tree(&$categories, $id, $depth = 0, $nochildrenof = -1
|
||||
// Indent the name of this category.
|
||||
$newcategories = array();
|
||||
$newcategories[$id] = $categories[$id];
|
||||
$newcategories[$id]->indentedname = str_repeat(' ', $depth) . $categories[$id]->name;
|
||||
$newcategories[$id]->indentedname = str_repeat(' ', $depth) .
|
||||
$categories[$id]->name;
|
||||
|
||||
// Recursively indent the children.
|
||||
foreach ($categories[$id]->childids as $childid) {
|
||||
if ($childid != $nochildrenof){
|
||||
$newcategories = $newcategories + flatten_category_tree($categories, $childid, $depth + 1, $nochildrenof);
|
||||
if ($childid != $nochildrenof) {
|
||||
$newcategories = $newcategories + flatten_category_tree(
|
||||
$categories, $childid, $depth + 1, $nochildrenof);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,8 +975,9 @@ function flatten_category_tree(&$categories, $id, $depth = 0, $nochildrenof = -1
|
||||
*/
|
||||
function add_indented_names($categories, $nochildrenof = -1) {
|
||||
|
||||
// Add an array to each category to hold the child category ids. This array will be removed
|
||||
// again by flatten_category_tree(). It should not be used outside these two functions.
|
||||
// Add an array to each category to hold the child category ids. This array
|
||||
// will be removed again by flatten_category_tree(). It should not be used
|
||||
// outside these two functions.
|
||||
foreach (array_keys($categories) as $id) {
|
||||
$categories[$id]->childids = array();
|
||||
}
|
||||
@@ -956,7 +987,8 @@ function add_indented_names($categories, $nochildrenof = -1) {
|
||||
// categories from other courses, but not their parents.
|
||||
$toplevelcategoryids = array();
|
||||
foreach (array_keys($categories) as $id) {
|
||||
if (!empty($categories[$id]->parent) && array_key_exists($categories[$id]->parent, $categories)) {
|
||||
if (!empty($categories[$id]->parent) &&
|
||||
array_key_exists($categories[$id]->parent, $categories)) {
|
||||
$categories[$categories[$id]->parent]->childids[] = $id;
|
||||
} else {
|
||||
$toplevelcategoryids[] = $id;
|
||||
@@ -966,7 +998,8 @@ function add_indented_names($categories, $nochildrenof = -1) {
|
||||
// Flatten the tree to and add the indents.
|
||||
$newcategories = array();
|
||||
foreach ($toplevelcategoryids as $id) {
|
||||
$newcategories = $newcategories + flatten_category_tree($categories, $id, 0, $nochildrenof);
|
||||
$newcategories = $newcategories + flatten_category_tree(
|
||||
$categories, $id, 0, $nochildrenof);
|
||||
}
|
||||
|
||||
return $newcategories;
|
||||
@@ -981,19 +1014,22 @@ function add_indented_names($categories, $nochildrenof = -1) {
|
||||
* @param integer $courseid the id of the course to get the categories for.
|
||||
* @param integer $published if true, include publised categories from other courses.
|
||||
* @param integer $only_editable if true, exclude categories this user is not allowed to edit.
|
||||
* @param integer $selected optionally, the id of a category to be selected by default in the dropdown.
|
||||
* @param integer $selected optionally, the id of a category to be selected by
|
||||
* default in the dropdown.
|
||||
*/
|
||||
function question_category_select_menu($contexts, $top = false, $currentcat = 0, $selected = "", $nochildrenof = -1) {
|
||||
function question_category_select_menu($contexts, $top = false, $currentcat = 0,
|
||||
$selected = "", $nochildrenof = -1) {
|
||||
global $OUTPUT;
|
||||
$categoriesarray = question_category_options($contexts, $top, $currentcat, false, $nochildrenof);
|
||||
$categoriesarray = question_category_options($contexts, $top, $currentcat,
|
||||
false, $nochildrenof);
|
||||
if ($selected) {
|
||||
$choose = '';
|
||||
} else {
|
||||
$choose = 'choosedots';
|
||||
}
|
||||
$options = array();
|
||||
foreach($categoriesarray as $group=>$opts) {
|
||||
$options[] = array($group=>$opts);
|
||||
foreach ($categoriesarray as $group => $opts) {
|
||||
$options[] = array($group => $opts);
|
||||
}
|
||||
|
||||
echo html_writer::select($options, 'category', $selected, $choose);
|
||||
@@ -1005,7 +1041,8 @@ function question_category_select_menu($contexts, $top = false, $currentcat = 0,
|
||||
*/
|
||||
function question_get_default_category($contextid) {
|
||||
global $DB;
|
||||
$category = $DB->get_records('question_categories', array('contextid' => $contextid),'id','*',0,1);
|
||||
$category = $DB->get_records('question_categories',
|
||||
array('contextid' => $contextid), 'id', '*', 0, 1);
|
||||
if (!empty($category)) {
|
||||
return reset($category);
|
||||
} else {
|
||||
@@ -1014,12 +1051,12 @@ function question_get_default_category($contextid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default category in the most specific context.
|
||||
* If no categories exist yet then default ones are created in all contexts.
|
||||
*
|
||||
* @param array $contexts The context objects for this context and all parent contexts.
|
||||
* @return object The default category - the category in the course context
|
||||
*/
|
||||
* Gets the default category in the most specific context.
|
||||
* If no categories exist yet then default ones are created in all contexts.
|
||||
*
|
||||
* @param array $contexts The context objects for this context and all parent contexts.
|
||||
* @return object The default category - the category in the course context
|
||||
*/
|
||||
function question_make_default_categories($contexts) {
|
||||
global $DB;
|
||||
static $preferredlevels = array(
|
||||
@@ -1033,7 +1070,8 @@ function question_make_default_categories($contexts) {
|
||||
$preferredness = 0;
|
||||
// If it already exists, just return it.
|
||||
foreach ($contexts as $key => $context) {
|
||||
if (!$exists = $DB->record_exists("question_categories", array('contextid'=>$context->id))) {
|
||||
if (!$exists = $DB->record_exists("question_categories",
|
||||
array('contextid' => $context->id))) {
|
||||
// Otherwise, we need to make one
|
||||
$category = new stdClass();
|
||||
$contextname = print_context_name($context, false, true);
|
||||
@@ -1041,14 +1079,15 @@ function question_make_default_categories($contexts) {
|
||||
$category->info = get_string('defaultinfofor', 'question', $contextname);
|
||||
$category->contextid = $context->id;
|
||||
$category->parent = 0;
|
||||
$category->sortorder = 999; // By default, all categories get this number, and are sorted alphabetically.
|
||||
// By default, all categories get this number, and are sorted alphabetically.
|
||||
$category->sortorder = 999;
|
||||
$category->stamp = make_unique_id_code();
|
||||
$category->id = $DB->insert_record('question_categories', $category);
|
||||
} else {
|
||||
$category = question_get_default_category($context->id);
|
||||
}
|
||||
if ($preferredlevels[$context->contextlevel] > $preferredness &&
|
||||
has_any_capability(array('moodle/question:usemine', 'moodle/question:useall'), $context)) {
|
||||
if ($preferredlevels[$context->contextlevel] > $preferredness && has_any_capability(
|
||||
array('moodle/question:usemine', 'moodle/question:useall'), $context)) {
|
||||
$toreturn = $category;
|
||||
$preferredness = $preferredlevels[$context->contextlevel];
|
||||
}
|
||||
@@ -1081,10 +1120,11 @@ function get_categories_for_contexts($contexts, $sortorder = 'parent, sortorder,
|
||||
/**
|
||||
* Output an array of question categories.
|
||||
*/
|
||||
function question_category_options($contexts, $top = false, $currentcat = 0, $popupform = false, $nochildrenof = -1) {
|
||||
function question_category_options($contexts, $top = false, $currentcat = 0,
|
||||
$popupform = false, $nochildrenof = -1) {
|
||||
global $CFG;
|
||||
$pcontexts = array();
|
||||
foreach($contexts as $context){
|
||||
foreach ($contexts as $context) {
|
||||
$pcontexts[] = $context->id;
|
||||
}
|
||||
$contextslist = join($pcontexts, ', ');
|
||||
@@ -1093,34 +1133,36 @@ function question_category_options($contexts, $top = false, $currentcat = 0, $po
|
||||
|
||||
$categories = question_add_context_in_key($categories);
|
||||
|
||||
if ($top){
|
||||
if ($top) {
|
||||
$categories = question_add_tops($categories, $pcontexts);
|
||||
}
|
||||
$categories = add_indented_names($categories, $nochildrenof);
|
||||
|
||||
//sort cats out into different contexts
|
||||
// sort cats out into different contexts
|
||||
$categoriesarray = array();
|
||||
foreach ($pcontexts as $pcontext){
|
||||
$contextstring = print_context_name(get_context_instance_by_id($pcontext), true, true);
|
||||
foreach ($pcontexts as $pcontext) {
|
||||
$contextstring = print_context_name(
|
||||
get_context_instance_by_id($pcontext), true, true);
|
||||
foreach ($categories as $category) {
|
||||
if ($category->contextid == $pcontext){
|
||||
if ($category->contextid == $pcontext) {
|
||||
$cid = $category->id;
|
||||
if ($currentcat!= $cid || $currentcat==0) {
|
||||
$countstring = (!empty($category->questioncount))?" ($category->questioncount)":'';
|
||||
if ($currentcat != $cid || $currentcat == 0) {
|
||||
$countstring = !empty($category->questioncount) ?
|
||||
" ($category->questioncount)" : '';
|
||||
$categoriesarray[$contextstring][$cid] = $category->indentedname.$countstring;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($popupform){
|
||||
if ($popupform) {
|
||||
$popupcats = array();
|
||||
foreach ($categoriesarray as $contextstring => $optgroup){
|
||||
foreach ($categoriesarray as $contextstring => $optgroup) {
|
||||
$group = array();
|
||||
foreach ($optgroup as $key=>$value) {
|
||||
foreach ($optgroup as $key => $value) {
|
||||
$key = str_replace($CFG->wwwroot, '', $key);
|
||||
$group[$key] = $value;
|
||||
}
|
||||
$popupcats[] = array($contextstring=>$group);
|
||||
$popupcats[] = array($contextstring => $group);
|
||||
}
|
||||
return $popupcats;
|
||||
} else {
|
||||
@@ -1128,7 +1170,7 @@ function question_category_options($contexts, $top = false, $currentcat = 0, $po
|
||||
}
|
||||
}
|
||||
|
||||
function question_add_context_in_key($categories){
|
||||
function question_add_context_in_key($categories) {
|
||||
$newcatarray = array();
|
||||
foreach ($categories as $id => $category) {
|
||||
$category->parent = "$category->parent,$category->contextid";
|
||||
@@ -1138,9 +1180,9 @@ function question_add_context_in_key($categories){
|
||||
return $newcatarray;
|
||||
}
|
||||
|
||||
function question_add_tops($categories, $pcontexts){
|
||||
function question_add_tops($categories, $pcontexts) {
|
||||
$topcats = array();
|
||||
foreach ($pcontexts as $context){
|
||||
foreach ($pcontexts as $context) {
|
||||
$newcat = new stdClass();
|
||||
$newcat->id = "0,$context";
|
||||
$newcat->name = get_string('top');
|
||||
@@ -1158,7 +1200,8 @@ function question_add_tops($categories, $pcontexts){
|
||||
function question_categorylist($categoryid) {
|
||||
global $DB;
|
||||
|
||||
$subcategories = $DB->get_records('question_categories', array('parent' => $categoryid), 'sortorder ASC', 'id, 1');
|
||||
$subcategories = $DB->get_records('question_categories',
|
||||
array('parent' => $categoryid), 'sortorder ASC', 'id, 1');
|
||||
|
||||
$categorylist = array($categoryid);
|
||||
foreach ($subcategories as $subcategory) {
|
||||
@@ -1211,12 +1254,12 @@ function get_import_export_formats($type) {
|
||||
|
||||
|
||||
/**
|
||||
* Create a reasonable default file name for exporting questions from a particular
|
||||
* category.
|
||||
* @param object $course the course the questions are in.
|
||||
* @param object $category the question category.
|
||||
* @return string the filename.
|
||||
*/
|
||||
* Create a reasonable default file name for exporting questions from a particular
|
||||
* category.
|
||||
* @param object $course the course the questions are in.
|
||||
* @param object $category the question category.
|
||||
* @return string the filename.
|
||||
*/
|
||||
function question_default_export_filename($course, $category) {
|
||||
// We build a string that is an appropriate name (questions) from the lang pack,
|
||||
// then the corse shortname, then the question category name, then a timestamp.
|
||||
@@ -1265,10 +1308,10 @@ class context_to_string_translator{
|
||||
}
|
||||
|
||||
protected function generate_context_to_string_array($contexts) {
|
||||
if (!$this->contexttostringarray){
|
||||
if (!$this->contexttostringarray) {
|
||||
$catno = 1;
|
||||
foreach ($contexts as $context){
|
||||
switch ($context->contextlevel){
|
||||
foreach ($contexts as $context) {
|
||||
switch ($context->contextlevel) {
|
||||
case CONTEXT_MODULE :
|
||||
$contextstring = 'module';
|
||||
break;
|
||||
@@ -1298,7 +1341,7 @@ class context_to_string_translator{
|
||||
* @param integer $cachecat useful to cache all question records in a category
|
||||
* @return boolean this user has the capability $cap for this question $question?
|
||||
*/
|
||||
function question_has_capability_on($question, $cap, $cachecat = -1){
|
||||
function question_has_capability_on($question, $cap, $cachecat = -1) {
|
||||
global $USER, $DB;
|
||||
|
||||
// these are capabilities on existing questions capabilties are
|
||||
@@ -1311,26 +1354,28 @@ function question_has_capability_on($question, $cap, $cachecat = -1){
|
||||
$questions += $DB->get_records('question', array('category' => $cachecat));
|
||||
$cachedcat[] = $cachecat;
|
||||
}
|
||||
if (!is_object($question)){
|
||||
if (!isset($questions[$question])){
|
||||
if (!$questions[$question] = $DB->get_record('question', array('id' => $question), 'id,category,createdby')) {
|
||||
if (!is_object($question)) {
|
||||
if (!isset($questions[$question])) {
|
||||
if (!$questions[$question] = $DB->get_record('question',
|
||||
array('id' => $question), 'id,category,createdby')) {
|
||||
print_error('questiondoesnotexist', 'question');
|
||||
}
|
||||
}
|
||||
$question = $questions[$question];
|
||||
}
|
||||
if (!isset($categories[$question->category])){
|
||||
if (!$categories[$question->category] = $DB->get_record('question_categories', array('id'=>$question->category))) {
|
||||
if (!isset($categories[$question->category])) {
|
||||
if (!$categories[$question->category] = $DB->get_record('question_categories',
|
||||
array('id'=>$question->category))) {
|
||||
print_error('invalidcategory', 'quiz');
|
||||
}
|
||||
}
|
||||
$category = $categories[$question->category];
|
||||
$context = get_context_instance_by_id($category->contextid);
|
||||
|
||||
if (array_search($cap, $question_questioncaps)!== FALSE){
|
||||
if (!has_capability('moodle/question:'.$cap.'all', $context)){
|
||||
if ($question->createdby == $USER->id){
|
||||
return has_capability('moodle/question:'.$cap.'mine', $context);
|
||||
if (array_search($cap, $question_questioncaps)!== false) {
|
||||
if (!has_capability('moodle/question:' . $cap . 'all', $context)) {
|
||||
if ($question->createdby == $USER->id) {
|
||||
return has_capability('moodle/question:' . $cap . 'mine', $context);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1338,7 +1383,7 @@ function question_has_capability_on($question, $cap, $cachecat = -1){
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return has_capability('moodle/question:'.$cap, $context);
|
||||
return has_capability('moodle/question:' . $cap, $context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1346,8 +1391,8 @@ function question_has_capability_on($question, $cap, $cachecat = -1){
|
||||
/**
|
||||
* Require capability on question.
|
||||
*/
|
||||
function question_require_capability_on($question, $cap){
|
||||
if (!question_has_capability_on($question, $cap)){
|
||||
function question_require_capability_on($question, $cap) {
|
||||
if (!question_has_capability_on($question, $cap)) {
|
||||
print_error('nopermissions', '', '', $cap);
|
||||
}
|
||||
return true;
|
||||
@@ -1364,7 +1409,7 @@ function question_get_real_state($state) {
|
||||
global $OUTPUT;
|
||||
$realstate = clone($state);
|
||||
$matches = array();
|
||||
if (!preg_match('|^random([0-9]+)-(.*)|', $state->answer, $matches)){
|
||||
if (!preg_match('|^random([0-9]+)-(.*)|', $state->answer, $matches)) {
|
||||
echo $OUTPUT->notification(get_string('errorrandom', 'quiz_statistics'));
|
||||
return false;
|
||||
} else {
|
||||
@@ -1421,20 +1466,25 @@ function question_extend_settings_navigation(navigation_node $navigationnode, $c
|
||||
return;
|
||||
}
|
||||
|
||||
$questionnode = $navigationnode->add(get_string('questionbank','question'), new moodle_url('/question/edit.php', $params), navigation_node::TYPE_CONTAINER);
|
||||
$questionnode = $navigationnode->add(get_string('questionbank', 'question'),
|
||||
new moodle_url('/question/edit.php', $params), navigation_node::TYPE_CONTAINER);
|
||||
|
||||
$contexts = new question_edit_contexts($context);
|
||||
if ($contexts->have_one_edit_tab_cap('questions')) {
|
||||
$questionnode->add(get_string('questions', 'quiz'), new moodle_url('/question/edit.php', $params), navigation_node::TYPE_SETTING);
|
||||
$questionnode->add(get_string('questions', 'quiz'), new moodle_url(
|
||||
'/question/edit.php', $params), navigation_node::TYPE_SETTING);
|
||||
}
|
||||
if ($contexts->have_one_edit_tab_cap('categories')) {
|
||||
$questionnode->add(get_string('categories', 'quiz'), new moodle_url('/question/category.php', $params), navigation_node::TYPE_SETTING);
|
||||
$questionnode->add(get_string('categories', 'quiz'), new moodle_url(
|
||||
'/question/category.php', $params), navigation_node::TYPE_SETTING);
|
||||
}
|
||||
if ($contexts->have_one_edit_tab_cap('import')) {
|
||||
$questionnode->add(get_string('import', 'quiz'), new moodle_url('/question/import.php', $params), navigation_node::TYPE_SETTING);
|
||||
$questionnode->add(get_string('import', 'quiz'), new moodle_url(
|
||||
'/question/import.php', $params), navigation_node::TYPE_SETTING);
|
||||
}
|
||||
if ($contexts->have_one_edit_tab_cap('export')) {
|
||||
$questionnode->add(get_string('export', 'quiz'), new moodle_url('/question/export.php', $params), navigation_node::TYPE_SETTING);
|
||||
$questionnode->add(get_string('export', 'quiz'), new moodle_url(
|
||||
'/question/export.php', $params), navigation_node::TYPE_SETTING);
|
||||
}
|
||||
|
||||
return $questionnode;
|
||||
@@ -1469,7 +1519,7 @@ function question_get_all_capabilities() {
|
||||
|
||||
class question_edit_contexts {
|
||||
|
||||
public static $CAPS = array(
|
||||
public static $caps = array(
|
||||
'editq' => array('moodle/question:add',
|
||||
'moodle/question:editmine',
|
||||
'moodle/question:editall',
|
||||
@@ -1495,10 +1545,10 @@ class question_edit_contexts {
|
||||
/**
|
||||
* @param current context
|
||||
*/
|
||||
public function question_edit_contexts($thiscontext) {
|
||||
public function __construct($thiscontext) {
|
||||
$pcontextids = get_parent_contexts($thiscontext);
|
||||
$contexts = array($thiscontext);
|
||||
foreach ($pcontextids as $pcontextid){
|
||||
foreach ($pcontextids as $pcontextid) {
|
||||
$contexts[] = get_context_instance_by_id($pcontextid);
|
||||
}
|
||||
$this->allcontexts = $contexts;
|
||||
@@ -1521,8 +1571,8 @@ class question_edit_contexts {
|
||||
*/
|
||||
public function having_cap($cap) {
|
||||
$contextswithcap = array();
|
||||
foreach ($this->allcontexts as $context){
|
||||
if (has_capability($cap, $context)){
|
||||
foreach ($this->allcontexts as $context) {
|
||||
if (has_capability($cap, $context)) {
|
||||
$contextswithcap[] = $context;
|
||||
}
|
||||
}
|
||||
@@ -1534,9 +1584,9 @@ class question_edit_contexts {
|
||||
*/
|
||||
public function having_one_cap($caps) {
|
||||
$contextswithacap = array();
|
||||
foreach ($this->allcontexts as $context){
|
||||
foreach ($caps as $cap){
|
||||
if (has_capability($cap, $context)){
|
||||
foreach ($this->allcontexts as $context) {
|
||||
foreach ($caps as $cap) {
|
||||
if (has_capability($cap, $context)) {
|
||||
$contextswithacap[] = $context;
|
||||
break; //done with caps loop
|
||||
}
|
||||
@@ -1549,7 +1599,7 @@ class question_edit_contexts {
|
||||
* @return array parent contexts having at least one of $caps, zero based index
|
||||
*/
|
||||
public function having_one_edit_tab_cap($tabname) {
|
||||
return $this->having_one_cap(self::$CAPS[$tabname]);
|
||||
return $this->having_one_cap(self::$caps[$tabname]);
|
||||
}
|
||||
/**
|
||||
* Has at least one parent context got the cap $cap?
|
||||
@@ -1582,8 +1632,8 @@ class question_edit_contexts {
|
||||
* @param string $tabname edit tab name
|
||||
* @return boolean
|
||||
*/
|
||||
public function have_one_edit_tab_cap($tabname){
|
||||
return $this->have_one_cap(self::$CAPS[$tabname]);
|
||||
public function have_one_edit_tab_cap($tabname) {
|
||||
return $this->have_one_cap(self::$caps[$tabname]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1591,8 +1641,8 @@ class question_edit_contexts {
|
||||
*
|
||||
* @param string $cap capability
|
||||
*/
|
||||
public function require_cap($cap){
|
||||
if (!$this->have_cap($cap)){
|
||||
public function require_cap($cap) {
|
||||
if (!$this->have_cap($cap)) {
|
||||
print_error('nopermissions', '', '', $cap);
|
||||
}
|
||||
}
|
||||
@@ -1602,7 +1652,7 @@ class question_edit_contexts {
|
||||
*
|
||||
* @param array $cap capabilities
|
||||
*/
|
||||
public function require_one_cap($caps) {
|
||||
public function require_one_cap($caps) {
|
||||
if (!$this->have_one_cap($caps)) {
|
||||
$capsstring = join($caps, ', ');
|
||||
print_error('nopermissions', '', '', $capsstring);
|
||||
@@ -1614,7 +1664,7 @@ class question_edit_contexts {
|
||||
*
|
||||
* @param string $tabname edit tab name
|
||||
*/
|
||||
public function require_one_edit_tab_cap($tabname){
|
||||
public function require_one_edit_tab_cap($tabname) {
|
||||
if (!$this->have_one_edit_tab_cap($tabname)) {
|
||||
print_error('nopermissions', '', '', 'access question edit tab '.$tabname);
|
||||
}
|
||||
@@ -1637,7 +1687,8 @@ class question_edit_contexts {
|
||||
* @param array $options
|
||||
* @return string
|
||||
*/
|
||||
function question_rewrite_question_urls($text, $file, $contextid, $component, $filearea, array $ids, $itemid, array $options=null) {
|
||||
function question_rewrite_question_urls($text, $file, $contextid, $component,
|
||||
$filearea, array $ids, $itemid, array $options=null) {
|
||||
global $CFG;
|
||||
|
||||
$options = (array)$options;
|
||||
@@ -1745,11 +1796,6 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
//DEBUG
|
||||
//echo '<textarea cols=90 rows=20>';
|
||||
//echo $content;
|
||||
//echo '</textarea>';
|
||||
//die;
|
||||
send_file($content, $filename, 0, 0, true, true, $qformat->mime_type());
|
||||
}
|
||||
|
||||
@@ -1793,8 +1839,11 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
|
||||
* @param string $ithcontexts
|
||||
* @param moodle_url export file url
|
||||
*/
|
||||
function question_make_export_url($contextid, $categoryid, $format, $withcategories, $withcontexts, $filename) {
|
||||
function question_make_export_url($contextid, $categoryid, $format, $withcategories,
|
||||
$withcontexts, $filename) {
|
||||
global $CFG;
|
||||
$urlbase = "$CFG->httpswwwroot/pluginfile.php";
|
||||
return moodle_url::make_file_url($urlbase, "/$contextid/question/export/{$categoryid}/{$format}/{$withcategories}/{$withcontexts}/{$filename}", true);
|
||||
return moodle_url::make_file_url($urlbase,
|
||||
"/$contextid/question/export/{$categoryid}/{$format}/{$withcategories}" .
|
||||
"/{$withcontexts}/{$filename}", true);
|
||||
}
|
||||
|
||||
+60
-60
@@ -806,13 +806,13 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
define('QUIZ_OLD_OPEN', 0x3c00fc0);
|
||||
define('QUIZ_OLD_CLOSED', 0x3c03f000);
|
||||
|
||||
define('QUIZ_OLD_RESPONSES', 1*0x1041); // Show responses
|
||||
define('QUIZ_OLD_SCORES', 2*0x1041); // Show scores
|
||||
define('QUIZ_OLD_FEEDBACK', 4*0x1041); // Show question feedback
|
||||
define('QUIZ_OLD_ANSWERS', 8*0x1041); // Show correct answers
|
||||
define('QUIZ_OLD_SOLUTIONS', 16*0x1041); // Show solutions
|
||||
define('QUIZ_OLD_GENERALFEEDBACK',32*0x1041); // Show question general feedback
|
||||
define('QUIZ_OLD_OVERALLFEEDBACK', 1*0x4440000); // Show quiz overall feedback
|
||||
define('QUIZ_OLD_RESPONSES', 1*0x1041); // Show responses
|
||||
define('QUIZ_OLD_SCORES', 2*0x1041); // Show scores
|
||||
define('QUIZ_OLD_FEEDBACK', 4*0x1041); // Show question feedback
|
||||
define('QUIZ_OLD_ANSWERS', 8*0x1041); // Show correct answers
|
||||
define('QUIZ_OLD_SOLUTIONS', 16*0x1041); // Show solutions
|
||||
define('QUIZ_OLD_GENERALFEEDBACK', 32*0x1041); // Show question general feedback
|
||||
define('QUIZ_OLD_OVERALLFEEDBACK', 1*0x4440000); // Show quiz overall feedback
|
||||
|
||||
// Copy the old review settings
|
||||
if ($oldversion < 2011051214) {
|
||||
@@ -820,13 +820,13 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewattempt = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
QUIZ_NEW_DURING,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_RESPONSES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_RESPONSES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_RESPONSES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
QUIZ_NEW_DURING,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_RESPONSES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_RESPONSES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_RESPONSES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -839,13 +839,13 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewcorrectness = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
QUIZ_NEW_DURING,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
QUIZ_NEW_DURING,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -858,13 +858,13 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewmarks = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
QUIZ_NEW_DURING,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
QUIZ_NEW_DURING,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -877,14 +877,14 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewspecificfeedback = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_FEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -897,14 +897,14 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewgeneralfeedback = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_GENERALFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -917,14 +917,14 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewrightanswer = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_ANSWERS) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -937,13 +937,13 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
$DB->execute("
|
||||
UPDATE {quiz}
|
||||
SET reviewoverallfeedback = " . $DB->sql_bitor($DB->sql_bitor(
|
||||
0,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_OVERALLFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_OVERALLFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_OVERALLFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
0,
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_OVERALLFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_OVERALLFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
|
||||
'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_OVERALLFEEDBACK) .
|
||||
' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
|
||||
");
|
||||
}
|
||||
|
||||
@@ -1048,7 +1048,7 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
}
|
||||
|
||||
if ($oldversion < 2011051225) {
|
||||
// Define table quiz_report to be renamed to quiz_reports
|
||||
// Define table quiz_report to be renamed to quiz_reports
|
||||
$table = new xmldb_table('quiz_report');
|
||||
|
||||
// Launch rename table for quiz_reports
|
||||
|
||||
+179
-128
@@ -52,7 +52,8 @@ function quiz_remove_question($quiz, $questionid) {
|
||||
unset($questionids[$key]);
|
||||
$quiz->questions = implode(',', $questionids);
|
||||
$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id));
|
||||
$DB->delete_records('quiz_question_instances', array('quiz' => $quiz->instance, 'question' => $questionid));
|
||||
$DB->delete_records('quiz_question_instances',
|
||||
array('quiz' => $quiz->instance, 'question' => $questionid));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +87,8 @@ function quiz_delete_empty_page($layout, $index) {
|
||||
* @param int $id The id of the question to be added
|
||||
* @param object $quiz The extended quiz object as used by edit.php
|
||||
* This is updated by this function
|
||||
* @param int $page Which page in quiz to add the question on. If 0 (default), add at the end
|
||||
* @param int $page Which page in quiz to add the question on. If 0 (default),
|
||||
* add at the end
|
||||
* @return bool false if the question was already in the quiz
|
||||
*/
|
||||
function quiz_add_quiz_question($id, $quiz, $page = 0) {
|
||||
@@ -150,7 +152,8 @@ function quiz_add_quiz_question($id, $quiz, $page = 0) {
|
||||
$DB->insert_record('quiz_question_instances', $instance);
|
||||
}
|
||||
|
||||
function quiz_add_random_questions($quiz, $addonpage, $categoryid, $number, $includesubcategories) {
|
||||
function quiz_add_random_questions($quiz, $addonpage, $categoryid, $number,
|
||||
$includesubcategories) {
|
||||
global $DB;
|
||||
|
||||
$category = $DB->get_record('question_categories', array('id' => $categoryid));
|
||||
@@ -168,7 +171,10 @@ function quiz_add_random_questions($quiz, $addonpage, $categoryid, $number, $inc
|
||||
WHERE qtype = 'random'
|
||||
AND category = ?
|
||||
AND " . $DB->sql_compare_text('questiontext') . " = ?
|
||||
AND NOT EXISTS (SELECT * FROM {quiz_question_instances} WHERE question = q.id)
|
||||
AND NOT EXISTS (
|
||||
SELECT *
|
||||
FROM {quiz_question_instances}
|
||||
WHERE question = q.id)
|
||||
ORDER BY id", array($category->id, $includesubcategories))) {
|
||||
// Take as many of these as needed.
|
||||
while (($existingquestion = array_shift($existingquestions)) && $number > 0) {
|
||||
@@ -464,7 +470,8 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
|
||||
$fakequestion->id = 0;
|
||||
$fakequestion->qtype = 'missingtype';
|
||||
$fakequestion->name = get_string('deletedquestion', 'qtype_missingtype');
|
||||
$fakequestion->questiontext = '<p>' . get_string('deletedquestion', 'qtype_missing') . '</p>';
|
||||
$fakequestion->questiontext = '<p>' .
|
||||
get_string('deletedquestion', 'qtype_missing') . '</p>';
|
||||
$fakequestion->length = 0;
|
||||
$questions[$qnum] = $fakequestion;
|
||||
$quiz->grades[$qnum] = 0;
|
||||
@@ -491,9 +498,11 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
|
||||
echo '</div>';
|
||||
if ($allowdelete) {
|
||||
echo '<div class="quizpagedelete">';
|
||||
echo $OUTPUT->action_icon($pageurl->out(true, array('deleteemptypage' => $count - 1, 'sesskey'=>sesskey())),
|
||||
echo $OUTPUT->action_icon($pageurl->out(true,
|
||||
array('deleteemptypage' => $count - 1, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/delete', $strremove),
|
||||
new component_action('click', 'M.core_scroll_manager.save_scroll_action'),
|
||||
new component_action('click',
|
||||
'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strremove));
|
||||
echo '</div>';
|
||||
}
|
||||
@@ -511,77 +520,84 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
|
||||
//this is an actual question
|
||||
|
||||
/* Display question start */
|
||||
?>
|
||||
?>
|
||||
<div class="question">
|
||||
<div class="questioncontainer <?php echo $question->qtype; ?>">
|
||||
<div class="qnum">
|
||||
<?php
|
||||
$reordercheckbox = '';
|
||||
$reordercheckboxlabel = '';
|
||||
$reordercheckboxlabelclose = '';
|
||||
if ($reordertool) {
|
||||
$reordercheckbox = '<input type="checkbox" name="s' . $question->id .
|
||||
'" id="s' . $question->id . '" />';
|
||||
$reordercheckboxlabel = '<label for="s' . $question->id . '">';
|
||||
$reordercheckboxlabelclose = '</label>';
|
||||
}
|
||||
if (!$quiz->shufflequestions) {
|
||||
// Print and increment question number
|
||||
$questioncountstring = '';
|
||||
if ($questioncount>999 || ($reordertool && $questioncount>99)) {
|
||||
$questioncountstring =
|
||||
"$reordercheckboxlabel<small>$questioncount</small>" .
|
||||
$reordercheckboxlabelclose . $reordercheckbox;
|
||||
<?php
|
||||
$reordercheckbox = '';
|
||||
$reordercheckboxlabel = '';
|
||||
$reordercheckboxlabelclose = '';
|
||||
if ($reordertool) {
|
||||
$reordercheckbox = '<input type="checkbox" name="s' . $question->id .
|
||||
'" id="s' . $question->id . '" />';
|
||||
$reordercheckboxlabel = '<label for="s' . $question->id . '">';
|
||||
$reordercheckboxlabelclose = '</label>';
|
||||
}
|
||||
if (!$quiz->shufflequestions) {
|
||||
// Print and increment question number
|
||||
$questioncountstring = '';
|
||||
if ($questioncount>999 || ($reordertool && $questioncount>99)) {
|
||||
$questioncountstring =
|
||||
"$reordercheckboxlabel<small>$questioncount</small>" .
|
||||
$reordercheckboxlabelclose . $reordercheckbox;
|
||||
} else {
|
||||
$questioncountstring = $reordercheckboxlabel . $questioncount .
|
||||
$reordercheckboxlabelclose . $reordercheckbox;
|
||||
}
|
||||
echo $questioncountstring;
|
||||
$qno += $question->length;
|
||||
} else {
|
||||
$questioncountstring = $reordercheckboxlabel . $questioncount .
|
||||
$reordercheckboxlabelclose . $reordercheckbox;
|
||||
echo "$reordercheckboxlabel ? $reordercheckboxlabelclose" .
|
||||
" $reordercheckbox";
|
||||
}
|
||||
echo $questioncountstring;
|
||||
$qno += $question->length;
|
||||
} else {
|
||||
echo "$reordercheckboxlabel ? $reordercheckboxlabelclose" .
|
||||
" $reordercheckbox";
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="questioncontrols">
|
||||
<?php
|
||||
if ($count != 0) {
|
||||
if (!$hasattempts) {
|
||||
$upbuttonclass = '';
|
||||
if ($count >= $lastindex - 1) {
|
||||
$upbuttonclass = 'upwithoutdown';
|
||||
if ($count != 0) {
|
||||
if (!$hasattempts) {
|
||||
$upbuttonclass = '';
|
||||
if ($count >= $lastindex - 1) {
|
||||
$upbuttonclass = 'upwithoutdown';
|
||||
}
|
||||
echo $OUTPUT->action_icon($pageurl->out(true,
|
||||
array('up' => $question->id, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/up', $strmoveup),
|
||||
new component_action('click',
|
||||
'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strmoveup));
|
||||
}
|
||||
echo $OUTPUT->action_icon($pageurl->out(true, array('up' => $question->id, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/up', $strmoveup),
|
||||
new component_action('click', 'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strmoveup));
|
||||
}
|
||||
|
||||
}
|
||||
if ($count < $lastindex - 1) {
|
||||
if (!$hasattempts) {
|
||||
echo $OUTPUT->action_icon($pageurl->out(true, array('down' => $question->id, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/down', $strmovedown),
|
||||
new component_action('click', 'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strmovedown));
|
||||
}
|
||||
}
|
||||
if ($allowdelete && (empty($question->id) || question_has_capability_on($question, 'use', $question->category))) {
|
||||
// remove from quiz, not question delete.
|
||||
if (!$hasattempts) {
|
||||
echo $OUTPUT->action_icon($pageurl->out(true, array('remove' => $question->id, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/delete', $strremove),
|
||||
new component_action('click', 'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strremove));
|
||||
if ($count < $lastindex - 1) {
|
||||
if (!$hasattempts) {
|
||||
echo $OUTPUT->action_icon($pageurl->out(true,
|
||||
array('down' => $question->id, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/down', $strmovedown),
|
||||
new component_action('click',
|
||||
'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strmovedown));
|
||||
}
|
||||
}
|
||||
if ($allowdelete && (empty($question->id) ||
|
||||
question_has_capability_on($question, 'use', $question->category))) {
|
||||
// remove from quiz, not question delete.
|
||||
if (!$hasattempts) {
|
||||
echo $OUTPUT->action_icon($pageurl->out(true,
|
||||
array('remove' => $question->id, 'sesskey'=>sesskey())),
|
||||
new pix_icon('t/delete', $strremove),
|
||||
new component_action('click',
|
||||
'M.core_scroll_manager.save_scroll_action'),
|
||||
array('title' => $strremove));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div><?php
|
||||
if ($question->qtype != 'description' && !$reordertool) {
|
||||
?>
|
||||
if ($question->qtype != 'description' && !$reordertool) {
|
||||
?>
|
||||
<div class="points">
|
||||
<form method="post" action="edit.php" class="quizsavegradesform"><div>
|
||||
<fieldset class="invisiblefieldset" style="display: block;">
|
||||
@@ -589,66 +605,71 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
|
||||
<input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
|
||||
<?php echo html_writer::input_hidden_params($pageurl); ?>
|
||||
<input type="hidden" name="savechanges" value="save" />
|
||||
<?php
|
||||
echo '<input type="text" name="g' . $question->id . '" id="inputq' . $question->id .
|
||||
'" size="' . ($quiz->decimalpoints + 2) . '" value="' . (0 + $quiz->grades[$qnum]) .
|
||||
'" tabindex="' . ($lastindex + $qno) . '" />';
|
||||
?>
|
||||
<?php
|
||||
echo '<input type="text" name="g' . $question->id .
|
||||
'" id="inputq' . $question->id .
|
||||
'" size="' . ($quiz->decimalpoints + 2) .
|
||||
'" value="' . (0 + $quiz->grades[$qnum]) .
|
||||
'" tabindex="' . ($lastindex + $qno) . '" />';
|
||||
?>
|
||||
<input type="submit" class="pointssubmitbutton" value="<?php echo $strsave; ?>" />
|
||||
</fieldset>
|
||||
<?php if ($question->qtype == 'random') {
|
||||
echo '<a href="' . $questionurl->out() . '" class="configurerandomquestion">' . get_string("configurerandomquestion", "quiz") . '</a>';
|
||||
}
|
||||
<?php
|
||||
if ($question->qtype == 'random') {
|
||||
echo '<a href="' . $questionurl->out() .
|
||||
'" class="configurerandomquestion">' .
|
||||
get_string("configurerandomquestion", "quiz") . '</a>';
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
} else if ($reordertool) {
|
||||
if ($qnum) {
|
||||
?>
|
||||
<?php
|
||||
} else if ($reordertool) {
|
||||
if ($qnum) {
|
||||
?>
|
||||
<div class="qorder">
|
||||
<?php
|
||||
echo '<input type="text" name="o' . $question->id . '" size="2" value="' .
|
||||
(10*$count + 10) .
|
||||
'" tabindex="' . ($lastindex + $qno) .
|
||||
'" />';
|
||||
?>
|
||||
<?php
|
||||
echo '<input type="text" name="o' . $question->id .
|
||||
'" size="2" value="' . (10*$count + 10) .
|
||||
'" tabindex="' . ($lastindex + $qno) . '" />';
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
?>
|
||||
<div class="questioncontentcontainer">
|
||||
<?php
|
||||
if ($question->qtype == 'random') { // it is a random question
|
||||
if (!$reordertool) {
|
||||
quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool);
|
||||
} else {
|
||||
quiz_print_randomquestion_reordertool($question, $pageurl, $quiz);
|
||||
<?php
|
||||
if ($question->qtype == 'random') { // it is a random question
|
||||
if (!$reordertool) {
|
||||
quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool);
|
||||
} else {
|
||||
quiz_print_randomquestion_reordertool($question, $pageurl, $quiz);
|
||||
}
|
||||
} else { // it is a single question
|
||||
if (!$reordertool) {
|
||||
quiz_print_singlequestion($question, $returnurl, $quiz);
|
||||
} else {
|
||||
quiz_print_singlequestion_reordertool($question, $returnurl, $quiz);
|
||||
}
|
||||
}
|
||||
} else { // it is a single question
|
||||
if (!$reordertool) {
|
||||
quiz_print_singlequestion($question, $returnurl, $quiz);
|
||||
} else {
|
||||
quiz_print_singlequestion_reordertool($question, $returnurl, $quiz);
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
<?php
|
||||
}
|
||||
}
|
||||
//a page break: end the existing page.
|
||||
if ($qnum == 0) {
|
||||
if ($pageopen) {
|
||||
if (!$reordertool && !($quiz->shufflequestions && $count < $questiontotalcount - 1)) {
|
||||
if (!$reordertool && !($quiz->shufflequestions &&
|
||||
$count < $questiontotalcount - 1)) {
|
||||
quiz_print_pagecontrols($quiz, $pageurl, $pagecount,
|
||||
$hasattempts, $defaultcategoryobj);
|
||||
} else if ($count < $questiontotalcount - 1) {
|
||||
@@ -661,10 +682,13 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
|
||||
|
||||
if (!$reordertool && !$quiz->shufflequestions) {
|
||||
echo $OUTPUT->container_start('addpage');
|
||||
$url = new moodle_url($pageurl->out_omit_querystring(), array('cmid' => $quiz->cmid, 'courseid' => $quiz->course, 'addpage' => $count, 'sesskey' => sesskey()));
|
||||
$url = new moodle_url($pageurl->out_omit_querystring(),
|
||||
array('cmid' => $quiz->cmid, 'courseid' => $quiz->course,
|
||||
'addpage' => $count, 'sesskey' => sesskey()));
|
||||
echo $OUTPUT->single_button($url, get_string('addpagehere', 'quiz'), 'post',
|
||||
array('disabled' => $hasattempts,
|
||||
'actions' => array(new component_action('click', 'M.core_scroll_manager.save_scroll_action'))));
|
||||
'actions' => array(new component_action('click',
|
||||
'M.core_scroll_manager.save_scroll_action'))));
|
||||
echo $OUTPUT->container_end();
|
||||
}
|
||||
$pageopen = false;
|
||||
@@ -711,7 +735,8 @@ function quiz_print_pagecontrols($quiz, $pageurl, $page, $hasattempts, $defaultc
|
||||
$returnurladdtoquiz = str_replace($CFG->wwwroot, '', $returnurladdtoquiz->out(false));
|
||||
$newquestionparams = array('returnurl' => $returnurladdtoquiz,
|
||||
'cmid' => $quiz->cmid, 'appendqnumstring' => 'addquestion');
|
||||
create_new_question_button($defaultcategoryid, $newquestionparams, get_string('addaquestion', 'quiz'),
|
||||
create_new_question_button($defaultcategoryid, $newquestionparams,
|
||||
get_string('addaquestion', 'quiz'),
|
||||
get_string('createquestionandadd', 'quiz'), $hasattempts);
|
||||
|
||||
if ($hasattempts) {
|
||||
@@ -721,14 +746,21 @@ function quiz_print_pagecontrols($quiz, $pageurl, $page, $hasattempts, $defaultc
|
||||
}
|
||||
?>
|
||||
<div class="singlebutton">
|
||||
<form class="randomquestionform" action="<?php echo $CFG->wwwroot; ?>/mod/quiz/addrandom.php" method="get">
|
||||
<form class="randomquestionform" action="<?php echo $CFG->wwwroot;
|
||||
?>/mod/quiz/addrandom.php" method="get">
|
||||
<div>
|
||||
<input type="hidden" class="addonpage_formelement" name="addonpage" value="<?php echo $page; ?>" />
|
||||
<input type="hidden" class="addonpage_formelement" name="addonpage" value="<?php
|
||||
echo $page; ?>" />
|
||||
<input type="hidden" name="cmid" value="<?php echo $quiz->cmid; ?>" />
|
||||
<input type="hidden" name="courseid" value="<?php echo $quiz->course; ?>" />
|
||||
<input type="hidden" name="category" value="<?php echo $pageurl->param('cat'); ?>" />
|
||||
<input type="hidden" name="returnurl" value="<?php echo s(str_replace($CFG->wwwroot, '', $pageurl->out(false))); ?>" />
|
||||
<input type="submit" id="addrandomdialoglaunch_<?php echo $randombuttoncount; ?>" value="<?php echo get_string('addarandomquestion', 'quiz'); ?>" <?php echo " $disabled"; ?> />
|
||||
<input type="hidden" name="category" value="<?php
|
||||
echo $pageurl->param('cat'); ?>" />
|
||||
<input type="hidden" name="returnurl" value="<?php
|
||||
echo s(str_replace($CFG->wwwroot, '', $pageurl->out(false))); ?>" />
|
||||
<input type="submit" id="addrandomdialoglaunch_<?php
|
||||
echo $randombuttoncount; ?>" value="<?php
|
||||
echo get_string('addarandomquestion', 'quiz'); ?>" <?php
|
||||
echo " $disabled"; ?> />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -747,11 +779,13 @@ function quiz_print_pagecontrols($quiz, $pageurl, $page, $hasattempts, $defaultc
|
||||
*/
|
||||
function quiz_print_singlequestion($question, $returnurl, $quiz) {
|
||||
echo '<div class="singlequestion">';
|
||||
echo quiz_question_edit_button($quiz->cmid, $question, $returnurl, quiz_question_tostring($question) . ' ');
|
||||
echo quiz_question_edit_button($quiz->cmid, $question, $returnurl,
|
||||
quiz_question_tostring($question) . ' ');
|
||||
echo '<span class="questiontype">';
|
||||
print_question_icon($question);
|
||||
echo ' ' . question_bank::get_qtype_name($question->qtype) . '</span>';
|
||||
echo '<span class="questionpreview">' . quiz_question_preview_button($quiz, $question, true) . '</span>';
|
||||
echo '<span class="questionpreview">' .
|
||||
quiz_question_preview_button($quiz, $question, true) . '</span>';
|
||||
echo "</div>\n";
|
||||
}
|
||||
/**
|
||||
@@ -767,7 +801,8 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktoo
|
||||
global $DB, $OUTPUT;
|
||||
echo '<div class="quiz_randomquestion">';
|
||||
|
||||
if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
|
||||
if (!$category = $DB->get_record('question_categories',
|
||||
array('id' => $question->category))) {
|
||||
echo $OUTPUT->notification('Random question category not found!');
|
||||
return;
|
||||
}
|
||||
@@ -786,8 +821,10 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktoo
|
||||
$linkcategorycontents = ' <a href="' . $openqbankurl . '">' . $strshowcategorycontents . '</a>';
|
||||
|
||||
echo '<div class="randomquestioncategory">';
|
||||
echo '<a href="' . $openqbankurl . '" title="' . $strshowcategorycontents . '">' . $category->name . '</a>';
|
||||
echo '<span class="questionpreview">' . quiz_question_preview_button($quiz, $question, true) . '</span>';
|
||||
echo '<a href="' . $openqbankurl . '" title="' . $strshowcategorycontents . '">' .
|
||||
$category->name . '</a>';
|
||||
echo '<span class="questionpreview">' .
|
||||
quiz_question_preview_button($quiz, $question, true) . '</span>';
|
||||
echo '</div>';
|
||||
|
||||
$questionids = question_bank::get_qtype('random')->get_available_questions_from_category(
|
||||
@@ -874,7 +911,8 @@ function quiz_print_randomquestion_reordertool(&$question, &$pageurl, &$quiz) {
|
||||
echo $OUTPUT->notification('Random question category not found!');
|
||||
return;
|
||||
}
|
||||
$questioncount = count(question_bank::get_qtype('random')->get_available_questions_from_category(
|
||||
$questioncount = count(question_bank::get_qtype(
|
||||
'random')->get_available_questions_from_category(
|
||||
$category->id, $question->questiontext == '1', '0'));
|
||||
|
||||
$reordercheckboxlabel = '<label for="s' . $question->id . '">';
|
||||
@@ -933,7 +971,8 @@ function print_random_option_icon($question) {
|
||||
* If false, show only question name.
|
||||
* @param bool $return If true (default), return the output. If false, print it.
|
||||
*/
|
||||
function quiz_question_tostring(&$question, $showicon = false, $showquestiontext = true, $return = true) {
|
||||
function quiz_question_tostring($question, $showicon = false,
|
||||
$showquestiontext = true, $return = true) {
|
||||
global $COURSE;
|
||||
$result = '';
|
||||
$result .= '<span class="questionname">';
|
||||
@@ -1049,7 +1088,8 @@ class quiz_question_bank_view extends question_bank_view {
|
||||
}
|
||||
|
||||
protected function wanted_columns() {
|
||||
return array('addtoquizaction', 'checkbox', 'qtype', 'questionnametext', 'editaction', 'previewaction');
|
||||
return array('addtoquizaction', 'checkbox', 'qtype', 'questionnametext',
|
||||
'editaction', 'previewaction');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1097,8 +1137,9 @@ class quiz_question_bank_view extends question_bank_view {
|
||||
$this->baseurl, $cat);
|
||||
|
||||
// continues with list of questions
|
||||
$this->display_question_list($this->contexts->having_one_edit_tab_cap($tabname), $this->baseurl, $cat, $this->cm,
|
||||
$recurse, $page, $perpage, $showhidden, $sortorder, $sortorderdecoded, $showquestiontext,
|
||||
$this->display_question_list($this->contexts->having_one_edit_tab_cap($tabname),
|
||||
$this->baseurl, $cat, $this->cm, $recurse, $page,
|
||||
$perpage, $showhidden, $sortorder, $sortorderdecoded, $showquestiontext,
|
||||
$this->contexts->having_cap('moodle/question:add'));
|
||||
|
||||
$this->display_options($recurse, $showhidden, $showquestiontext);
|
||||
@@ -1108,7 +1149,8 @@ class quiz_question_bank_view extends question_bank_view {
|
||||
protected function print_choose_category_message($categoryandcontext) {
|
||||
global $OUTPUT;
|
||||
echo $OUTPUT->box_start('generalbox questionbank');
|
||||
$this->display_category_form($this->contexts->having_one_edit_tab_cap('edit'), $this->baseurl, $categoryandcontext);
|
||||
$this->display_category_form($this->contexts->having_one_edit_tab_cap('edit'),
|
||||
$this->baseurl, $categoryandcontext);
|
||||
echo "<p style=\"text-align:center;\"><b>";
|
||||
print_string('selectcategoryabove', 'quiz');
|
||||
echo "</b></p>";
|
||||
@@ -1123,19 +1165,25 @@ class quiz_question_bank_view extends question_bank_view {
|
||||
$strcategory;
|
||||
echo ': <span class="categorynamefield">';
|
||||
echo shorten_text(strip_tags(format_string($category->name)), 60);
|
||||
echo '</span></div><div class="categoryinfofieldcontainer"><span class="categoryinfofield">';
|
||||
echo '</span></div><div class="categoryinfofieldcontainer">' .
|
||||
'<span class="categoryinfofield">';
|
||||
echo shorten_text(strip_tags(format_text($category->info, $category->infoformat,
|
||||
$formatoptions, $this->course->id)), 200);
|
||||
echo '</span></div></div>';
|
||||
}
|
||||
|
||||
protected function display_options($recurse = 1, $showhidden = false, $showquestiontext = false) {
|
||||
protected function display_options($recurse = 1, $showhidden = false,
|
||||
$showquestiontext = false) {
|
||||
echo '<form method="get" action="edit.php" id="displayoptions">';
|
||||
echo "<fieldset class='invisiblefieldset'>";
|
||||
echo html_writer::input_hidden_params($this->baseurl, array('recurse', 'showhidden', 'showquestiontext'));
|
||||
$this->display_category_form_checkbox('recurse', get_string('includesubcategories', 'question'));
|
||||
$this->display_category_form_checkbox('showhidden', get_string('showhidden', 'question'));
|
||||
echo '<noscript><div class="centerpara"><input type="submit" value="'. get_string('go') . '" />';
|
||||
echo html_writer::input_hidden_params($this->baseurl,
|
||||
array('recurse', 'showhidden', 'showquestiontext'));
|
||||
$this->display_category_form_checkbox('recurse',
|
||||
get_string('includesubcategories', 'question'));
|
||||
$this->display_category_form_checkbox('showhidden',
|
||||
get_string('showhidden', 'question'));
|
||||
echo '<noscript><div class="centerpara"><input type="submit" value="' .
|
||||
get_string('go') . '" />';
|
||||
echo '</div></noscript></fieldset></form>';
|
||||
}
|
||||
}
|
||||
@@ -1157,7 +1205,8 @@ function quiz_print_grading_form($quiz, $pageurl, $tabindex) {
|
||||
echo '<fieldset class="invisiblefieldset" style="display: block;">';
|
||||
echo "<input type=\"hidden\" name=\"sesskey\" value=\"" . sesskey() . "\" />";
|
||||
echo html_writer::input_hidden_params($pageurl);
|
||||
$a = '<input type="text" id="inputmaxgrade" name="maxgrade" size="' . ($quiz->decimalpoints + 2) . '" tabindex="' . $tabindex
|
||||
$a = '<input type="text" id="inputmaxgrade" name="maxgrade" size="' .
|
||||
($quiz->decimalpoints + 2) . '" tabindex="' . $tabindex
|
||||
. '" value="' . quiz_format_grade($quiz, $quiz->grade) . '" />';
|
||||
echo '<label for="inputmaxgrade">' . get_string('maximumgradex', '', $a) . "</label>";
|
||||
echo '<input type="hidden" name="savechanges" value="save" />';
|
||||
@@ -1176,13 +1225,14 @@ function quiz_print_status_bar($quiz) {
|
||||
global $CFG;
|
||||
$numberofquestions = quiz_number_of_questions_in_quiz($quiz->questions);
|
||||
?><div class="statusbar"><span class="totalpoints">
|
||||
<?php echo get_string('totalpointsx', 'quiz', quiz_format_grade($quiz, $quiz->sumgrades)) ?></span>
|
||||
<?php echo get_string('totalpointsx', 'quiz',
|
||||
quiz_format_grade($quiz, $quiz->sumgrades)) ?></span>
|
||||
| <span class="numberofquestions">
|
||||
<?php
|
||||
echo get_string('numquestionsx', 'quiz', $numberofquestions);
|
||||
?></span>
|
||||
<?php
|
||||
// Current status of the quiz, with open an close dates as a tool tip.
|
||||
// Current status of the quiz, with open an close dates as a tool tip.
|
||||
$currentstatus = get_string('quizisopen', 'quiz');
|
||||
$dates = array();
|
||||
$timenow = time();
|
||||
@@ -1200,7 +1250,8 @@ function quiz_print_status_bar($quiz) {
|
||||
print_string('quizisclosed', 'quiz');
|
||||
} else {
|
||||
$dates[] = get_string('quizcloseson', 'quiz', userdate($quiz->timeclose));
|
||||
$currentstatus = get_string('quizisopenwillclose', 'quiz', userdate($quiz->timeclose, get_string('strftimedatetimeshort', 'langconfig')));
|
||||
$currentstatus = get_string('quizisopenwillclose', 'quiz',
|
||||
userdate($quiz->timeclose, get_string('strftimedatetimeshort', 'langconfig')));
|
||||
}
|
||||
}
|
||||
if (empty($dates)) {
|
||||
|
||||
+112
-69
@@ -58,10 +58,10 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$quizconfig = get_config('quiz');
|
||||
$mform = $this->_form;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'general', get_string('general', 'form'));
|
||||
|
||||
/// Name.
|
||||
// Name.
|
||||
$mform->addElement('text', 'name', get_string('name'), array('size'=>'64'));
|
||||
if (!empty($CFG->formatstringstriptags)) {
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
@@ -70,10 +70,10 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
}
|
||||
$mform->addRule('name', null, 'required', null, 'client');
|
||||
|
||||
/// Introduction.
|
||||
// Introduction.
|
||||
$this->add_intro_editor(false, get_string('introduction', 'quiz'));
|
||||
|
||||
/// Open and close dates.
|
||||
// Open and close dates.
|
||||
$mform->addElement('date_time_selector', 'timeopen', get_string('quizopen', 'quiz'),
|
||||
array('optional' => true, 'step' => 1));
|
||||
$mform->addHelpButton('timeopen', 'quizopenclose', 'quiz');
|
||||
@@ -81,38 +81,45 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$mform->addElement('date_time_selector', 'timeclose', get_string('quizclose', 'quiz'),
|
||||
array('optional' => true, 'step' => 1));
|
||||
|
||||
/// Time limit.
|
||||
$mform->addElement('duration', 'timelimit', get_string('timelimit', 'quiz'), array('optional' => true));
|
||||
// Time limit.
|
||||
$mform->addElement('duration', 'timelimit', get_string('timelimit', 'quiz'),
|
||||
array('optional' => true));
|
||||
$mform->addHelpButton('timelimit', 'timelimit', 'quiz');
|
||||
$mform->setAdvanced('timelimit', $quizconfig->timelimit_adv);
|
||||
$mform->setDefault('timelimit', $quizconfig->timelimit);
|
||||
|
||||
/// Number of attempts.
|
||||
// Number of attempts.
|
||||
$attemptoptions = array('0' => get_string('unlimited'));
|
||||
for ($i = 1; $i <= QUIZ_MAX_ATTEMPT_OPTION; $i++) {
|
||||
$attemptoptions[$i] = $i;
|
||||
}
|
||||
$mform->addElement('select', 'attempts', get_string('attemptsallowed', 'quiz'), $attemptoptions);
|
||||
$mform->addElement('select', 'attempts', get_string('attemptsallowed', 'quiz'),
|
||||
$attemptoptions);
|
||||
$mform->setAdvanced('attempts', $quizconfig->attempts_adv);
|
||||
$mform->setDefault('attempts', $quizconfig->attempts);
|
||||
|
||||
/// Grading method.
|
||||
$mform->addElement('select', 'grademethod', get_string('grademethod', 'quiz'), quiz_get_grading_options());
|
||||
// Grading method.
|
||||
$mform->addElement('select', 'grademethod', get_string('grademethod', 'quiz'),
|
||||
quiz_get_grading_options());
|
||||
$mform->addHelpButton('grademethod', 'grademethod', 'quiz');
|
||||
$mform->setAdvanced('grademethod', $quizconfig->grademethod_adv);
|
||||
$mform->setDefault('grademethod', $quizconfig->grademethod);
|
||||
$mform->disabledIf('grademethod', 'attempts', 'eq', 1);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'layouthdr', get_string('layout', 'quiz'));
|
||||
|
||||
/// Shuffle questions.
|
||||
$shuffleoptions = array(0 => get_string('asshownoneditscreen', 'quiz'), 1 => get_string('shuffledrandomly', 'quiz'));
|
||||
$mform->addElement('select', 'shufflequestions', get_string('questionorder', 'quiz'), $shuffleoptions, array('id' => 'id_shufflequestions'));
|
||||
// Shuffle questions.
|
||||
$shuffleoptions = array(
|
||||
0 => get_string('asshownoneditscreen', 'quiz'),
|
||||
1 => get_string('shuffledrandomly', 'quiz')
|
||||
);
|
||||
$mform->addElement('select', 'shufflequestions', get_string('questionorder', 'quiz'),
|
||||
$shuffleoptions, array('id' => 'id_shufflequestions'));
|
||||
$mform->setAdvanced('shufflequestions', $quizconfig->shufflequestions_adv);
|
||||
$mform->setDefault('shufflequestions', $quizconfig->shufflequestions);
|
||||
|
||||
/// Questions per page.
|
||||
// Questions per page.
|
||||
$pageoptions = array();
|
||||
$pageoptions[0] = get_string('neverallononepage', 'quiz');
|
||||
$pageoptions[1] = get_string('everyquestion', 'quiz');
|
||||
@@ -121,57 +128,67 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
}
|
||||
|
||||
$pagegroup = array();
|
||||
$pagegroup[] = &$mform->createElement('select', 'questionsperpage', get_string('newpage', 'quiz'), $pageoptions, array('id' => 'id_questionsperpage'));
|
||||
$pagegroup[] = $mform->createElement('select', 'questionsperpage',
|
||||
get_string('newpage', 'quiz'), $pageoptions, array('id' => 'id_questionsperpage'));
|
||||
$mform->setDefault('questionsperpage', $quizconfig->questionsperpage);
|
||||
|
||||
if (!empty($this->_cm)) {
|
||||
$pagegroup[] = &$mform->createElement('checkbox', 'repaginatenow', '', get_string('repaginatenow', 'quiz'), array('id' => 'id_repaginatenow'));
|
||||
$pagegroup[] = $mform->createElement('checkbox', 'repaginatenow', '',
|
||||
get_string('repaginatenow', 'quiz'), array('id' => 'id_repaginatenow'));
|
||||
$mform->disabledIf('repaginatenow', 'shufflequestions', 'eq', 1);
|
||||
$PAGE->requires->yui2_lib('event');
|
||||
$PAGE->requires->js('/mod/quiz/edit.js');
|
||||
$PAGE->requires->js_init_call('quiz_settings_init');
|
||||
}
|
||||
|
||||
$mform->addGroup($pagegroup, 'questionsperpagegrp', get_string('newpage', 'quiz'), null, false);
|
||||
$mform->addGroup($pagegroup, 'questionsperpagegrp',
|
||||
get_string('newpage', 'quiz'), null, false);
|
||||
$mform->addHelpButton('questionsperpagegrp', 'newpage', 'quiz');
|
||||
$mform->setAdvanced('questionsperpagegrp', $quizconfig->questionsperpage_adv);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'interactionhdr', get_string('questionbehaviour', 'quiz'));
|
||||
|
||||
/// Shuffle within questions.
|
||||
// Shuffle within questions.
|
||||
$mform->addElement('selectyesno', 'shuffleanswers', get_string('shufflewithin', 'quiz'));
|
||||
$mform->addHelpButton('shuffleanswers', 'shufflewithin', 'quiz');
|
||||
$mform->setAdvanced('shuffleanswers', $quizconfig->shuffleanswers_adv);
|
||||
$mform->setDefault('shuffleanswers', $quizconfig->shuffleanswers);
|
||||
|
||||
/// How questions behave (question behaviour).
|
||||
// How questions behave (question behaviour).
|
||||
if (!empty($this->current->preferredbehaviour)) {
|
||||
$currentbehaviour = $this->current->preferredbehaviour;
|
||||
} else {
|
||||
$currentbehaviour = '';
|
||||
}
|
||||
$behaviours = question_engine::get_behaviour_options($currentbehaviour);
|
||||
$mform->addElement('select', 'preferredbehaviour', get_string('howquestionsbehave', 'question'), $behaviours);
|
||||
$mform->addElement('select', 'preferredbehaviour',
|
||||
get_string('howquestionsbehave', 'question'), $behaviours);
|
||||
$mform->addHelpButton('preferredbehaviour', 'howquestionsbehave', 'question');
|
||||
$mform->setDefault('preferredbehaviour', $quizconfig->preferredbehaviour);
|
||||
|
||||
/// Each attempt builds on last.
|
||||
$mform->addElement('selectyesno', 'attemptonlast', get_string('eachattemptbuildsonthelast', 'quiz'));
|
||||
// Each attempt builds on last.
|
||||
$mform->addElement('selectyesno', 'attemptonlast',
|
||||
get_string('eachattemptbuildsonthelast', 'quiz'));
|
||||
$mform->addHelpButton('attemptonlast', 'eachattemptbuildsonthelast', 'quiz');
|
||||
$mform->setAdvanced('attemptonlast', $quizconfig->attemptonlast_adv);
|
||||
$mform->setDefault('attemptonlast', $quizconfig->attemptonlast);
|
||||
$mform->disabledIf('attemptonlast', 'attempts', 'eq', 1);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'reviewoptionshdr', get_string('reviewoptionsheading', 'quiz'));
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'reviewoptionshdr',
|
||||
get_string('reviewoptionsheading', 'quiz'));
|
||||
$mform->addHelpButton('reviewoptionshdr', 'reviewoptionsheading', 'quiz');
|
||||
|
||||
/// Review options.
|
||||
$this->add_review_options_group($mform, $quizconfig, 'during', mod_quiz_display_options::DURING);
|
||||
$this->add_review_options_group($mform, $quizconfig, 'immediately', mod_quiz_display_options::IMMEDIATELY_AFTER);
|
||||
$this->add_review_options_group($mform, $quizconfig, 'open', mod_quiz_display_options::LATER_WHILE_OPEN);
|
||||
$this->add_review_options_group($mform, $quizconfig, 'closed', mod_quiz_display_options::AFTER_CLOSE);
|
||||
// Review options.
|
||||
$this->add_review_options_group($mform, $quizconfig, 'during',
|
||||
mod_quiz_display_options::DURING);
|
||||
$this->add_review_options_group($mform, $quizconfig, 'immediately',
|
||||
mod_quiz_display_options::IMMEDIATELY_AFTER);
|
||||
$this->add_review_options_group($mform, $quizconfig, 'open',
|
||||
mod_quiz_display_options::LATER_WHILE_OPEN);
|
||||
$this->add_review_options_group($mform, $quizconfig, 'closed',
|
||||
mod_quiz_display_options::AFTER_CLOSE);
|
||||
|
||||
foreach ($behaviours as $behaviour => $notused) {
|
||||
$unusedoptions = question_engine::get_behaviour_unused_display_options($behaviour);
|
||||
@@ -185,31 +202,34 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$mform->disabledIf('overallfeedbackduring', 'preferredbehaviour',
|
||||
'neq', 'wontmatch');
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'display', get_string('display', 'form'));
|
||||
|
||||
/// Show user picture.
|
||||
$mform->addElement('selectyesno', 'showuserpicture', get_string('showuserpicture', 'quiz'));
|
||||
// Show user picture.
|
||||
$mform->addElement('selectyesno', 'showuserpicture',
|
||||
get_string('showuserpicture', 'quiz'));
|
||||
$mform->addHelpButton('showuserpicture', 'showuserpicture', 'quiz');
|
||||
$mform->setAdvanced('showuserpicture', $quizconfig->showuserpicture_adv);
|
||||
$mform->setDefault('showuserpicture', $quizconfig->showuserpicture);
|
||||
|
||||
/// Overall decimal points.
|
||||
// Overall decimal points.
|
||||
$options = array();
|
||||
for ($i = 0; $i <= QUIZ_MAX_DECIMAL_OPTION; $i++) {
|
||||
$options[$i] = $i;
|
||||
}
|
||||
$mform->addElement('select', 'decimalpoints', get_string('decimalplaces', 'quiz'), $options);
|
||||
$mform->addElement('select', 'decimalpoints', get_string('decimalplaces', 'quiz'),
|
||||
$options);
|
||||
$mform->addHelpButton('decimalpoints', 'decimalplaces', 'quiz');
|
||||
$mform->setAdvanced('decimalpoints', $quizconfig->decimalpoints_adv);
|
||||
$mform->setDefault('decimalpoints', $quizconfig->decimalpoints);
|
||||
|
||||
/// Question decimal points.
|
||||
// Question decimal points.
|
||||
$options = array(-1 => get_string('sameasoverall', 'quiz'));
|
||||
for ($i = 0; $i <= QUIZ_MAX_Q_DECIMAL_OPTION; $i++) {
|
||||
$options[$i] = $i;
|
||||
}
|
||||
$mform->addElement('select', 'questiondecimalpoints', get_string('decimalplacesquestion', 'quiz'), $options);
|
||||
$mform->addElement('select', 'questiondecimalpoints',
|
||||
get_string('decimalplacesquestion', 'quiz'), $options);
|
||||
$mform->addHelpButton('questiondecimalpoints', 'decimalplacesquestion', 'quiz');
|
||||
$mform->setAdvanced('questiondecimalpoints', $quizconfig->questiondecimalpoints_adv);
|
||||
$mform->setDefault('questiondecimalpoints', $quizconfig->questiondecimalpoints);
|
||||
@@ -220,38 +240,40 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$mform->setAdvanced('showblocks', $quizconfig->showblocks_adv);
|
||||
$mform->setDefault('showblocks', $quizconfig->showblocks);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'security', get_string('extraattemptrestrictions', 'quiz'));
|
||||
|
||||
/// Enforced time delay between quiz attempts.
|
||||
// Enforced time delay between quiz attempts.
|
||||
$mform->addElement('passwordunmask', 'quizpassword', get_string('requirepassword', 'quiz'));
|
||||
$mform->setType('quizpassword', PARAM_TEXT);
|
||||
$mform->addHelpButton('quizpassword', 'requirepassword', 'quiz');
|
||||
$mform->setAdvanced('quizpassword', $quizconfig->password_adv);
|
||||
$mform->setDefault('quizpassword', $quizconfig->password);
|
||||
|
||||
/// IP address.
|
||||
// IP address.
|
||||
$mform->addElement('text', 'subnet', get_string('requiresubnet', 'quiz'));
|
||||
$mform->setType('subnet', PARAM_TEXT);
|
||||
$mform->addHelpButton('subnet', 'requiresubnet', 'quiz');
|
||||
$mform->setAdvanced('subnet', $quizconfig->subnet_adv);
|
||||
$mform->setDefault('subnet', $quizconfig->subnet);
|
||||
|
||||
/// Enforced time delay between quiz attempts.
|
||||
$mform->addElement('duration', 'delay1', get_string('delay1st2nd', 'quiz'), array('optional' => true));
|
||||
// Enforced time delay between quiz attempts.
|
||||
$mform->addElement('duration', 'delay1', get_string('delay1st2nd', 'quiz'),
|
||||
array('optional' => true));
|
||||
$mform->addHelpButton('delay1', 'delay1st2nd', 'quiz');
|
||||
$mform->setAdvanced('delay1', $quizconfig->delay1_adv);
|
||||
$mform->setDefault('delay1', $quizconfig->delay1);
|
||||
$mform->disabledIf('delay1', 'attempts', 'eq', 1);
|
||||
|
||||
$mform->addElement('duration', 'delay2', get_string('delaylater', 'quiz'), array('optional' => true));
|
||||
$mform->addElement('duration', 'delay2', get_string('delaylater', 'quiz'),
|
||||
array('optional' => true));
|
||||
$mform->addHelpButton('delay2', 'delaylater', 'quiz');
|
||||
$mform->setAdvanced('delay2', $quizconfig->delay2_adv);
|
||||
$mform->setDefault('delay2', $quizconfig->delay2);
|
||||
$mform->disabledIf('delay2', 'attempts', 'eq', 1);
|
||||
$mform->disabledIf('delay2', 'attempts', 'eq', 2);
|
||||
|
||||
/// 'Secure' window.
|
||||
// 'Secure' window.
|
||||
$options = array(
|
||||
0 => get_string('none', 'quiz'),
|
||||
1 => get_string('popupwithjavascriptsupport', 'quiz'));
|
||||
@@ -263,7 +285,7 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$mform->setAdvanced('popup', $quizconfig->popup_adv);
|
||||
$mform->setDefault('popup', $quizconfig->popup);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'overallfeedbackhdr', get_string('overallfeedback', 'quiz'));
|
||||
$mform->addHelpButton('overallfeedbackhdr', 'overallfeedback', 'quiz');
|
||||
|
||||
@@ -276,15 +298,20 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$needwarning = $quizconfig->maximumgrade == 0;
|
||||
}
|
||||
if ($needwarning) {
|
||||
$mform->addElement('static', 'nogradewarning', '', get_string('nogradewarning', 'quiz'));
|
||||
$mform->addElement('static', 'nogradewarning', '',
|
||||
get_string('nogradewarning', 'quiz'));
|
||||
}
|
||||
|
||||
$mform->addElement('static', 'gradeboundarystatic1', get_string('gradeboundary', 'quiz'), '100%');
|
||||
$mform->addElement('static', 'gradeboundarystatic1',
|
||||
get_string('gradeboundary', 'quiz'), '100%');
|
||||
|
||||
$repeatarray = array();
|
||||
$repeatedoptions = array();
|
||||
$repeatarray[] = MoodleQuickForm::createElement('editor', 'feedbacktext', get_string('feedback', 'quiz'), null, array('maxfiles'=>EDITOR_UNLIMITED_FILES, 'noclean'=>true, 'context'=>$this->context));
|
||||
$repeatarray[] = MoodleQuickForm::createElement('text', 'feedbackboundaries', get_string('gradeboundary', 'quiz'), array('size' => 10));
|
||||
$repeatarray[] = MoodleQuickForm::createElement('editor', 'feedbacktext',
|
||||
get_string('feedback', 'quiz'), null, array('maxfiles' => EDITOR_UNLIMITED_FILES,
|
||||
'noclean' => true, 'context' => $this->context));
|
||||
$repeatarray[] = MoodleQuickForm::createElement('text', 'feedbackboundaries',
|
||||
get_string('gradeboundary', 'quiz'), array('size' => 10));
|
||||
$repeatedoptions['feedbacktext']['type'] = PARAM_RAW;
|
||||
$repeatedoptions['feedbackboundaries']['type'] = PARAM_RAW;
|
||||
|
||||
@@ -317,10 +344,10 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$mform->disabledIf('feedbacktext[' . ($i + 1) . ']', 'grade', 'eq', 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
$this->standard_coursemodule_elements();
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
// buttons
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
@@ -330,7 +357,8 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
foreach (self::$reviewfields as $field => $label) {
|
||||
$group[] = $mform->createElement('checkbox', $field . $whenname, '', $label);
|
||||
}
|
||||
$mform->addGroup($group, $whenname . 'optionsgrp', get_string('review' . $whenname, 'quiz'), null, false);
|
||||
$mform->addGroup($group, $whenname . 'optionsgrp',
|
||||
get_string('review' . $whenname, 'quiz'), null, false);
|
||||
|
||||
foreach (self::$reviewfields as $field => $notused) {
|
||||
$cfgfield = 'review' . $field;
|
||||
@@ -358,12 +386,13 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
|
||||
public function data_preprocessing(&$toform) {
|
||||
if (isset($toform['grade'])) {
|
||||
$toform['grade'] = $toform['grade'] + 0; // Convert to a real number, so we don't get 0.0000.
|
||||
// Convert to a real number, so we don't get 0.0000.
|
||||
$toform['grade'] = $toform['grade'] + 0;
|
||||
}
|
||||
|
||||
if (count($this->_feedbacks)) {
|
||||
$key = 0;
|
||||
foreach ($this->_feedbacks as $feedback){
|
||||
foreach ($this->_feedbacks as $feedback) {
|
||||
$draftid = file_get_submitted_draft_itemid('feedbacktext['.$key.']');
|
||||
$toform['feedbacktext['.$key.']']['text'] = file_prepare_draft_area(
|
||||
$draftid, // draftid
|
||||
@@ -387,7 +416,8 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
}
|
||||
|
||||
if ($feedback->mingrade > 0) {
|
||||
$toform['feedbackboundaries['.$key.']'] = (100.0 * $feedback->mingrade / $toform['grade']) . '%';
|
||||
$toform['feedbackboundaries['.$key.']'] =
|
||||
(100.0 * $feedback->mingrade / $toform['grade']) . '%';
|
||||
}
|
||||
$key++;
|
||||
}
|
||||
@@ -397,10 +427,14 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$toform['timelimitenable'] = $toform['timelimit'] > 0;
|
||||
}
|
||||
|
||||
$this->preprocessing_review_settings($toform, 'during', mod_quiz_display_options::DURING);
|
||||
$this->preprocessing_review_settings($toform, 'immediately', mod_quiz_display_options::IMMEDIATELY_AFTER);
|
||||
$this->preprocessing_review_settings($toform, 'open', mod_quiz_display_options::LATER_WHILE_OPEN);
|
||||
$this->preprocessing_review_settings($toform, 'closed', mod_quiz_display_options::AFTER_CLOSE);
|
||||
$this->preprocessing_review_settings($toform, 'during',
|
||||
mod_quiz_display_options::DURING);
|
||||
$this->preprocessing_review_settings($toform, 'immediately',
|
||||
mod_quiz_display_options::IMMEDIATELY_AFTER);
|
||||
$this->preprocessing_review_settings($toform, 'open',
|
||||
mod_quiz_display_options::LATER_WHILE_OPEN);
|
||||
$this->preprocessing_review_settings($toform, 'closed',
|
||||
mod_quiz_display_options::AFTER_CLOSE);
|
||||
$toform['attemptduring'] = true;
|
||||
$toform['overallfeedbackduring'] = false;
|
||||
|
||||
@@ -416,7 +450,8 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
// Check open and close times are consistent.
|
||||
if ($data['timeopen'] != 0 && $data['timeclose'] != 0 && $data['timeclose'] < $data['timeopen']) {
|
||||
if ($data['timeopen'] != 0 && $data['timeclose'] != 0 &&
|
||||
$data['timeclose'] < $data['timeopen']) {
|
||||
$errors['timeclose'] = get_string('closebeforeopen', 'quiz');
|
||||
}
|
||||
|
||||
@@ -429,14 +464,18 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
if (is_numeric($boundary)) {
|
||||
$boundary = $boundary * $data['grade'] / 100.0;
|
||||
} else {
|
||||
$errors["feedbackboundaries[$i]"] = get_string('feedbackerrorboundaryformat', 'quiz', $i + 1);
|
||||
$errors["feedbackboundaries[$i]"] =
|
||||
get_string('feedbackerrorboundaryformat', 'quiz', $i + 1);
|
||||
}
|
||||
}
|
||||
if (is_numeric($boundary) && $boundary <= 0 || $boundary >= $data['grade'] ) {
|
||||
$errors["feedbackboundaries[$i]"] = get_string('feedbackerrorboundaryoutofrange', 'quiz', $i + 1);
|
||||
$errors["feedbackboundaries[$i]"] =
|
||||
get_string('feedbackerrorboundaryoutofrange', 'quiz', $i + 1);
|
||||
}
|
||||
if (is_numeric($boundary) && $i > 0 && $boundary >= $data['feedbackboundaries'][$i - 1]) {
|
||||
$errors["feedbackboundaries[$i]"] = get_string('feedbackerrororder', 'quiz', $i + 1);
|
||||
if (is_numeric($boundary) && $i > 0 &&
|
||||
$boundary >= $data['feedbackboundaries'][$i - 1]) {
|
||||
$errors["feedbackboundaries[$i]"] =
|
||||
get_string('feedbackerrororder', 'quiz', $i + 1);
|
||||
}
|
||||
$data['feedbackboundaries'][$i] = $boundary;
|
||||
$i += 1;
|
||||
@@ -446,14 +485,18 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
// Check there is nothing in the remaining unused fields.
|
||||
if (!empty($data['feedbackboundaries'])) {
|
||||
for ($i = $numboundaries; $i < count($data['feedbackboundaries']); $i += 1) {
|
||||
if (!empty($data['feedbackboundaries'][$i] ) && trim($data['feedbackboundaries'][$i] ) != '') {
|
||||
$errors["feedbackboundaries[$i]"] = get_string('feedbackerrorjunkinboundary', 'quiz', $i + 1);
|
||||
if (!empty($data['feedbackboundaries'][$i] ) &&
|
||||
trim($data['feedbackboundaries'][$i] ) != '') {
|
||||
$errors["feedbackboundaries[$i]"] =
|
||||
get_string('feedbackerrorjunkinboundary', 'quiz', $i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for ($i = $numboundaries + 1; $i < count($data['feedbacktext']); $i += 1) {
|
||||
if (!empty($data['feedbacktext'][$i]['text']) && trim($data['feedbacktext'][$i]['text'] ) != '') {
|
||||
$errors["feedbacktext[$i]"] = get_string('feedbackerrorjunkinfeedback', 'quiz', $i + 1);
|
||||
if (!empty($data['feedbacktext'][$i]['text']) &&
|
||||
trim($data['feedbacktext'][$i]['text'] ) != '') {
|
||||
$errors["feedbacktext[$i]"] =
|
||||
get_string('feedbackerrorjunkinfeedback', 'quiz', $i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1697,7 +1697,7 @@ function question_edit_setup($edittab, $baseurl, $requirecmid = false, $requirec
|
||||
* Required for legacy reasons. Was originally global then changed to class static
|
||||
* as of Moodle 2.0
|
||||
*/
|
||||
$QUESTION_EDITTABCAPS = question_edit_contexts::$CAPS;
|
||||
$QUESTION_EDITTABCAPS = question_edit_contexts::$caps;
|
||||
|
||||
/**
|
||||
* Make sure user is logged in as required in this context.
|
||||
|
||||
Reference in New Issue
Block a user