} else { require_capability('moodle/question:add', context::instance_by_id($newcontextid)); if (!empty($fromform->makecopy) && !$question->formoptions->cansaveasnew) { print_error('nopermissions', '', '', 'edit'); } } $question = $qtypeobj->save_question($question, $fromform); if (!empty($CFG->usetags) && isset($fromform->tags)) { // A wizardpage from multipe pages questiontype like calculated may not // allow editing the question tags, hence the isset($fromform->tags) test. require_once $CFG->dirroot . '/tag/lib.php'; tag_set('question', $question->id, $fromform->tags); } } // Purge this question from the cache. question_bank::notify_question_edited($question->id); if ($qtypeobj->finished_edit_wizard($fromform) || $movecontext) { if ($inpopup) { echo $OUTPUT->notification(get_string('changessaved'), ''); close_window(3); } else { $returnurl->param('lastchanged', $question->id); if ($appendqnumstring) { $returnurl->param($appendqnumstring, $question->id); $returnurl->param('sesskey', sesskey()); $returnurl->param('cmid', $cmid); } redirect($returnurl); } } else { $nexturlparams = array('returnurl' => $originalreturnurl, 'appendqnumstring' => $appendqnumstring, 'scrollpos' => $scrollpos);
/** * This function helps move a question cateogry to a new context by moving all * the files belonging to all the questions to the new context. * Also moves subcategories. * @param integer $categoryid the id of the category being moved. * @param integer $oldcontextid the old context id. * @param integer $newcontextid the new context id. */ function question_move_category_to_context($categoryid, $oldcontextid, $newcontextid) { global $DB; $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); // Purge this question from the cache. question_bank::notify_question_edited($questionid); } $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)); question_move_category_to_context($subcatid, $oldcontextid, $newcontextid); } }
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); } }
/** * This function helps move a question cateogry to a new context by moving all * the files belonging to all the questions to the new context. * Also moves subcategories. * @param integer $categoryid the id of the category being moved. * @param integer $oldcontextid the old context id. * @param integer $newcontextid the new context id. */ function question_move_category_to_context($categoryid, $oldcontextid, $newcontextid) { global $DB; $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); // Purge this question from the cache. question_bank::notify_question_edited($questionid); } if ($questionids) { // Update the contextid for any tag instances that may exist for these questions. list($questionids, $params) = $DB->get_in_or_equal(array_keys($questionids)); $DB->set_field_select('tag_instance', 'contextid', $newcontextid, "component = 'core_question' AND itemid {$questionids}", $params); } $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)); question_move_category_to_context($subcatid, $oldcontextid, $newcontextid); } }
public function save_question_options($question) { global $DB, $USER; assert(isset($question->coderunnertype)); $fields = $this->extra_question_fields(); array_shift($fields); // Discard table name $customised = isset($question->customise) && $question->customise; $isprototype = $question->prototypetype != 0; if ($customised && $question->prototypetype == 2 && $question->coderunnertype != $question->typename) { // Saving a new user-defined prototype. // Copy new type name into coderunnertype $question->coderunnertype = $question->typename; } // If we're saving a new prototype, make sure its coderunnertype is // unique by appending a suitable suffix. [Shouldn't happen via // question edit form, but could be a spurious import or a question // duplication mouse click.] if ($question->isnew && $isprototype) { $suffix = ''; $type = $question->coderunnertype; while (true) { try { $row = $this->get_prototype($type . $suffix, $question->context); $suffix = $suffix == '' ? '-1' : $suffix - 1; } catch (coderunner_exception $e) { break; } } $question->coderunnertype = $type . $suffix; } // Set all inherited fields to null if the corresponding form // field is blank or if it's being saved with customise explicitly // turned off and it's not a prototype. $questioninherits = isset($question->customise) && !$question->customise && !$isprototype; foreach ($fields as $field) { $isinherited = !in_array($field, $this->noninherited_fields()); $isblankstring = !isset($question->{$field}) || is_string($question->{$field}) && trim($question->{$field}) === ''; if ($isinherited && ($isblankstring || $questioninherits)) { $question->{$field} = null; } } if (trim($question->sandbox) === 'DEFAULT') { $question->sandbox = null; } parent::save_question_options($question); $testcasetable = "question_coderunner_tests"; if (!isset($question->testcases)) { $this->copy_testcases_from_form($question); } if (!($oldtestcases = $DB->get_records($testcasetable, array('questionid' => $question->id), 'id ASC'))) { $oldtestcases = array(); } foreach ($question->testcases as $tc) { if ($oldtestcase = array_shift($oldtestcases)) { // Existing testcase, so reuse it $tc->id = $oldtestcase->id; $DB->update_record($testcasetable, $tc); } else { // A new testcase $tc->questionid = $question->id; $id = $DB->insert_record($testcasetable, $tc); } } // delete old testcase records foreach ($oldtestcases as $otc) { $DB->delete_records($testcasetable, array('id' => $otc->id)); } // If this is a prototype, clear the caching of any child questions if ($question->prototypetype != 0) { $typename = $question->coderunnertype; $children = $DB->get_records('question_coderunner_options', array('prototypetype' => 0, 'coderunnertype' => $typename)); foreach ($children as $child) { question_bank::notify_question_edited($child->questionid); } } // Lastly, save any datafiles if ($USER->id && isset($question->datafiles)) { // The id check is a hack to deal with phpunit initialisation, when no user exists file_save_draft_area_files($question->datafiles, $question->context->id, 'qtype_coderunner', 'datafile', (int) $question->id, $this->fileoptions); } return true; }