mirror of
https://github.com/moodle/moodle.git
synced 2025-04-14 04:52:36 +02:00
quiz editing: Refactor the editing actions to make functions in editlib.php for most of them.
In the process, do MDL-17456, move/delete questions by question id rather than position, for greater robustness.
This commit is contained in:
parent
1fd211a770
commit
4299df1daf
@ -167,54 +167,43 @@ if (isset($quiz->instance) && empty($quiz->grades)) { // Construct an array to
|
||||
$quiz->grades = quiz_get_all_question_grades($quiz);
|
||||
}
|
||||
|
||||
// SECTION: PROCESS COMMANDS //
|
||||
// If any edit action makes a significant change to the structure of the quiz,
|
||||
// then we will need to delete all preview attempts.
|
||||
$significantchangemade = false;
|
||||
// Process commands ============================================================
|
||||
|
||||
if (($up = optional_param('up', false, PARAM_INT)) !== false && confirm_sesskey()) {
|
||||
/// Move the given question up a slot
|
||||
$questions = explode(',', $quiz->questions);
|
||||
if ($up > 0 && isset($questions[$up])) {
|
||||
//$prevkey = ($questions[$up-1] == 0) ? $up-2 : $up-1;
|
||||
$prevkey = $up-1;
|
||||
$swap = $questions[$prevkey];
|
||||
$questions[$prevkey] = $questions[$up];
|
||||
$questions[$up] = $swap;
|
||||
$quiz->questions = implode(',', $questions);
|
||||
$quiz->questions = quiz_clean_layout($quiz->questions);
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions,
|
||||
array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
}
|
||||
$significantchangemade = true;
|
||||
// Get the list of question ids had their check-boxes ticked.
|
||||
$selectedquestionids = array();
|
||||
$params = (array) data_submitted();
|
||||
foreach ($params as $key => $value) {
|
||||
if (preg_match('!^s([0-9]+)$!', $key, $matches)) {
|
||||
$selectedquestionids[] = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (($down = optional_param('down', false, PARAM_INT)) !== false && confirm_sesskey()) {
|
||||
/// Move the given question down a slot
|
||||
$questions = explode(',', $quiz->questions);
|
||||
if ($down < count($questions)) {
|
||||
//$nextkey = ($questions[$down+1] == 0) ? $down+2 : $down+1;
|
||||
$nextkey = $down+1;
|
||||
$swap = $questions[$nextkey];
|
||||
$questions[$nextkey] = $questions[$down];
|
||||
$questions[$down] = $swap;
|
||||
$quiz->questions = implode(',', $questions);
|
||||
$quiz->questions = quiz_clean_layout($quiz->questions);
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions,
|
||||
array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
}
|
||||
$significantchangemade = true;
|
||||
}
|
||||
if (($up = optional_param('up', false, PARAM_INT)) && confirm_sesskey()) {
|
||||
$quiz->questions = quiz_move_question_up($quiz->questions, $up);
|
||||
quiz_save_new_layout($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
if (($down = optional_param('down', false, PARAM_INT)) && confirm_sesskey()) {
|
||||
$quiz->questions = quiz_move_question_down($quiz->questions, $down);
|
||||
quiz_save_new_layout($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
if (optional_param('repaginate', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
// Re-paginate the quiz
|
||||
$questionsperpage = optional_param('questionsperpage', $quiz->questionsperpage, PARAM_INT);
|
||||
$quiz->questions = quiz_repaginate($quiz->questions, $questionsperpage );
|
||||
quiz_save_new_layout($quiz);
|
||||
}
|
||||
|
||||
if (($addquestion = optional_param('addquestion', 0, PARAM_INT)) && confirm_sesskey()) {
|
||||
/// Add a single question to the current quiz
|
||||
$addonpage = optional_param('addonpage', 0, PARAM_INT);
|
||||
quiz_add_quiz_question($addquestion, $quiz, $addonpage);
|
||||
$significantchangemade = true;
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
@ -226,24 +215,20 @@ if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
quiz_add_quiz_question($key, $quiz);
|
||||
}
|
||||
}
|
||||
$significantchangemade = true;
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$qcobject = new question_category_object(
|
||||
$pagevars['cpage'],
|
||||
$thispageurl,
|
||||
$contexts->having_one_edit_tab_cap('categories'),
|
||||
$defaultcategoryid,
|
||||
$defaultcategory,
|
||||
null,
|
||||
$contexts->having_cap('moodle/question:add'));
|
||||
$qcobject = new question_category_object($pagevars['cpage'], $thispageurl,
|
||||
$contexts->having_one_edit_tab_cap('categories'), $defaultcategoryid,
|
||||
$defaultcategory, null, $contexts->having_cap('moodle/question:add'));
|
||||
|
||||
$newrandomcategory = false;
|
||||
$newquestioninfo = quiz_process_randomquestion_formdata($qcobject);
|
||||
if ($newquestioninfo) {
|
||||
$newrandomcategory = $newquestioninfo->newrandomcategory;
|
||||
if (!$newrandomcategory) {
|
||||
print_r($newquestioninfo);
|
||||
print_error('cannotcreatecategory');
|
||||
} else {
|
||||
add_to_log($quiz->course, 'quiz', 'addcategory',
|
||||
@ -311,114 +296,48 @@ if ((optional_param('addrandom', false, PARAM_BOOL) || $newrandomcategory) && co
|
||||
}
|
||||
}
|
||||
|
||||
$significantchangemade = true;
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$addpagesafterquestions = array();
|
||||
if ($addnewpagesafterselected = optional_param('addnewpagesafterselected', null)) {
|
||||
$rawgrades = (array) data_submitted();
|
||||
foreach ($rawgrades as $key => $value) {
|
||||
/// Parse input for question -> grades
|
||||
if (preg_match('!^s([0-9]+)$!', $key, $matches)) {
|
||||
$addpagesafterquestions[] = $matches[1];
|
||||
}
|
||||
if (optional_param('addnewpagesafterselected', null) && !empty($selectedquestionids) && confirm_sesskey()) {
|
||||
foreach ($selectedquestionids as $questionid) {
|
||||
$quiz->questions = quiz_add_page_break_after($quiz->questions, $questionid);
|
||||
}
|
||||
quiz_save_new_layout($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$addpage = optional_param('addpage', false, PARAM_INT);
|
||||
if (($addpage || !empty($addpagesafterquestions)) && confirm_sesskey()) {
|
||||
/// Move the given question up a slot
|
||||
|
||||
$questions = explode(',', $quiz->questions);
|
||||
|
||||
$pagebreakid = '0';
|
||||
if ($addpage > 0 && isset($questions[$addpage])) {
|
||||
array_splice($questions, $addpage, 0, $pagebreakid);
|
||||
$significantchangemade = true;
|
||||
}
|
||||
foreach ($addpagesafterquestions as $key => $questionid) {
|
||||
$addpage = array_search($questionid, $questions)+1;
|
||||
if ($addpage > 0 && isset($questions[$addpage])) {
|
||||
$pagebreakid = '0';
|
||||
array_splice($questions, $addpage, 0, $pagebreakid);
|
||||
$significantchangemade = true;
|
||||
}
|
||||
}
|
||||
$quiz->questions = implode(',', $questions);
|
||||
$quiz->questions = quiz_clean_layout($quiz->questions);
|
||||
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions,
|
||||
array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_param('repaginate', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
// Re-paginate the quiz
|
||||
$questionsperpage = optional_param('questionsperpage',
|
||||
$quiz->questionsperpage, PARAM_INT);
|
||||
$quiz->questions = quiz_repaginate($quiz->questions,
|
||||
$questionsperpage );
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id))) {
|
||||
print_error('cannotsavelayout', 'quiz');
|
||||
}
|
||||
$significantchangemade = true;
|
||||
if ($addpage !== false && confirm_sesskey()) {
|
||||
$quiz->questions = quiz_add_page_break_at($quiz->questions, $addpage);
|
||||
quiz_save_new_layout($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$deleteemptypage = optional_param('deleteemptypage', false, PARAM_INT);
|
||||
if (($deleteemptypage !== false) && confirm_sesskey()) {
|
||||
$questions = explode(',', $quiz->questions);
|
||||
if ($deleteemptypage>0) {
|
||||
//it points to a value one too big due to the display logic
|
||||
$deleteemptypage--;
|
||||
}
|
||||
if (((int)$questions[$deleteemptypage]) == 0) {
|
||||
$questions = explode(',', $quiz->questions);
|
||||
$endpart = array_slice($questions, $deleteemptypage + 1, null, true);
|
||||
$beginpart = array_slice($questions, 0, $deleteemptypage, true);
|
||||
$questions = array_merge($beginpart, $endpart);
|
||||
$quiz->questions = implode(',', $questions);
|
||||
$quiz->questions = quiz_clean_layout($quiz->questions);
|
||||
}
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions,
|
||||
array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
}
|
||||
$quiz->questions = quiz_delete_empty_page($quiz->questions, $deleteemptypage);
|
||||
quiz_save_new_layout($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$deletequestions = array();
|
||||
if ($quizdeleteselected = optional_param('quizdeleteselected', false)) {
|
||||
$rawgrades = (array) data_submitted();
|
||||
foreach ($rawgrades as $key => $value) {
|
||||
/// Parse input for question -> grades
|
||||
if (preg_match('!^s([0-9]+)$!', $key, $matches)) {
|
||||
$deletequestions[] = $matches[1];
|
||||
}
|
||||
}
|
||||
$remove = optional_param('remove', false, PARAM_INT);
|
||||
if (($remove = optional_param('remove', false, PARAM_INT)) && confirm_sesskey()) {
|
||||
quiz_remove_question($quiz, $remove);
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$delete = optional_param('delete', false, PARAM_INT);
|
||||
if (($delete !== false || !empty($deletequestions)) && confirm_sesskey()) {
|
||||
|
||||
//was: if ($delete > 0 ) {
|
||||
if ($delete !==false) {
|
||||
quiz_delete_quiz_question($delete, $quiz);
|
||||
$significantchangemade = true;
|
||||
}
|
||||
foreach ($deletequestions as $key => $questionid) {
|
||||
$questions = explode(',', $quiz->questions);
|
||||
$delete = array_search($questionid, $questions);
|
||||
if ($delete !== false) {
|
||||
quiz_delete_quiz_question($delete, $quiz);
|
||||
$significantchangemade = true;
|
||||
}
|
||||
}
|
||||
$quiz->questions = quiz_clean_layout($quiz->questions);
|
||||
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions,
|
||||
array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
if (optional_param('quizdeleteselected', false, PARAM_BOOL) && !empty($selectedquestionids) && confirm_sesskey()) {
|
||||
foreach ($selectedquestionids as $questionid) {
|
||||
quiz_remove_question($quiz, $questionid);
|
||||
}
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
@ -436,7 +355,7 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
}
|
||||
|
||||
foreach ($rawgrades as $key => $value) {
|
||||
if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
|
||||
if (preg_match('!^g([0-9]+)$!', $key, $matches)) {
|
||||
/// Parse input for question -> grades
|
||||
$key = $matches[1];
|
||||
$quiz->grades[$key] = $value;
|
||||
@ -453,28 +372,21 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
$value++;
|
||||
}
|
||||
$questions[$value] = $oldquestions[$key];
|
||||
|
||||
} else if (preg_match('!^s([0-9]+)$!', $key, $matches)) {
|
||||
// Parse input for selected questions
|
||||
// (add new pages after questions in quiz)
|
||||
$key = $matches[1];
|
||||
if ($moveselectedonpage) {
|
||||
$moveonpagequestions[] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If ordering info was given, reorder the questions
|
||||
if ($questions) {
|
||||
ksort($questions);
|
||||
$quiz->questions = implode(',', $questions) . ',0';
|
||||
$quiz->questions = quiz_clean_layout($quiz->questions);
|
||||
|
||||
}
|
||||
|
||||
//get a list of questions to move, later to be added in the appropriate
|
||||
//place in the string
|
||||
if ($moveonpagequestions) {
|
||||
if ($moveselectedonpage) {
|
||||
$questions = explode(',', $quiz->questions);
|
||||
foreach ($moveonpagequestions as $page => $question) {
|
||||
foreach ($selectedquestionids as $page => $question) {
|
||||
//remove the questions from their original positions first
|
||||
while (($delpos = array_search($question, $questions)) !== FALSE) {
|
||||
//in case there are multiple instances because of an error, remove all
|
||||
@ -499,14 +411,14 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
$pagebreakpositions = array_keys($questions, 0);
|
||||
//move to the end of the selected page
|
||||
$moveselectedpos = $pagebreakpositions[$moveselectedonpage - 1];
|
||||
foreach ($moveonpagequestions as $question) {
|
||||
foreach ($selectedquestionids as $question) {
|
||||
array_splice($questions, $moveselectedpos, 0, $question);
|
||||
//place the next one after this one:
|
||||
$moveselectedpos++;
|
||||
}
|
||||
$quiz->questions = implode(',', $questions);
|
||||
}
|
||||
if ($moveonpagequestions || $questions) {
|
||||
if ($moveselectedonpage || $questions) {
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions,
|
||||
array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
@ -520,24 +432,14 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
}
|
||||
}
|
||||
|
||||
$significantchangemade = true;
|
||||
}
|
||||
/// Delete any teacher preview attempts if the quiz has been modified
|
||||
if ($significantchangemade) {
|
||||
$previewattempts = $DB->get_records_select('quiz_attempts',
|
||||
'quiz = ? AND preview = 1', array($quiz->id));
|
||||
if ($previewattempts) {
|
||||
foreach ($previewattempts as $attempt) {
|
||||
quiz_delete_attempt($attempt, $quiz);
|
||||
}
|
||||
}
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
redirect($thispageurl->out());
|
||||
}
|
||||
|
||||
$questionbank->process_actions($thispageurl, $cm);
|
||||
|
||||
/// all commands have been dealt with, now print the page
|
||||
// End of process commands =====================================================
|
||||
|
||||
if (isset($quiz->instance) && $DB->record_exists_select('quiz_attempts',
|
||||
'quiz = ? AND preview = 0', array($quiz->instance))) {
|
||||
|
@ -35,35 +35,45 @@ require_once("locallib.php");
|
||||
define('NUM_QS_TO_SHOW_IN_RANDOM', 3);
|
||||
|
||||
/**
|
||||
* Delete a question from a quiz
|
||||
*
|
||||
* Deletes a question or a pagebreak from a quiz by updating $quiz
|
||||
* as well as the quiz, quiz_question_instances
|
||||
* @return boolean false if the question was not in the quiz
|
||||
* @param int $id The id of the question to be deleted
|
||||
* @param object $quiz The extended quiz object as used by edit.php
|
||||
* This is updated by this function
|
||||
*/
|
||||
function quiz_delete_quiz_question($id, &$quiz) {
|
||||
* Remove a question from a quiz
|
||||
* @param object $quiz the quiz object.
|
||||
* @param int $questionid The id of the question to be deleted.
|
||||
*/
|
||||
function quiz_remove_question($quiz, $questionid) {
|
||||
global $DB;
|
||||
// TODO: For the sake of safety check that this question can be deleted
|
||||
// safely, i.e., that it is not already in use.
|
||||
$questions = explode(",", $quiz->questions);
|
||||
|
||||
// only do something if this question exists
|
||||
if (!isset($questions[$id])) {
|
||||
return false;
|
||||
$questionids = explode(',', $quiz->questions);
|
||||
$key = array_search($questionid, $questionids);
|
||||
if ($key === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$question = $questions[$id];
|
||||
unset($questions[$id]);
|
||||
$quiz->questions = implode(",", $questions);
|
||||
// save new questionlist in database
|
||||
if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->instance))) {
|
||||
print_error('cannotsavequestion', 'quiz');
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty page from the quiz layout. If that is not possible, do nothing.
|
||||
* @param string $layout the existinng layout, $quiz->questions.
|
||||
* @param integer $index the position into $layout where the empty page should be removed.
|
||||
* @return the updated layout
|
||||
*/
|
||||
function quiz_delete_empty_page($layout, $index) {
|
||||
$questionids = explode(',', $layout);
|
||||
|
||||
if ($index < -1 || $index >= count($questionids) - 1) {
|
||||
return $layout;
|
||||
}
|
||||
$DB->delete_records('quiz_question_instances', array('quiz' => $quiz->instance, 'question'=> $question));
|
||||
return true;
|
||||
|
||||
if (($index >= 0 && $questionids[$index] != 0) || $questionids[$index + 1] != 0) {
|
||||
return $layout; // This was not an empty page.
|
||||
}
|
||||
|
||||
unset($questionids[$index + 1]);
|
||||
|
||||
return implode(',', $questionids);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,6 +151,53 @@ function quiz_add_quiz_question($id, &$quiz, $page=0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a page break after at particular position$.
|
||||
* @param string $layout the existinng layout, $quiz->questions.
|
||||
* @param integer $index the position into $layout where the empty page should be removed.
|
||||
* @return the updated layout
|
||||
*/
|
||||
function quiz_add_page_break_at($layout, $index) {
|
||||
$questionids = explode(',', $layout);
|
||||
if ($index < 0 || $index >= count($questionids)) {
|
||||
return $layout;
|
||||
}
|
||||
|
||||
array_splice($questionids, $index, 0, '0');
|
||||
|
||||
return implode(',', $questionids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a page break after a particular question.
|
||||
* @param string $layout the existinng layout, $quiz->questions.
|
||||
* @param integer $qustionid the question to add the page break after.
|
||||
* @return the updated layout
|
||||
*/
|
||||
function quiz_add_page_break_after($layout, $questionid) {
|
||||
$questionids = explode(',', $layout);
|
||||
$key = array_search($questionid, $questionids);
|
||||
if ($key === false || !$questionid) {
|
||||
return $layout;
|
||||
}
|
||||
|
||||
array_splice($questionids, $key + 1, 0, '0');
|
||||
|
||||
return implode(',', $questionids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the database after $quiz->questions has been changed. For example,
|
||||
* this deletes preview attempts and updates $quiz->sumgrades.
|
||||
* @param $quiz the quiz object.
|
||||
*/
|
||||
function quiz_save_new_layout($quiz) {
|
||||
global $DB;
|
||||
$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id));
|
||||
quiz_update_sumgrades($quiz);
|
||||
quiz_delete_previews($quiz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save changes to question instance
|
||||
*
|
||||
@ -165,6 +222,52 @@ function quiz_update_question_instance($grade, $questionid, $quizid) {
|
||||
}
|
||||
}
|
||||
|
||||
// Private function used by the following two.
|
||||
function _quiz_move_question($layout, $questionid, $shift) {
|
||||
if (!$questionid || !($shift == 1 || $shift == -1)) {
|
||||
return $layout;
|
||||
}
|
||||
|
||||
$questionids = explode(',', $layout);
|
||||
$key = array_search($questionid, $questionids);
|
||||
if ($key === false) {
|
||||
return $layout;
|
||||
}
|
||||
|
||||
$otherkey = $key + $shift;
|
||||
if ($otherkey < 0 || $otherkey >= count($questionids) - 1) {
|
||||
return $layout;
|
||||
}
|
||||
|
||||
$temp = $questionids[$otherkey];
|
||||
$questionids[$otherkey] = $questionids[$key];
|
||||
$questionids[$key] = $temp;
|
||||
|
||||
return implode(',', $questionids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a particular question one space earlier in the $quiz->questions list.
|
||||
* If that is not possible, do nothing.
|
||||
* @param string $layout the existinng layout, $quiz->questions.
|
||||
* @param integer $questionid the id of a question.
|
||||
* @return the updated layout
|
||||
*/
|
||||
function quiz_move_question_up($layout, $questionid) {
|
||||
return _quiz_move_question($layout, $questionid, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a particular question one space later in the $quiz->questions list.
|
||||
* If that is not possible, do nothing.
|
||||
* @param string $layout the existinng layout, $quiz->questions.
|
||||
* @param integer $questionid the id of a question.
|
||||
* @return the updated layout
|
||||
*/
|
||||
function quiz_move_question_down($layout, $questionid) {
|
||||
return _quiz_move_question($layout, $questionid, +1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a list of quiz questions for the edit.php main view for edit
|
||||
* ($reordertool=false) and order and paging ($reordertool=true) tabs
|
||||
@ -319,30 +422,28 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete=true,
|
||||
$questions[$qnum]->qtype = 'missingtype';
|
||||
}
|
||||
$deletex="delete.gif";
|
||||
if($qnum!=0 OR ($qnum==0&&!$pageopen)){
|
||||
if ($qnum != 0 || ($qnum == 0 && !$pageopen)) {
|
||||
//this is either a question or a page break after another
|
||||
// (no page is currently open)
|
||||
if(!$pageopen){
|
||||
if (!$pageopen) {
|
||||
//if no page is open, start display of a page
|
||||
$pagecount++;
|
||||
echo '<div class="quizpage"><span class="pagetitle">'.
|
||||
get_string('page').' '.$pagecount.
|
||||
'</span><div class="pagecontent">';
|
||||
$pageopen=true;
|
||||
$pageopen = true;
|
||||
}
|
||||
if($qnum==0 && $i<$questiontotalcount){
|
||||
//this is a consequent 0 (signaling empty page), tell
|
||||
// the user the page is empty
|
||||
if ($qnum == 0 && $i < $questiontotalcount) {
|
||||
// This is the second successive page break. Tell the user the page is empty.
|
||||
echo '<div class="pagestatus">';
|
||||
print_string("noquestionsonpage", "quiz");
|
||||
echo '</div>';
|
||||
if ($allowdelete && !$quiz->questionsperpage) { // remove from quiz, not question delete.
|
||||
if ($allowdelete && !$quiz->questionsperpage) {
|
||||
echo '<div class="quizpagedelete">';
|
||||
echo "<a title=\"".get_string("removeemptypage","quiz")."\" href=\"".
|
||||
$pageurl->out_action(array('deleteemptypage'=>$i)).
|
||||
"\"><img src=\"$CFG->pixpath/t/delete.gif\" ".
|
||||
"class=\"iconsmall\"".
|
||||
" alt=\"$strremove\" /></a>";
|
||||
echo '<a title="' . get_string('removeemptypage', 'quiz') . '" href="' .
|
||||
$pageurl->out_action(array('deleteemptypage' => $i - 1)) .
|
||||
'"><img src="' . $CFG->pixpath . '/t/delete.gif" ' .
|
||||
'class="iconsmall" alt="' . $strremove . '" /></a>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
@ -396,31 +497,31 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete=true,
|
||||
<div class="questioncontrols">
|
||||
<?php
|
||||
if ($count != 0) {
|
||||
if(!$hasattempts){
|
||||
if (!$hasattempts) {
|
||||
$upbuttonclass="";
|
||||
if (!($count < $lastindex-1)) {
|
||||
if ($count >= $lastindex - 1) {
|
||||
$upbuttonclass="upwithoutdown";
|
||||
}
|
||||
echo "<a title=\"$strmoveup\" href=\"".
|
||||
$pageurl->out_action(array('up'=>$count))."\"><img
|
||||
$pageurl->out_action(array('up' => $question->id))."\"><img
|
||||
src=\"$CFG->pixpath/t/up.gif\" class=\"iconsmall
|
||||
$upbuttonclass\" alt=\"$strmoveup\" /></a>";
|
||||
}
|
||||
|
||||
}
|
||||
if ($count < $lastindex-1) {
|
||||
if ($count < $lastindex - 1) {
|
||||
if(!$hasattempts){
|
||||
echo "<a title=\"$strmovedown\" href=\"".
|
||||
$pageurl->out_action(array('down'=>$count))."\"><img
|
||||
$pageurl->out_action(array('down' => $question->id))."\"><img
|
||||
src=\"$CFG->pixpath/t/down.gif\" class=\"iconsmall\"".
|
||||
" alt=\"$strmovedown\" /></a>";
|
||||
}
|
||||
}
|
||||
if ($allowdelete && question_has_capability_on($question, 'use',
|
||||
$question->category)) { // remove from quiz, not question delete.
|
||||
if(!$hasattempts){
|
||||
if ($allowdelete && question_has_capability_on($question, 'use', $question->category)) {
|
||||
// remove from quiz, not question delete.
|
||||
if (!$hasattempts) {
|
||||
echo "<a title=\"$strremove\" href=\"".
|
||||
$pageurl->out_action(array('delete'=>$count))."\">
|
||||
$pageurl->out_action(array('remove' => $question->id))."\">
|
||||
<img src=\"$CFG->pixpath/t/delete.gif\" ".
|
||||
"class=\"iconsmall\" alt=\"$strremove\" /></a>";
|
||||
}
|
||||
@ -437,7 +538,7 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete=true,
|
||||
<?php echo $pageurl->hidden_params_out(); ?>
|
||||
<input type="hidden" name="savechanges" value="save" />
|
||||
<?php
|
||||
echo '<input type="text" name="q'.$qnum.'" id="inputq'.$qnum.'" size="' . ($quiz->decimalpoints + 2) . '"
|
||||
echo '<input type="text" name="g'.$qnum.'" id="inputq'.$qnum.'" size="' . ($quiz->decimalpoints + 2) . '"
|
||||
value="'.(0 + $quiz->grades[$qnum]).
|
||||
'" tabindex="'.($lastindex+$qno).'" />';
|
||||
?>
|
||||
|
@ -204,6 +204,24 @@ function quiz_delete_attempt($attempt, $quiz) {
|
||||
quiz_update_grades($quiz, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the preview attempts at a quiz, or possibly all the attempts belonging
|
||||
* to one user.
|
||||
* @param object $quiz the quiz object.
|
||||
* @param integer $userid (optional) if given, only delete the previews belonging to this user.
|
||||
*/
|
||||
function quiz_delete_previews($quiz, $userid = null) {
|
||||
global $DB;
|
||||
$conditions = array('quiz' => $quiz->id, 'preview' => 1);
|
||||
if (!empty($userid)) {
|
||||
$conditions['userid'] = $userid;
|
||||
}
|
||||
$previewattempts = $DB->get_records('quiz_attempts', $conditions);
|
||||
foreach ($previewattempts as $attempt) {
|
||||
quiz_delete_attempt($attempt, $quiz);
|
||||
}
|
||||
}
|
||||
|
||||
/// Functions to do with quiz layout and pages ////////////////////////////////
|
||||
|
||||
/**
|
||||
@ -298,7 +316,7 @@ function quiz_first_questionnumber($quizlayout, $pagelayout) {
|
||||
* @param boolean $shuffle Should the questions be reordered randomly?
|
||||
* @return string the new layout string
|
||||
*/
|
||||
function quiz_repaginate($layout, $perpage, $shuffle=false) {
|
||||
function quiz_repaginate($layout, $perpage, $shuffle = false) {
|
||||
$layout = str_replace(',0', '', $layout); // remove existing page breaks
|
||||
$questions = explode(',', $layout);
|
||||
//remove empty pages from beginning
|
||||
@ -306,7 +324,6 @@ function quiz_repaginate($layout, $perpage, $shuffle=false) {
|
||||
array_shift($questions);
|
||||
}
|
||||
if ($shuffle) {
|
||||
srand((float)microtime() * 1000000); // for php < 4.2
|
||||
shuffle($questions);
|
||||
}
|
||||
$i = 1;
|
||||
|
62
mod/quiz/simpletest/testeditlib.php
Normal file
62
mod/quiz/simpletest/testeditlib.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Unit tests for (some of) mod/quiz/editlib.php.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
* @package quiz
|
||||
*/
|
||||
|
||||
if (!defined('MOODLE_INTERNAL')) {
|
||||
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page.
|
||||
}
|
||||
|
||||
require_once($CFG->dirroot . '/mod/quiz/editlib.php');
|
||||
|
||||
class quiz_editlib_test extends UnitTestCase {
|
||||
function test_quiz_move_question_up() {
|
||||
$this->assertEqual(quiz_move_question_up('0', 123), '0');
|
||||
$this->assertEqual(quiz_move_question_up('1,2,0', 1), '1,2,0');
|
||||
$this->assertEqual(quiz_move_question_up('1,2,0', 0), '1,2,0');
|
||||
$this->assertEqual(quiz_move_question_up('1,2,0', 2), '2,1,0');
|
||||
$this->assertEqual(quiz_move_question_up('1,2,0,3,4,0', 3), '1,2,3,0,4,0');
|
||||
$this->assertEqual(quiz_move_question_up('1,2,3,0,4,0', 4), '1,2,3,4,0,0');
|
||||
}
|
||||
|
||||
function test_quiz_move_question_down() {
|
||||
$this->assertEqual(quiz_move_question_down('0', 123), '0');
|
||||
$this->assertEqual(quiz_move_question_down('1,2,0', 2), '1,2,0');
|
||||
$this->assertEqual(quiz_move_question_down('1,2,0', 0), '1,2,0');
|
||||
$this->assertEqual(quiz_move_question_down('1,2,0', 1), '2,1,0');
|
||||
$this->assertEqual(quiz_move_question_down('1,2,0,3,4,0', 2), '1,0,2,3,4,0');
|
||||
$this->assertEqual(quiz_move_question_down('1,0,2,3,0,4,0', 1), '0,1,2,3,0,4,0');
|
||||
}
|
||||
|
||||
function test_quiz_delete_empty_page() {
|
||||
$this->assertEqual(quiz_delete_empty_page('0', 0), '0');
|
||||
$this->assertEqual(quiz_delete_empty_page('1,2,0', 2), '1,2,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('0,1,2,0', -1), '1,2,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('0,1,2,0', 0), '0,1,2,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('1,2,0', 3), '1,2,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('1,2,0', -1), '1,2,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('1,2,0,0', 2), '1,2,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('1,2,0,0', 1), '1,2,0,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('1,2,0,0,3,4,0', 2), '1,2,0,3,4,0');
|
||||
$this->assertEqual(quiz_delete_empty_page('0,0,1,2,0', 0), '0,1,2,0');
|
||||
}
|
||||
|
||||
function test_quiz_add_page_break_after() {
|
||||
$this->assertEqual(quiz_add_page_break_after('0', 1), '0');
|
||||
$this->assertEqual(quiz_add_page_break_after('1,2,0', 1), '1,0,2,0');
|
||||
$this->assertEqual(quiz_add_page_break_after('1,2,0', 2), '1,2,0,0');
|
||||
$this->assertEqual(quiz_add_page_break_after('1,2,0', 0), '1,2,0');
|
||||
}
|
||||
|
||||
function test_quiz_add_page_break_at() {
|
||||
$this->assertEqual(quiz_add_page_break_at('0', 0), '0,0');
|
||||
$this->assertEqual(quiz_add_page_break_at('1,2,0', 0), '0,1,2,0');
|
||||
$this->assertEqual(quiz_add_page_break_at('1,2,0', 1), '1,0,2,0');
|
||||
$this->assertEqual(quiz_add_page_break_at('1,2,0', 2), '1,2,0,0');
|
||||
$this->assertEqual(quiz_add_page_break_at('1,2,0', 3), '1,2,0');
|
||||
}
|
||||
}
|
||||
?>
|
@ -89,12 +89,7 @@ if (!$quizobj->is_preview_user() && $messages) {
|
||||
$accessmanager->do_password_check($quizobj->is_preview_user());
|
||||
|
||||
/// Delete any previous preview attempts belonging to this user.
|
||||
if ($oldattempts = $DB->get_records_select('quiz_attempts', "quiz = ?
|
||||
AND userid = ? AND preview = 1", array($quiz->id, $USER->id))) {
|
||||
foreach ($oldattempts as $oldattempt) {
|
||||
quiz_delete_attempt($oldattempt, $quiz);
|
||||
}
|
||||
}
|
||||
quiz_delete_previews($quiz, $USER->id);
|
||||
|
||||
/// Create the new attempt and initialize the question sessions
|
||||
$attempt = quiz_create_attempt($quiz, $attemptnumber, $lastattempt, time(), $quizobj->is_preview_user());
|
||||
|
Loading…
x
Reference in New Issue
Block a user