/** * 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; $questionids = explode(',', $quiz->questions); $key = array_search($questionid, $questionids); if ($key === false) { return; } 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)); $qtype = $DB->get_field('question', 'qtype', array('id' => $questionid)); if ($qtype === 'random') { // This function automatically checks if the question is in use, and won't delete if it is. question_delete_question($questionid); } }
/** * 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_slot($quiz, $slotnumber) { global $DB; $slot = $DB->get_record('quiz_slots', array('quizid' => $quiz->id, 'slot' => $slotnumber)); $maxslot = $DB->get_field_sql('SELECT MAX(slot) FROM {quiz_slots} WHERE quizid = ?', array($quiz->id)); if (!$slot) { return; } $trans = $DB->start_delegated_transaction(); $DB->delete_records('quiz_slots', array('id' => $slot->id)); for ($i = $slot->slot + 1; $i <= $maxslot; $i++) { $DB->set_field('quiz_slots', 'slot', $i - 1, array('quizid' => $quiz->id, 'slot' => $i)); } $qtype = $DB->get_field('question', 'qtype', array('id' => $slot->questionid)); if ($qtype === 'random') { // This function automatically checks if the question is in use, and won't delete if it is. question_delete_question($slot->questionid); } $trans->allow_commit(); }
/** * All question categories and their questions are deleted for this activity. * * @param object $cm the course module object representing the activity * @param boolean $feedback to specify if the process must output a summary of its work * @return boolean */ function question_delete_activity($cm, $feedback = true) { global $DB, $OUTPUT; //To store feedback to be showed at the end of the process $feedbackdata = array(); //Cache some strings $strcatdeleted = get_string('unusedcategorydeleted', 'quiz'); $modcontext = context_module::instance($cm->id); 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); foreach ($categoriesmods as $category) { //Delete it completely (questions and category itself) //deleting questions 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)); } //delete the category $DB->delete_records('question_categories', array('id' => $category->id)); //Fill feedback $feedbackdata[] = array($category->name, $strcatdeleted); } //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->data = $feedbackdata; echo html_writer::table($table); } } return true; }
/** * Deletes question and all associated data from the database * * It will not delete a question if it is used by an activity module * @param object $question The question being deleted */ function question_delete_question($questionid) { global $DB; $question = $DB->get_record_sql(' SELECT q.*, qc.contextid FROM {question} q JOIN {question_categories} qc ON qc.id = q.category WHERE q.id = ?', array($questionid)); if (!$question) { // In some situations, for example if this was a child of a // Cloze question that was previously deleted, the question may already // have gone. In this case, just do nothing. return; } // Do not delete a question if it is used by an activity module if (questions_in_use(array($questionid))) { return; } $dm = new question_engine_data_mapper(); $dm->delete_previews($questionid); // delete questiontype-specific data question_bank::get_qtype($question->qtype, false)->delete_question($questionid, $question->contextid); // Delete all tag instances. $DB->delete_records('tag_instance', array('component' => 'core_question', 'itemid' => $question->id)); // Now recursively delete all child questions if ($children = $DB->get_records('question', array('parent' => $questionid), '', 'id, qtype')) { foreach ($children as $child) { if ($child->id != $questionid) { question_delete_question($child->id); } } } // Finally delete the question record itself $DB->delete_records('question', array('id' => $questionid)); question_bank::notify_question_edited($questionid); }
public function save_question_options($question) { global $DB; $result = new stdClass(); // This function needs to be able to handle the case where the existing set of wrapped // questions does not match the new set of wrapped questions so that some need to be // created, some modified and some deleted // Unfortunately the code currently simply overwrites existing ones in sequence. This // will make re-marking after a re-ordering of wrapped questions impossible and // will also create difficulties if questiontype specific tables reference the id. // First we get all the existing wrapped questions if (!($oldwrappedids = $DB->get_field('question_multianswer', 'sequence', array('question' => $question->id)))) { $oldwrappedquestions = array(); } else { $oldwrappedquestions = $DB->get_records_list('question', 'id', explode(',', $oldwrappedids), 'id ASC'); } $sequence = array(); foreach ($question->options->questions as $wrapped) { if (!empty($wrapped)) { // if we still have some old wrapped question ids, reuse the next of them if (is_array($oldwrappedquestions) && ($oldwrappedquestion = array_shift($oldwrappedquestions))) { $wrapped->id = $oldwrappedquestion->id; if ($oldwrappedquestion->qtype != $wrapped->qtype) { switch ($oldwrappedquestion->qtype) { case 'multichoice': $DB->delete_records('question_multichoice', array('question' => $oldwrappedquestion->id)); break; case 'shortanswer': $DB->delete_records('question_shortanswer', array('question' => $oldwrappedquestion->id)); break; case 'numerical': $DB->delete_records('question_numerical', array('question' => $oldwrappedquestion->id)); break; default: throw new moodle_exception('qtypenotrecognized', 'qtype_multianswer', '', $oldwrappedquestion->qtype); $wrapped->id = 0; } } } else { $wrapped->id = 0; } } $wrapped->name = $question->name; $wrapped->parent = $question->id; $previousid = $wrapped->id; // save_question strips this extra bit off the category again. $wrapped->category = $question->category . ',1'; $wrapped = question_bank::get_qtype($wrapped->qtype)->save_question($wrapped, clone $wrapped); $sequence[] = $wrapped->id; if ($previousid != 0 && $previousid != $wrapped->id) { // for some reasons a new question has been created // so delete the old one question_delete_question($previousid); } } // Delete redundant wrapped questions if (is_array($oldwrappedquestions) && count($oldwrappedquestions)) { foreach ($oldwrappedquestions as $oldwrappedquestion) { question_delete_question($oldwrappedquestion->id); } } if (!empty($sequence)) { $multianswer = new stdClass(); $multianswer->question = $question->id; $multianswer->sequence = implode(',', $sequence); if ($oldid = $DB->get_field('question_multianswer', 'id', array('question' => $question->id))) { $multianswer->id = $oldid; $DB->update_record('question_multianswer', $multianswer); } else { $DB->insert_record('question_multianswer', $multianswer); } } $this->save_hints($question); }
/** * Given an ID of an instance of this module, * this function will permanently delete the instance * and any data that depends on it. * * @param int $id the id of the quiz to delete. * @return bool success or failure. */ function quiz_delete_instance($id) { global $DB; $quiz = $DB->get_record('quiz', array('id' => $id), '*', MUST_EXIST); quiz_delete_all_attempts($quiz); quiz_delete_all_overrides($quiz); // Look for random questions that may no longer be used when this quiz is gone. $sql = "SELECT q.id\n FROM {quiz_slots} slot\n JOIN {question} q ON q.id = slot.questionid\n WHERE slot.quizid = ? AND q.qtype = ?"; $questionids = $DB->get_fieldset_sql($sql, array($quiz->id, 'random')); // We need to do this before we try and delete randoms, otherwise they would still be 'in use'. $DB->delete_records('quiz_slots', array('quizid' => $quiz->id)); $DB->delete_records('quiz_sections', array('quizid' => $quiz->id)); foreach ($questionids as $questionid) { question_delete_question($questionid); } $DB->delete_records('quiz_feedback', array('quizid' => $quiz->id)); quiz_access_manager::delete_settings($quiz); $events = $DB->get_records('event', array('modulename' => 'quiz', 'instance' => $quiz->id)); foreach ($events as $event) { $event = calendar_event::load($event); $event->delete(); } quiz_grade_item_delete($quiz); $DB->delete_records('quiz', array('id' => $quiz->id)); return true; }
public function process_actions() { global $CFG, $DB; /// Now, check for commands on this page and modify variables as necessary if (optional_param('move', false, PARAM_BOOL) and confirm_sesskey()) { // Move selected questions to new category $category = required_param('category', PARAM_SEQUENCE); list($tocategoryid, $contextid) = explode(',', $category); if (! $tocategory = $DB->get_record('question_categories', array('id' => $tocategoryid, 'contextid' => $contextid))) { print_error('cannotfindcate', 'question'); } $tocontext = context::instance_by_id($contextid); require_capability('moodle/question:add', $tocontext); $rawdata = (array) data_submitted(); $questionids = array(); foreach ($rawdata as $key => $value) { // Parse input for question ids if (preg_match('!^q([0-9]+)$!', $key, $matches)) { $key = $matches[1]; $questionids[] = $key; } } if ($questionids) { list($usql, $params) = $DB->get_in_or_equal($questionids); $sql = ""; $questions = $DB->get_records_sql(" SELECT q.*, c.contextid FROM {question} q JOIN {question_categories} c ON c.id = q.category WHERE q.id $usql", $params); foreach ($questions as $question){ question_require_capability_on($question, 'move'); } question_move_questions_to_category($questionids, $tocategory->id); redirect($this->baseurl->out(false, array('category' => "$tocategoryid,$contextid"))); } } if (optional_param('deleteselected', false, PARAM_BOOL)) { // delete selected questions from the category if (($confirm = optional_param('confirm', '', PARAM_ALPHANUM)) and confirm_sesskey()) { // teacher has already confirmed the action $deleteselected = required_param('deleteselected', PARAM_RAW); if ($confirm == md5($deleteselected)) { if ($questionlist = explode(',', $deleteselected)) { // for each question either hide it if it is in use or delete it foreach ($questionlist as $questionid) { $questionid = (int)$questionid; question_require_capability_on($questionid, 'edit'); if (questions_in_use(array($questionid))) { $DB->set_field('question', 'hidden', 1, array('id' => $questionid)); } else { question_delete_question($questionid); } } } redirect($this->baseurl); } else { print_error('invalidconfirm', 'question'); } } } // Unhide a question if(($unhide = optional_param('unhide', '', PARAM_INT)) and confirm_sesskey()) { question_require_capability_on($unhide, 'edit'); $DB->set_field('question', 'hidden', 0, array('id' => $unhide)); // Purge these questions from the cache. question_bank::notify_question_edited($unhide); redirect($this->baseurl); } }
/** * Remove a slot from a offlinequiz * @param \stdClass $offlinequiz the offlinequiz object. * @param int $slotnumber The number of the slot to be deleted. */ public function remove_slot($offlinequiz, $slotnumber) { global $DB; $this->check_can_be_edited(); $slot = $DB->get_record('offlinequiz_group_questions', array('offlinequizid' => $offlinequiz->id, 'offlinegroupid' => $offlinequiz->groupid, 'slot' => $slotnumber)); $maxslot = $DB->get_field_sql('SELECT MAX(slot) FROM {offlinequiz_group_questions} WHERE offlinequizid = ? AND offlinegroupid = ?', array($offlinequiz->id, $offlinequiz->groupid)); if (!$slot) { return; } $trans = $DB->start_delegated_transaction(); $DB->delete_records('offlinequiz_group_questions', array('id' => $slot->id)); for ($i = $slot->slot + 1; $i <= $maxslot; $i++) { $DB->set_field('offlinequiz_group_questions', 'slot', $i - 1, array('offlinequizid' => $offlinequiz->id, 'offlinegroupid' => $offlinequiz->groupid, 'slot' => $i)); } $qtype = $DB->get_field('question', 'qtype', array('id' => $slot->questionid)); if ($qtype === 'random') { // This function automatically checks if the question is in use, and won't delete if it is. question_delete_question($slot->questionid); } unset($this->questions[$slot->questionid]); $this->refresh_page_numbers_and_update_db($offlinequiz); $trans->allow_commit(); }
function RWSDQCat($r_qci) { global $DB; global $CFG; $r_chn = $DB->get_records("question_categories", array("parent" => $r_qci)); if (count($r_chn) > 0) { foreach ($r_chn as $r_chd) { RWSDQCat($r_chd->id); } } $r_qsts = $DB->get_records("question", array("category" => $r_qci)); if (count($r_qsts) > 0) { foreach ($r_qsts as $r_q) { if (respondusws_floatcompare($CFG->version, 2011070100, 2) >= 0) { question_delete_question($r_q->id); } else { delete_question($r_q->id); } } $DB->delete_records("question", array("category" => $r_qci)); } $DB->delete_records("question_categories", array("id" => $r_qci)); }
/** * Remove a slot from a quiz * @param int $slotnumber The number of the slot to be deleted. */ public function remove_slot($slotnumber) { global $DB; $this->check_can_be_edited(); if ($this->is_only_slot_in_section($slotnumber)) { throw new \coding_exception('You cannot remove the last slot in a section.'); } $slot = $DB->get_record('quiz_slots', array('quizid' => $this->get_quizid(), 'slot' => $slotnumber)); if (!$slot) { return; } $maxslot = $DB->get_field_sql('SELECT MAX(slot) FROM {quiz_slots} WHERE quizid = ?', array($this->get_quizid())); $trans = $DB->start_delegated_transaction(); $DB->delete_records('quiz_slots', array('id' => $slot->id)); for ($i = $slot->slot + 1; $i <= $maxslot; $i++) { $DB->set_field('quiz_slots', 'slot', $i - 1, array('quizid' => $this->get_quizid(), 'slot' => $i)); } $qtype = $DB->get_field('question', 'qtype', array('id' => $slot->questionid)); if ($qtype === 'random') { // This function automatically checks if the question is in use, and won't delete if it is. question_delete_question($slot->questionid); } $DB->execute("\n UPDATE {quiz_sections}\n SET firstslot = firstslot - 1\n WHERE quizid = ?\n AND firstslot > ?\n ", array($this->get_quizid(), $slotnumber)); unset($this->questions[$slot->questionid]); $this->refresh_page_numbers_and_update_db(); $trans->allow_commit(); }