question bank MDL-24995 clean up a lot of deprecated code to do with moving questions around.

This should also fix MDL-25172, MDL-23021 and MDL-23073. In other words, moving questions between categories should now work.
This commit is contained in:
Tim Hunt
2010-11-11 21:54:22 +00:00
parent 333fde7664
commit 5d548d3e0a
20 changed files with 205 additions and 1474 deletions
+47 -169
View File
@@ -120,16 +120,6 @@ define('QUESTION_PREVIEW_POPUP_OPTIONS', 'scrollbars=yes&resizable=yes&width=700
define('QUESTION_ADAPTIVE', 1);
/**#@-*/
/**#@+
* Options used in forms that move files.
*/
define('QUESTION_FILENOTHINGSELECTED', 0);
define('QUESTION_FILEDONOTHING', 1);
define('QUESTION_FILECOPY', 2);
define('QUESTION_FILEMOVE', 3);
define('QUESTION_FILEMOVELINKSONLY', 4);
/**#@-*/
/**#@+
* Options for whether flags are shown/editable when rendering questions.
*/
@@ -718,7 +708,7 @@ function question_delete_course_category($category, $newcategory, $feedback=true
// 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(implode(',', array_keys($questionids)),
if (!$rescueqcategory = question_save_from_deletion(array_keys($questionids),
get_parent_contextid($context), print_context_name($context), $rescueqcategory)) {
return false;
}
@@ -854,32 +844,57 @@ function question_delete_activity($cm, $feedback=true) {
function question_move_questions_to_category($questionids, $newcategoryid) {
global $DB, $QTYPES;
$ids = explode(',', $questionids);
foreach ($ids as $questionid) {
$questionid = (int)$questionid;
$params = array();
$params[] = $questionid;
$sql = 'SELECT q.*, c.id AS contextid, c.contextlevel, c.instanceid, c.path, c.depth
FROM {question} q, {question_categories} qc, {context} c
WHERE q.category=qc.id AND q.id=? AND qc.contextid=c.id';
$question = $DB->get_record_sql($sql, $params);
$category = $DB->get_record('question_categories', array('id'=>$newcategoryid));
// process files
$QTYPES[$question->qtype]->move_files($question, $category);
$newcontextid = $DB->get_field('question_categories', 'contextid',
array('id' => $newcategoryid));
list($questionidcondition, $params) = $DB->get_in_or_equal($questionids);
$questions = $DB->get_records_sql("
SELECT q.id, q.qtype, qc.contextid
FROM {question} q
JOIN {question_categories} qc ON q.category = qc.id
WHERE q.id $questionidcondition", $params);
foreach ($questions as $question) {
if ($newcontextid != $question->contextid) {
$QTYPES[$question->qtype]->move_files($question->id,
$question->contextid, $newcontextid);
}
}
// Move the questions themselves.
$DB->set_field_select('question', 'category', $newcategoryid, "id IN ($questionids)");
$DB->set_field_select('question', 'category', $newcategoryid, "id $questionidcondition", $params);
// Move any subquestions belonging to them.
$DB->set_field_select('question', 'category', $newcategoryid, "parent IN ($questionids)");
$DB->set_field_select('question', 'category', $newcategoryid, "parent $questionidcondition", $params);
// TODO Deal with datasets.
return true;
}
/**
* 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, $QTYPES;
$questionids = $DB->get_records_menu('question',
array('category' => $categoryid), '', 'id,qtype');
foreach ($questionids as $questionid => $qtype) {
$QTYPES[$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));
question_move_category_to_context($subcatid, $oldcontextid, $newcontextid);
}
}
/**
* 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.
@@ -1850,37 +1865,11 @@ function print_question_icon($question, $return = false) {
}
/**
* Returns a html link to the question image if there is one
*
* @global object
* @global object
* @return string The html image tag or the empy string if there is no image.
* @param object $question The question object
*/
function get_question_image($question) {
global $CFG, $DB;
$img = '';
if (!$category = $DB->get_record('question_categories', array('id'=>$question->category))) {
print_error('invalidcategory');
}
$coursefilesdir = get_filesdir_from_context(get_context_instance_by_id($category->contextid));
if ($question->image) {
if (substr(strtolower($question->image), 0, 7) == 'http://') {
$img .= $question->image;
} else {
require_once($CFG->libdir .'/filelib.php');
$img = get_file_url("$coursefilesdir/{$question->image}");
}
}
return $img;
}
/**
* @global array
* @param $question
* @param $state
* @param $prefix
* @param $cmoptions
* @param $caption
*/
function question_print_comment_fields($question, $state, $prefix, $cmoptions, $caption = '') {
global $QTYPES;
@@ -2826,117 +2815,6 @@ function question_require_capability_on($question, $cap){
return true;
}
/**
* @global object
*/
function question_file_links_base_url($courseid){
global $CFG;
$baseurl = preg_quote("$CFG->wwwroot/file.php", '!');
$baseurl .= '('.preg_quote('?file=', '!').')?';//may or may not
//be using slasharguments, accept either
$baseurl .= "/$courseid/";//course directory
return $baseurl;
}
/**
* Find all course / site files linked to in a piece of html.
* @global object
* @param string html the html to search
* @param int course search for files for courseid course or set to siteid for
* finding site files.
* @return array files with keys being files.
*/
function question_find_file_links_from_html($html, $courseid){
global $CFG;
$baseurl = question_file_links_base_url($courseid);
$searchfor = '!'.
'(<\s*(a|img)\s[^>]*(href|src)\s*=\s*")'.$baseurl.'([^"]*)"'.
'|'.
'(<\s*(a|img)\s[^>]*(href|src)\s*=\s*\')'.$baseurl.'([^\']*)\''.
'!i';
$matches = array();
$no = preg_match_all($searchfor, $html, $matches);
if ($no){
$rawurls = array_filter(array_merge($matches[5], $matches[10]));//array_filter removes empty elements
//remove any links that point somewhere they shouldn't
foreach (array_keys($rawurls) as $rawurlkey){
if (!$cleanedurl = question_url_check($rawurls[$rawurlkey])){
unset($rawurls[$rawurlkey]);
} else {
$rawurls[$rawurlkey] = $cleanedurl;
}
}
$urls = array_flip($rawurls);// array_flip removes duplicate files
// and when we merge arrays will continue to automatically remove duplicates
} else {
$urls = array();
}
return $urls;
}
/**
* Check that url doesn't point anywhere it shouldn't
*
* @global object
* @param $url string relative url within course files directory
* @return mixed boolean false if not OK or cleaned URL as string if OK
*/
function question_url_check($url){
global $CFG;
if ((substr(strtolower($url), 0, strlen($CFG->moddata)) == strtolower($CFG->moddata)) ||
(substr(strtolower($url), 0, 10) == 'backupdata')){
return false;
} else {
return clean_param($url, PARAM_PATH);
}
}
/**
* Find all course / site files linked to in a piece of html.
*
* @global object
* @param string html the html to search
* @param int course search for files for courseid course or set to siteid for
* finding site files.
* @return array files with keys being files.
*/
function question_replace_file_links_in_html($html, $fromcourseid, $tocourseid, $url, $destination, &$changed){
global $CFG;
require_once($CFG->libdir .'/filelib.php');
$tourl = get_file_url("$tocourseid/$destination");
$fromurl = question_file_links_base_url($fromcourseid).preg_quote($url, '!');
$searchfor = array('!(<\s*(a|img)\s[^>]*(href|src)\s*=\s*")'.$fromurl.'(")!i',
'!(<\s*(a|img)\s[^>]*(href|src)\s*=\s*\')'.$fromurl.'(\')!i');
$newhtml = preg_replace($searchfor, '\\1'.$tourl.'\\5', $html);
if ($newhtml != $html){
$changed = true;
}
return $newhtml;
}
/**
* @global object
*/
function get_filesdir_from_context($context){
global $DB;
switch ($context->contextlevel){
case CONTEXT_COURSE :
$courseid = $context->instanceid;
break;
case CONTEXT_MODULE :
$courseid = $DB->get_field('course_modules', 'course', array('id'=>$context->instanceid));
break;
case CONTEXT_COURSECAT :
case CONTEXT_SYSTEM :
$courseid = SITEID;
break;
default :
print_error('invalidcontext');
}
return $courseid;
}
/**
* Get the real state - the correct question id and answer - for a random
* question.
@@ -2944,7 +2822,7 @@ function get_filesdir_from_context($context){
* @return mixed return integer real question id or false if there was an
* error..
*/
function question_get_real_state($state){
function question_get_real_state($state) {
global $OUTPUT;
$realstate = clone($state);
$matches = array();
+13 -62
View File
@@ -38,24 +38,6 @@ class question_category_list extends moodle_list {
public function get_records() {
$this->records = get_categories_for_contexts($this->context->id, $this->sortby);
}
public function process_actions($left, $right, $moveup, $movedown, $moveupcontext, $movedowncontext, $tocontext){
global $CFG;
//parent::procces_actions redirects after any action
parent::process_actions($left, $right, $moveup, $movedown);
if ($tocontext == $this->context->id){
//only called on toplevel list
if ($moveupcontext){
$cattomove = $moveupcontext;
$totop = 0;
} elseif ($movedowncontext){
$cattomove = $movedowncontext;
$totop = 1;
}
$toparent = "0,{$this->context->id}";
$url = new moodle_url('/question/contextmove.php?', $this->pageurl->params() + compact('cattomove', 'totop', 'toparent'));
redirect($url);
}
}
}
class question_category_list_item extends list_item {
@@ -87,12 +69,13 @@ class question_category_list_item extends list_item {
/// Each section adds html to be displayed as part of this list item
$questionbankurl = new moodle_url("/question/edit.php", ($this->parentlist->pageurl->params() + array('category'=>"$category->id,$category->contextid")));
$catediturl = $this->parentlist->pageurl->out(true, array('edit'=>$this->id));
$catediturl = $this->parentlist->pageurl->out(true, array('edit' => $this->id));
$item = "<b><a title=\"{$str->edit}\" href=\"$catediturl\">".$category->name ."</a></b> <a title=\"$editqestions\" href=\"$questionbankurl\">".'('.$category->questioncount.')</a>';
$item .= '&nbsp;'. $category->info;
if (count($this->parentlist->records)!=1){ // don't allow delete if this is the last category in this context.
// don't allow delete if this is the last category in this context.
if (count($this->parentlist->records) != 1) {
$item .= '<a title="' . $str->delete . '" href="'.$this->parentlist->pageurl->out(true, array('delete'=>$this->id, 'sesskey'=>sesskey())).'">
<img src="' . $OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="' .$str->delete. '" /></a>';
}
@@ -374,11 +357,9 @@ class question_category_object {
public function move_questions($oldcat, $newcat){
global $DB;
$questionids = $DB->get_records_select_menu('question', "category = ? AND (parent = 0 OR parent = id)", array($oldcat), '', 'id,1');
$ids = implode(',', array_keys($questionids));
if (!question_move_questions_to_category($ids, $newcat)) {
print_error('errormovingquestions', 'question', $this->pageurl->out(), $ids);
}
$questionids = $DB->get_records_select_menu('question',
'category = ? AND (parent = 0 OR parent = id)', array($oldcat), '', 'id,1');
question_move_questions_to_category($questionids, $newcat);
}
/**
@@ -439,7 +420,7 @@ class question_category_object {
require_capability('moodle/question:managecategory', $fromcontext);
// If moving to another context, check permissions some more.
if ($oldcat->contextid != $tocontextid){
if ($oldcat->contextid != $tocontextid) {
$tocontext = get_context_instance_by_id($tocontextid);
require_capability('moodle/question:managecategory', $tocontext);
}
@@ -450,7 +431,7 @@ class question_category_object {
$cat->name = $newname;
$cat->info = $newinfo;
$cat->parent = $parentid;
// We don't change $cat->contextid here, if necessary we redirect to contextmove.php later.
$cat->contextid = $tocontextid;
$DB->update_record('question_categories', $cat);
// If the category name has changed, rename any random questions in that category.
@@ -464,41 +445,11 @@ class question_category_object {
$DB->set_field_select('question', 'name', $randomqname, $where, array($cat->id, '1'));
}
// Then redirect to an appropriate place.
if ($oldcat->contextid == $tocontextid) { // not moving contexts
redirect($this->pageurl);
} else {
$url = new moodle_url('/question/contextmove.php', ($this->pageurl->params() + array('cattomove' => $updateid, 'toparent'=>$newparent)));
redirect($url);
if ($oldcat->contextid != $tocontextid) {
// Moving to a new context. Must move files belonging to questions.
question_move_category_to_context($cat->id, $oldcat->contextid, $tocontextid);
}
redirect($this->pageurl);
}
public function move_question_from_cat_confirm($fromcat, $fromcourse, $tocat=null, $question=null){
global $QTYPES, $DB;
if (!$question){
$questions[] = $question;
} else {
$questions = $DB->get_records('question', array('category' => $tocat->id));
}
$urls = array();
foreach ($questions as $question){
$urls = array_merge($urls, $QTYPES[$question->qtype]->find_file_links_in_question($question));
}
if ($fromcourse){
$append = 'tocourse';
} else {
$append = 'tosite';
}
if ($tocat){
echo '<p>'.get_string('needtomovethesefilesincat','question').'</p>';
} else {
echo '<p>'.get_string('needtomovethesefilesinquestion','question').'</p>';
}
}
}
-219
View File
@@ -1,219 +0,0 @@
<?php
/**
* Allows someone with appropriate permissions to move a category and associated
* files to another context.
*
* @author Jamie Pratt
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package questionbank
*/
require_once("../config.php");
require_once($CFG->dirroot."/question/editlib.php");
require_once($CFG->dirroot."/question/contextmove_form.php");
//TODO: MDL-16094
throw new coding_exception('contextmove.php was not converted to new file api yet, sorry - see MDL-16094');
list($thispageurl, $contexts, $cmid, $cm, $module, $pagevars) =
question_edit_setup('categories', '/question/contextmove.php');
// get values from form for actions on this page
$toparent = required_param('toparent', PARAM_SEQUENCE);
$cattomove = required_param('cattomove', PARAM_INT);
$totop = optional_param('totop', 0, PARAM_INT); // optional param moves category to top of peers. Default is
//to add it to the bottom.
$onerrorurl = new moodle_url('/question/category.php', $thispageurl->params());
list($toparent, $contextto) = explode(',', $toparent);
if (!empty($toparent)){//not top level category, make it a child of $toparent
if (!$toparent = $DB->get_record('question_categories', array('id' => $toparent))){
print_error('invalidcategoryidforparent', 'question', $onerrorurl);
}
$contextto = $toparent->contextid;
} else {
$toparent = new stdClass();
$toparent->id = 0;
$toparent->contextid = $contextto;
}
if (!$cattomove = $DB->get_record('question_categories', array('id' => $cattomove))){
print_error('invalidcategoryidtomove', 'question', $onerrorurl);
}
if ($cattomove->contextid == $contextto){
print_error('contexterror', '', $onerrorurl);
}
$cattomove->categorylist = question_categorylist($cattomove->id);
$thispageurl->params(array('cattomove'=>$cattomove->id,
'toparent'=>"{$toparent->id},{$toparent->contextid}",
'totop'=>$totop));
$contextfrom = get_context_instance_by_id($cattomove->contextid);
$contextto = get_context_instance_by_id($contextto);
$contexttostring = print_context_name($contextto);
require_capability('moodle/question:managecategory', $contextfrom);
require_capability('moodle/question:managecategory', $contextto);
$fromcoursefilesid = get_filesdir_from_context($contextfrom);//siteid or courseid
$tocoursefilesid = get_filesdir_from_context($contextto);//siteid or courseid
if ($fromcoursefilesid != $tocoursefilesid){
list($usql, $params) = $DB->get_in_or_equal(explode(',', $cattomove->categorylist));
$questions = $DB->get_records_select('question', "category $usql", $params);
$urls = array();
if ($questions){
foreach ($questions as $id => $question){
$QTYPES[$questions[$id]->qtype]->get_question_options($questions[$id]);
$urls = array_merge_recursive($urls, $QTYPES[$questions[$id]->qtype]->find_file_links($questions[$id], $fromcoursefilesid));
}
}
ksort($urls);
} else {
$urls = array();
}
$brokenurls = array();
foreach (array_keys($urls) as $url){
if (!file_exists($CFG->dataroot."/$fromcoursefilesid/".$url)){
$brokenurls[] = $url;
}
}
if ($fromcoursefilesid == SITEID){
$fromareaname = get_string('filesareasite', 'question');
} else {
$fromareaname = get_string('filesareacourse', 'question');
}
if ($tocoursefilesid == SITEID){
$toareaname = get_string('filesareasite', 'question');
} else {
$toareaname = get_string('filesareacourse', 'question');
}
$contextmoveform = new question_context_move_form($thispageurl,
compact('urls', 'fromareaname', 'toareaname', 'brokenurls',
'fromcoursefilesid', 'tocoursefilesid'));
if ($contextmoveform->is_cancelled()){
$thispageurl->remove_params('cattomove', 'toparent', 'totop');
redirect(new moodle_url("/question/category.php".$thispageurl->params()));
}elseif ($moveformdata = $contextmoveform->get_data()) {
if (isset($moveformdata->urls) && is_array($moveformdata->urls)){
check_dir_exists($CFG->dataroot."/$tocoursefilesid/", true);
$flipurls = array_keys($urls);
foreach ($moveformdata->urls as $key => $urlaction){
$source = $CFG->dataroot."/$fromcoursefilesid/".$flipurls[$key];
$destination = $flipurls[$key];
if (($urlaction != QUESTION_FILEDONOTHING) && ($urlaction != QUESTION_FILEMOVELINKSONLY)){
// Ensure the target folder exists.
check_dir_exists(dirname($CFG->dataroot."/$tocoursefilesid/".$destination), true);
// Then make sure the destination file name does not exist. If it does, change the name to be unique.
while (file_exists($CFG->dataroot."/$tocoursefilesid/".$destination)){
$matches = array();
//check for '_'. copyno after filename, before extension.
if (preg_match('!\_([0-9]+)(\.[^\.\\/]+)?$!', $destination, $matches)){
$copyno = $matches[1]+1;
} else {
$copyno = 1;
}
//replace old copy no with incremented one.
$destination = preg_replace('!(\_[0-9]+)?(\.[^\.\\/]+)?$!', '_'.$copyno.'\\2', $destination, 1);
}
}
switch ($urlaction){
case QUESTION_FILECOPY :
if (!copy($source, $CFG->dataroot."/$tocoursefilesid/".$destination)){
print_error('errorfilecannotbecopied', 'question', $onerrorurl, $source);
}
break;
case QUESTION_FILEMOVE :
if (!rename($source, $CFG->dataroot."/$tocoursefilesid/".$destination)){
print_error('errorfilecannotbemoved', 'question', $onerrorurl, $source);
}
break;
case QUESTION_FILEDONOTHING :
case QUESTION_FILEMOVELINKSONLY :
break;
default :
print_error('invalidaction', '', $onerrorurl);
}
switch ($urlaction){
//now search and replace urls in questions.
case QUESTION_FILECOPY :
case QUESTION_FILEMOVE :
case QUESTION_FILEMOVELINKSONLY :
$url = $flipurls[$key];
$questionids = array_unique($urls[$url]);
foreach ($questionids as $questionid){
$question = $questions[$questionid];
$QTYPES[$question->qtype]->replace_file_links($question, $fromcoursefilesid, $tocoursefilesid, $url, $destination);
}
break;
case QUESTION_FILEDONOTHING :
default :
break;
}
}
}
//adjust sortorder before we make the cat a peer of it's new peers
$peers = $DB->get_records_select_menu('question_categories',
'contextid = ? AND parent = ?', array($toparent->contextid, $toparent->id),
'sortorder ASC', 'id, 1');
$peers = array_keys($peers);
if ($totop){
array_unshift($peers, $cattomove->id);
} else {
$peers[] = $cattomove->id;
}
$sortorder = 0;
foreach ($peers as $peer) {
$DB->set_field('question_categories', "sortorder", $sortorder, array("id" => $peer));
$sortorder++;
}
//now move category
$cat = new stdClass();
$cat->id = $cattomove->id;
$cat->parent = $toparent->id;
//set context of category we are moving and all children also!
list($usql, $params) = $DB->get_in_or_equal(explode(',', $cattomove->categorylist));
$params = array_merge(array($contextto->id), $params);
$DB->execute("UPDATE {question_categories} SET contextid = ? WHERE id $usql", $params);
//finally set the new parent id
$DB->update_record("question_categories", $cat);
$thispageurl->remove_params('cattomove', 'toparent', 'totop');
$url = new moodle_url('/question/category.php', ($thispageurl->params() + array('cat'=>"{$cattomove->id},{$contextto->id}")));
redirect($url);
}
$streditingcategories = get_string('editcategories', 'quiz');
$PAGE->set_url($thispageurl->out());
$PAGE->navbar->add($streditingcategories, $thispageurl->out());
$PAGE->navbar->add(get_string('movingcategory', 'question'));
$PAGE->set_heading($COURSE->fullname);
echo $OUTPUT->header();
//parameter for get_string
$cattomove->contextto = $contexttostring;
if (count($urls)){
$defaults = array();
for ($default_key = 0; $default_key < count($urls); $default_key++){
$defaults['urls'][$default_key] = QUESTION_FILECOPY;
}
$contextmoveform->set_data($defaults);
//some parameters for get_string
$cattomove->urlcount = count($urls);
$cattomove->toareaname = $toareaname;
$cattomove->fromareaname = $fromareaname;
echo $OUTPUT->box(get_string('movingcategoryandfiles', 'question', $cattomove), 'boxwidthnarrow boxaligncenter generalbox');
} else {
echo $OUTPUT->box(get_string('movingcategorynofiles', 'question', $cattomove), 'boxwidthnarrow boxaligncenter generalbox');
}
$contextmoveform->display();
echo $OUTPUT->footer();
-107
View File
@@ -1,107 +0,0 @@
<?php
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->libdir.'/formslib.php');
class question_context_move_form extends moodleform {
function definition() {
global $CFG, $OUTPUT;
$mform =& $this->_form;
//--------------------------------------------------------------------------------
$urls = $this->_customdata['urls'];
$fromareaname = $this->_customdata['fromareaname'];
$toareaname = $this->_customdata['toareaname'];
$fileoptions = array(QUESTION_FILEDONOTHING=>get_string('donothing', 'question'),
QUESTION_FILECOPY=>get_string('copy', 'question', $fromareaname),
QUESTION_FILEMOVE=>get_string('move', 'question', $fromareaname),
QUESTION_FILEMOVELINKSONLY=>get_string('movelinksonly', 'question', $fromareaname));
$brokenfileoptions = array(QUESTION_FILEDONOTHING=>get_string('donothing', 'question'),
QUESTION_FILEMOVELINKSONLY=>get_string('movelinksonly', 'question', $fromareaname));
$brokenurls = $this->_customdata['brokenurls'];
if (count($urls)){
$mform->addElement('header','general', get_string('filestomove', 'question', $toareaname));
$i = 0;
foreach (array_keys($urls) as $url){
$icontype = mimeinfo('type', $url);
$img = "<img src=\"" . $OUTPUT->pix_url(file_extension_icon($url)) . "\" class=\"icon\" alt=\"$icontype\" />";
if (in_array($url, $brokenurls)){
$mform->addElement('select', "urls[$i]", $img.$url, $brokenfileoptions);
} else {
$mform->addElement('select', "urls[$i]", $img.$url, $fileoptions);
}
$i++;
}
}
if (count($brokenurls)){
$mform->addElement('advcheckbox','ignorebroken', get_string('ignorebroken', 'question'));
}
//--------------------------------------------------------------------------------
$this->add_action_buttons(true, get_string('movecategory', 'question'));
}
function validation($data, $files) {
$errors = parent::validation($data, $files);
$tocoursefilesid = $this->_customdata['tocoursefilesid'];
$fromcoursefilesid = $this->_customdata['fromcoursefilesid'];
if (isset($data['urls']) && (count($data['urls']))){
foreach ($data['urls'] as $key => $urlaction){
switch ($urlaction){
case QUESTION_FILEMOVE :
if (!has_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $fromcoursefilesid))){
$errors["urls[$key]"] = get_string('filecantmovefrom', 'question');
}
//no break; COPY check is also applied to MOVE action
case QUESTION_FILECOPY :
if (!has_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $tocoursefilesid))){
$errors["urls[$key]"] = get_string('filecantmoveto', 'question');
}
break;
case QUESTION_FILEMOVELINKSONLY :
case QUESTION_FILEDONOTHING :
break;
}
}
}
//check that there hasn't been any changes in files between time form was displayed
//and now when it has been submitted.
if (isset($data['urls']) &&
(count($data['urls'])
!= count($this->_customdata['urls']))){
$errors['urls[0]'] = get_string('errorfileschanged', 'question');
}
return $errors;
}
/*
* We want these errors to show up on first loading the form which is not the default for
* validation method which is not run until submission.
*/
function definition_after_data(){
$mform = $this->_form;
$brokenurls = $this->_customdata['brokenurls'];
if (count($brokenurls)){
$ignoreval = $mform->getElementValue('ignorebroken');
if (!$ignoreval){
$urls = $this->_customdata['urls'];
$i = 0;
foreach (array_keys($urls) as $url){
if (in_array($url, $brokenurls)){
$mform->setElementError("urls[$i]", get_string('broken', 'question'));
} else {
$mform->setElementError("urls[$i]", '');
}
$i++;
}
}
}
}
}
-224
View File
@@ -1,224 +0,0 @@
<?php
/**
* Page for moving questions
*
* @author [email protected]
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package questionbank
*/
// Includes.
require_once(dirname(__FILE__) . '/../config.php');
require_once(dirname(__FILE__) . '/editlib.php');
require_once($CFG->dirroot.'/question/contextmoveq_form.php');
//TODO: MDL-16094
throw new coding_exception('contextmoveq.php was not converted to new file api yet, sorry - see MDL-16094');
$ids = required_param('ids', PARAM_SEQUENCE); // question ids
if (!$cmid = optional_param('cmid', 0, PARAM_INT)){
$courseid = required_param('courseid', PARAM_INT);
}
$tocatid = required_param('tocatid', PARAM_INT);
$returnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
$thispageurl = new moodle_url('/question/contextmoveq.php');
$thispageurl->params(compact('tocatid', 'ids', 'returnurl'));
if ($cmid){
list($module, $cm) = get_module_from_cmid($cmid);
require_login($cm->course, false, $cm);
$thiscontext = get_context_instance(CONTEXT_MODULE, $cmid);
if (!$returnurl) {
$returnurl = "{$CFG->wwwroot}/question/edit.php?cmid={$cm->id}";
}
$thispageurl->param('cmid', $cmid);
} elseif ($courseid) {
require_login($courseid, false);
$thiscontext = get_context_instance(CONTEXT_COURSE, $courseid);
$module = null;
$cm = null;
if (!$returnurl) {
$returnurl = "{$CFG->wwwroot}/question/edit.php?courseid={$COURSE->id}";
}
$thispageurl->param('courseid', $COURSE->id);
} else {
print_error('missingcourseorcmid', 'question');
}
$contexts = new question_edit_contexts($thiscontext);
list($usql, $params) = $DB->get_in_or_equal(explode(',', $ids));
if (!$questions = $DB->get_records_sql("SELECT q.*, c.contextid FROM {question} q, {question_categories} c WHERE q.id $usql AND c.id = q.category", $params)) {
print_error('questiondoesnotexist', 'question', $returnurl);
}
if (!$tocat = $DB->get_record('question_categories', array('id' => $tocatid))){
print_error('categorydoesnotexist', 'question', $returnurl);
}
$tocat->context = get_context_instance_by_id($tocat->contextid);
require_capability('moodle/question:add', $tocat->context);
$tocoursefilesid = get_filesdir_from_context($tocat->context);
$urls = array();
if ($tocoursefilesid == SITEID){
$toareaname = get_string('filesareasite', 'question');
} else {
$toareaname = get_string('filesareacourse', 'question');
}
$fromcoursefilesid = 0;
foreach (array_keys($questions) as $id){
question_require_capability_on($questions[$id], 'move');
get_question_options($questions[$id]);
$questions[$id]->context = get_context_instance_by_id($questions[$id]->contextid);
$thisfilesid = get_filesdir_from_context($questions[$id]->context);
if ($fromcoursefilesid && $thisfilesid != $fromcoursefilesid){
print_error('cannotmovequestion', 'question');
} else {
$fromcoursefilesid = $thisfilesid;
}
if ($tocoursefilesid != $fromcoursefilesid){
$urls = array_merge_recursive($urls, $QTYPES[$questions[$id]->qtype]->find_file_links($questions[$id], $fromcoursefilesid));
}
}
$brokenurls = array();
foreach (array_keys($urls) as $url){
if (!file_exists($CFG->dataroot."/$fromcoursefilesid/".$url)){
$brokenurls[] = $url;
}
}
if ($fromcoursefilesid == SITEID){
$fromareaname = get_string('filesareasite', 'question');
} else {
$fromareaname = get_string('filesareacourse', 'question');
}
$contextmoveform = new question_context_move_question_form($thispageurl,
compact('urls', 'fromareaname', 'toareaname', 'brokenurls',
'fromcoursefilesid', 'tocoursefilesid'));
if ($contextmoveform->is_cancelled()){
redirect($returnurl);
}elseif ($moveformdata = $contextmoveform->get_data()) {
if (isset($moveformdata->urls) && is_array($moveformdata->urls)){
check_dir_exists($CFG->dataroot."/$tocoursefilesid/", true);
$flipurls = array_keys($urls);
//actions on files
foreach ($moveformdata->urls as $key => $urlaction){
$source = $CFG->dataroot."/$fromcoursefilesid/".$flipurls[$key];
$destination = $flipurls[$key];
if (($urlaction != QUESTION_FILEDONOTHING) && ($urlaction != QUESTION_FILEMOVELINKSONLY)){
// Ensure the target folder exists.
check_dir_exists(dirname($CFG->dataroot."/$tocoursefilesid/".$destination), true);
// Then make sure the destination file name does not exist. If it does, change the name to be unique.
while (file_exists($CFG->dataroot."/$tocoursefilesid/".$destination)){
$matches = array();
//check for '_'. copyno after filename, before extension.
if (preg_match('!\_([0-9]+)(\.[^\.\\/]+)?$!', $destination, $matches)){
$copyno = $matches[1]+1;
} else {
$copyno = 1;
}
//replace old copy no with incremented one.
$destination = preg_replace('!(\_[0-9]+)?(\.[^\.\\/]+)?$!', '_'.$copyno.'\\2', $destination, 1);
}
}
switch ($urlaction){
case QUESTION_FILECOPY :
if (!copy($source, $CFG->dataroot."/$tocoursefilesid/".$destination)){
print_error('errorfilecannotbecopied', 'question', $returnurl, $source);
}
break;
case QUESTION_FILEMOVE :
if (!rename($source, $CFG->dataroot."/$tocoursefilesid/".$destination)){
print_error('errorfilecannotbemoved', 'question', $returnurl, $source);
}
break;
case QUESTION_FILEMOVELINKSONLY :
case QUESTION_FILEDONOTHING :
break;
default :
print_error('invalidaction', '', $returnurl);
}
//now search and replace urls in questions.
switch ($urlaction){
case QUESTION_FILECOPY :
case QUESTION_FILEMOVE :
case QUESTION_FILEMOVELINKSONLY :
$url = $flipurls[$key];
$questionswithlinks = array_unique($urls[$url]);
foreach ($questionswithlinks as $questionid){
$QTYPES[$questions[$questionid]->qtype]->replace_file_links($questions[$questionid], $fromcoursefilesid, $tocoursefilesid, $url, $destination);
}
break;
case QUESTION_FILEDONOTHING :
break;
default :
print_error('invalidaction', '', $returnurl);
break;
}
}
}
/// Now move questions.
if (!question_move_questions_to_category($ids, $tocat->id)) {
print_error('errormovingquestions', 'question', $returnurl, $ids);
}
if ($returnurl) {
$returnurl = new moodle_url('/' . $returnurl);
}
redirect($returnurl);
}
$streditingcategories = get_string('editcategories', 'quiz');
$strmovingquestions = get_string('movingquestions', 'question');
$PAGE->set_url($thispageurl->out());
$PAGE->navbar->add($strmovingquestions);
$PAGE->set_title($strmovingquestions);
$PAGE->set_heading($COURSE->fullname);
echo $OUTPUT->header();
//parameter for get_string
$questionsstr = new stdClass();
$questionsstr->tocontext = print_context_name($tocat->context);
$questionsstr->fromareaname = $fromareaname;
//comma seperated string "'xx', 'cx', 'sdf' and 'fgdhfg'"
$questionnamestojoin = array();
foreach ($questions as $question){
$questionnamestojoin[] = $question->name;
}
$tojoincount = count($questionnamestojoin);
if ($tojoincount > 1){
$a = new stdClass();
$a->one = $questionnamestojoin[$tojoincount -2].'"</strong>';
$a->two = '<strong>"'.$questionnamestojoin[$tojoincount -1];
$questionnamestojoin[$tojoincount -2] = get_string('and', '', $a);
unset($questionnamestojoin[$tojoincount -1]);
}
$questionsstr->questions = '<strong>"'.join($questionnamestojoin, '"</strong>, <strong>"').'"</strong>';
if (count($urls)){
$defaults = array();
for ($default_key = 0; $default_key < count($urls); $default_key++){
$defaults['urls'][$default_key] = QUESTION_FILECOPY;
}
$contextmoveform->set_data($defaults);
//some parameters for get_string
$questionsstr->urlcount = count($urls);
$questionsstr->toareaname = $toareaname;
echo $OUTPUT->box(get_string('movingquestionsandfiles', 'question', $questionsstr), 'boxwidthnarrow boxaligncenter generalbox');
} else {
echo $OUTPUT->box(get_string('movingquestionsnofiles', 'question', $questionsstr), 'boxwidthnarrow boxaligncenter generalbox');
}
$contextmoveform->display();
echo $OUTPUT->footer();
-111
View File
@@ -1,111 +0,0 @@
<?php
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->libdir.'/formslib.php');
class question_context_move_question_form extends moodleform {
function definition() {
global $CFG, $OUTPUT;
$mform =& $this->_form;
//--------------------------------------------------------------------------------
$urls = $this->_customdata['urls'];
$fromareaname = $this->_customdata['fromareaname'];
$toareaname = $this->_customdata['toareaname'];
$fileoptions = array(QUESTION_FILEDONOTHING=>get_string('donothing', 'question'),
QUESTION_FILECOPY=>get_string('copy', 'question', $fromareaname),
QUESTION_FILEMOVE=>get_string('move', 'question', $fromareaname),
QUESTION_FILEMOVELINKSONLY=>get_string('movelinksonly', 'question', $fromareaname));
$brokenfileoptions = array(QUESTION_FILEDONOTHING=>get_string('donothing', 'question'),
QUESTION_FILEMOVELINKSONLY=>get_string('movelinksonly', 'question', $fromareaname));
$brokenurls = $this->_customdata['brokenurls'];
if (count($urls)){
$mform->addElement('header','general', get_string('filestomove', 'question', $toareaname));
$i = 0;
foreach (array_keys($urls) as $url){
$icontype = mimeinfo('type', $url);
$img = "<img src=\"" . $OUTPUT->pix_url(file_extension_icon($url)) . "\" class=\"icon\" alt=\"$icontype\" />";
if (in_array($url, $brokenurls)){
$mform->addElement('select', "urls[$i]", $img.$url, $brokenfileoptions);
} else {
$mform->addElement('select', "urls[$i]", $img.$url, $fileoptions);
}
$i++;
}
}
if (count($brokenurls)){
$mform->addElement('advcheckbox','ignorebroken', get_string('ignorebroken', 'question'));
}
//--------------------------------------------------------------------------------
$this->add_action_buttons(true, get_string('moveq', 'question'));
}
function validation($data, $files) {
$errors = parent::validation($data, $files);
$tocoursefilesid = $this->_customdata['tocoursefilesid'];
$fromcoursefilesid = $this->_customdata['fromcoursefilesid'];
if (isset($data['urls']) && (count($data['urls']))){
foreach ($data['urls'] as $key => $urlaction){
switch ($urlaction){
case QUESTION_FILEMOVE :
if (!has_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $fromcoursefilesid))){
$errors["urls[$key]"] = get_string('filecantmovefrom', 'question');
}
case QUESTION_FILECOPY :
if (!has_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $tocoursefilesid))){
$errors["urls[$key]"] = get_string('filecantmoveto', 'question');
}
break;
case QUESTION_FILEMOVELINKSONLY :
case QUESTION_FILEDONOTHING :
break;
}
}
}
//check that there hasn't been any changes in files between time form was displayed
//and now when it has been submitted.
if (isset($data['urls']) &&
(count($data['urls'])
!= count($this->_customdata['urls']))){
$errors['urls[0]'] = get_string('errorfileschanged', 'question');
}
return $errors;
}
/*
* We want these errors to show up on first loading the form which is not the default for
* validation method which is not run until submission.
*/
function definition_after_data(){
static $done = false;
if (!$done){
$mform = $this->_form;
$brokenurls = $this->_customdata['brokenurls'];
if (count($brokenurls)){
$ignoreval = $mform->getElementValue('ignorebroken');
if (!$ignoreval){
$urls = $this->_customdata['urls'];
$i = 0;
foreach (array_keys($urls) as $url){
if (in_array($url, $brokenurls)){
$mform->setElementError("urls[$i]", get_string('broken', 'question'));
} else {
$mform->setElementError("urls[$i]", '');
}
$i++;
}
}
}
$done = true;
}
}
}
+11 -30
View File
@@ -1385,7 +1385,8 @@ class question_bank_view {
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
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))) {
@@ -1403,38 +1404,18 @@ class question_bank_view {
}
if ($questionids) {
list($usql, $params) = $DB->get_in_or_equal($questionids);
$sql = "SELECT q.*, c.contextid FROM {question} q, {question_categories} c WHERE q.id $usql AND c.id = q.category";
if (!$questions = $DB->get_records_sql($sql, $params)){
print_error('questiondoesnotexist', 'question', $pageurl->out());
}
$checkforfiles = false;
$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){
//check capabilities
question_require_capability_on($question, 'move');
$fromcontext = get_context_instance_by_id($question->contextid);
if (get_filesdir_from_context($fromcontext) != get_filesdir_from_context($tocontext)){
$checkforfiles = true;
}
}
$returnurl = $this->baseurl->out(false, array('category' => "$tocategoryid,$contextid"));
if (!$checkforfiles){
if (!question_move_questions_to_category(implode(',', $questionids), $tocategory->id)) {
print_error('errormovingquestions', 'question', $returnurl, $questionids);
}
redirect($returnurl);
} else {
$returnurl = str_replace($CFG->wwwroot . '/', '', $returnurl);
$movecontexturl = new moodle_url('/question/contextmoveq.php',
array('returnurl' => $returnurl,
'ids' => implode(',', $questionids),
'tocatid' => $tocategoryid));
if (!empty($cm->id)){
$movecontexturl->param('cmid', $cm->id);
} else {
$movecontexturl->param('courseid', $this->course->id);
}
redirect($movecontexturl);
}
question_move_questions_to_category($questionids, $tocategory->id);
redirect($this->baseurl->out(false,
array('category' => "$tocategoryid,$contextid")));
}
}
+18 -26
View File
@@ -211,7 +211,7 @@ if ($mform->is_cancelled()){
}
redirect($returnurl->out(false));
}
} elseif ($fromform = $mform->get_data()) {
} else if ($fromform = $mform->get_data()) {
/// If we are saving as a copy, break the connection to the old question.
if (!empty($fromform->makecopy)) {
$question->id = 0;
@@ -237,36 +237,27 @@ if ($mform->is_cancelled()){
question_require_capability_on($question, 'move');
}
/// Ensure we redirect back to the category the question is being saved into.
// Ensure we redirect back to the category the question is being saved into.
$returnurl->param('category', $fromform->category);
/// Call the appropriate method.
if ($movecontext) {
// We are just moving the question to a different context.
list($tocatid, $tocontextid) = explode(',', $fromform->categorymoveto);
$tocontext = get_context_instance_by_id($tocontextid);
require_capability('moodle/question:add', $tocontext);
if (get_filesdir_from_context($categorycontext) != get_filesdir_from_context($tocontext)){
$movecontexturl = new moodle_url('/question/contextmoveq.php', array(
'returnurl' => str_replace($CFG->wwwroot, '', $returnurl->out(false)),
'ids' => $question->id,
'tocatid' => $tocatid));
if ($cmid){
$movecontexturl->param('cmid', $cmid);
} else {
$movecontexturl->param('courseid', $courseid);
}
redirect($movecontexturl);
require_capability('moodle/question:add', get_context_instance_by_id($tocontextid));
question_move_questions_to_category(array($question->id), $tocatid);
} else {
// We are acutally saving the question.
$question = $QTYPES[$question->qtype]->save_question($question, $fromform, $COURSE, $wizardnow, true);
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);
}
}
$question = $QTYPES[$question->qtype]->save_question($question, $fromform, $COURSE, $wizardnow, true);
// a wizardpage from multipe pages questiontype like calculated may not allow editing the question tags
if (!empty($CFG->usetags) && isset($fromform->tags)) {
require_once($CFG->dirroot.'/tag/lib.php');
tag_set('question', $question->id, $fromform->tags);
}
if (($QTYPES[$question->qtype]->finished_edit_wizard($fromform)) || $movecontext){
if (($QTYPES[$question->qtype]->finished_edit_wizard($fromform)) || $movecontext) {
if ($inpopup) {
echo $OUTPUT->notification(get_string('changessaved'), '');
close_window(3);
@@ -279,6 +270,7 @@ if ($mform->is_cancelled()){
}
redirect($returnurl);
}
} else {
$nexturlparams = array(
'returnurl' => $originalreturnurl,
@@ -297,8 +289,8 @@ if ($mform->is_cancelled()){
}
redirect($nexturl);
}
} else {
} else {
$streditingquestion = $QTYPES[$question->qtype]->get_heading();
$PAGE->set_title($streditingquestion);
$PAGE->set_heading($COURSE->fullname);
@@ -316,7 +308,7 @@ if ($mform->is_cancelled()){
} else {
$strediting = '<a href="edit.php?courseid='.$COURSE->id.'">'.get_string("editquestions", "quiz").'</a> -> '.$streditingquestion;
$PAGE->navbar->add(get_string('editquestions', "quiz"), $returnurl);
$PAGE->navbar->add(get_string('editquestions', 'quiz'), $returnurl);
$PAGE->navbar->add($streditingquestion);
echo $OUTPUT->header();
}
+7 -37
View File
@@ -2108,44 +2108,14 @@ class question_calculated_qtype extends default_questiontype {
return $new_question;
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
parent::move_files($question, $newcategory);
function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
$component = 'qtype_numerical';
$filearea = 'instruction';
$files = $fs->get_area_files($question->contextid, $component, $filearea, $question->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_numerical', 'instruction', $questionid);
}
function check_file_access($question, $state, $options, $contextid, $component,
+10 -40
View File
@@ -548,48 +548,18 @@ class question_calculatedmulti_qtype extends question_calculated_qtype {
return $new_question;
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
// move files belonging to question component
parent::move_files($question, $newcategory);
// move files belonging to qtype_calculatedmulti
function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
$component = 'qtype_calculatedmulti';
foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $filearea) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $question->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
}
function check_file_access($question, $state, $options, $contextid, $component,
@@ -341,45 +341,15 @@ class question_calculatedsimple_qtype extends question_calculated_qtype {
return $new_question;
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
parent::move_files($question, $newcategory);
function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'feedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
$component = 'qtype_calculatedsimple';
$filearea = 'feedback';
$filearea = 'instruction';
$files = $fs->get_area_files($question->contextid, $component, $filearea, $question->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_calculatedsimple', 'instruction', $questionid);
}
function check_file_access($question, $state, $options, $contextid, $component,
+14 -20
View File
@@ -46,7 +46,6 @@ class question_edit_form extends moodleform {
public $contexts;
public $category;
public $categorycontext;
public $coursefilesid;
/** @var object current context */
public $context;
@@ -64,25 +63,20 @@ class question_edit_form extends moodleform {
$this->contexts = $contexts;
$record = $DB->get_record('question_categories', array('id'=>$question->category), 'contextid');
$record = $DB->get_record('question_categories', array('id' => $question->category), 'contextid');
$this->context = get_context_instance_by_id($record->contextid);
$this->editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'context'=>$this->context);
$this->fileoptions = array('subdir'=>true, 'maxfiles'=>-1, 'maxbytes'=>-1);
$this->editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'context' => $this->context);
$this->fileoptions = array('subdir' => true, 'maxfiles' => -1, 'maxbytes' => -1);
$this->category = $category;
$this->categorycontext = get_context_instance_by_id($category->contextid);
//** *
//course id or site id depending on question cat context
$this->coursefilesid = get_filesdir_from_context(get_context_instance_by_id($category->contextid));
if (!empty($question->id)) {
$question->id = (int)$question->id;
//$this->instance = new
$question->id = (int) $question->id;
}
parent::moodleform($submiturl, null, 'post', '', null, $formeditable);
}
/**
@@ -104,20 +98,20 @@ class question_edit_form extends moodleform {
$mform->addElement('header', 'generalheader', get_string("general", 'form'));
if (!isset($this->question->id)){
//adding question
// Adding question
$mform->addElement('questioncategory', 'category', get_string('category', 'quiz'),
array('contexts' => $this->contexts->having_cap('moodle/question:add')));
} elseif (!($this->question->formoptions->canmove || $this->question->formoptions->cansaveasnew)){
//editing question with no permission to move from category.
// Editing question with no permission to move from category.
$mform->addElement('questioncategory', 'category', get_string('category', 'quiz'),
array('contexts' => array($this->categorycontext)));
} elseif ($this->question->formoptions->movecontext){
//moving question to another context.
// Moving question to another context.
$mform->addElement('questioncategory', 'categorymoveto', get_string('category', 'quiz'),
array('contexts' => $this->contexts->having_cap('moodle/question:add')));
} else {
//editing question with permission to move from category or save as new q
// Editing question with permission to move from category or save as new q
$currentgrp = array();
$currentgrp[0] =& $mform->createElement('questioncategory', 'category', get_string('categorycurrent', 'question'),
array('contexts' => array($this->categorycontext)));
@@ -143,7 +137,7 @@ class question_edit_form extends moodleform {
$mform->addRule('name', null, 'required', null, 'client');
$mform->addElement('editor', 'questiontext', get_string('questiontext', 'quiz'),
array('rows' => 15, 'course' => $this->coursefilesid), $this->editoroptions);
array('rows' => 15), $this->editoroptions);
$mform->setType('questiontext', PARAM_RAW);
$mform->addElement('text', 'defaultgrade', get_string('defaultgrade', 'quiz'),
@@ -160,7 +154,7 @@ class question_edit_form extends moodleform {
$mform->setDefault('penalty', 0.1);
$mform->addElement('editor', 'generalfeedback', get_string('generalfeedback', 'quiz'),
array('rows' => 10, 'course' => $this->coursefilesid), $this->editoroptions);
array('rows' => 10), $this->editoroptions);
$mform->setType('generalfeedback', PARAM_RAW);
$mform->addHelpButton('generalfeedback', 'generalfeedback', 'quiz');
@@ -243,15 +237,15 @@ class question_edit_form extends moodleform {
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
$mform->closeHeaderBefore('buttonar');
if ($this->question->formoptions->movecontext){
if ($this->question->formoptions->movecontext) {
$mform->hardFreezeAllVisibleExcept(array('categorymoveto', 'buttonar'));
} elseif ((!empty($this->question->id)) && (!($this->question->formoptions->canedit || $this->question->formoptions->cansaveasnew))){
} else if ((!empty($this->question->id)) && (!($this->question->formoptions->canedit || $this->question->formoptions->cansaveasnew))){
$mform->hardFreezeAllVisibleExcept(array('categorymoveto', 'buttonar', 'currentgrp'));
}
}
function validation($fromform, $files) {
$errors= parent::validation($fromform, $files);
$errors = parent::validation($fromform, $files);
if (empty($fromform->makecopy) && isset($this->question->id)
&& ($this->question->formoptions->canedit || $this->question->formoptions->cansaveasnew)
&& empty($fromform->usecurrentcat) && !$this->question->formoptions->canmove) {
@@ -284,7 +278,7 @@ class question_edit_form extends moodleform {
$repeated[] =& $mform->createElement('text', 'answer', get_string('answer', 'quiz'), array('size' => 80));
$repeated[] =& $mform->createElement('select', 'fraction', get_string('grade'), $gradeoptions);
$repeated[] =& $mform->createElement('editor', 'feedback', get_string('feedback', 'quiz'),
array('course' => $this->coursefilesid), $this->editoroptions);
array('rows' => 5), $this->editoroptions);
$repeatedoptions['answer']['type'] = PARAM_RAW;
$repeatedoptions['fraction']['default'] = 0;
$answersoption = 'answers';
+3 -27
View File
@@ -156,33 +156,9 @@ class question_essay_qtype extends default_questiontype {
return $this->save_question($question, $form, $course);
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
parent::move_files($question, $newcategory);
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
function move_files($questionid, $oldcontextid, $newcontextid) {
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
}
function check_file_access($question, $state, $options, $contextid, $component,
+9 -58
View File
@@ -492,39 +492,6 @@ class question_match_qtype extends default_questiontype {
return 1 / count($question->options->subquestions);
}
function find_file_links($question, $courseid){
// find links in the question_match_sub table.
$urls = array();
if (isset($question->options->subquestions)){
foreach ($question->options->subquestions as $subquestion) {
$urls += question_find_file_links_from_html($subquestion->questiontext, $courseid);
}
//set all the values of the array to the question object
if ($urls){
$urls = array_combine(array_keys($urls), array_fill(0, count($urls), array($question->id)));
}
}
$urls = array_merge_recursive($urls, parent::find_file_links($question, $courseid));
return $urls;
}
function replace_file_links($question, $fromcourseid, $tocourseid, $url, $destination){
global $DB;
parent::replace_file_links($question, $fromcourseid, $tocourseid, $url, $destination);
// replace links in the question_match_sub table.
if (isset($question->options->subquestions)){
foreach ($question->options->subquestions as $subquestion) {
$subquestionchanged = false;
$subquestion->questiontext = question_replace_file_links_in_html($subquestion->questiontext, $fromcourseid, $tocourseid, $url, $destination, $subquestionchanged);
if ($subquestionchanged){//need to update rec in db
$DB->update_record('question_match_sub', $subquestion);
}
}
}
}
/**
* Runs all the code required to set up and save an essay question for testing purposes.
* Alternate DB table prefix may be used to facilitate data deletion.
@@ -544,36 +511,20 @@ class question_match_qtype extends default_questiontype {
return $this->save_question($question, $form, $course);
}
function move_files($question, $newcategory) {
function move_files($questionid, $oldcontextid, $newcontextid) {
global $DB;
// move files belonging to question component
parent::move_files($question, $newcategory);
// move files belonging to qtype_multichoice
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
// process files in sub questions
if (!$subquestions = $DB->get_records('question_match_sub', array('question' => $question->id), 'id ASC')) {
$subquestions = array();
}
$component = 'qtype_match';
$filearea = 'subquestion';
foreach ($subquestions as $sub) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $sub->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
parent::move_files($questionid, $oldcontextid, $newcontextid);
$subquestionids = $DB->get_records_menu('question_match_sub',
array('question' => $questionid), 'id', 'id,1');
foreach ($subquestionids as $subquestionid => $notused) {
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_match', 'subquestion', $subquestionid);
}
}
function check_file_access($question, $state, $options, $contextid, $component,
$filearea, $args) {
@@ -66,7 +66,7 @@ class question_edit_multichoice_form extends question_edit_form {
foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $feedbackname) {
$mform->addElement('editor', $feedbackname, get_string($feedbackname, 'qtype_multichoice'),
array('course' => $this->coursefilesid), $this->editoroptions);
array('rows' => 10), $this->editoroptions);
$mform->setType($feedbackname, PARAM_RAW);
}
+10 -85
View File
@@ -14,10 +14,6 @@ class question_multichoice_qtype extends default_questiontype {
return 'multichoice';
}
function has_html_answers() {
return true;
}
function get_question_options(&$question) {
global $DB, $OUTPUT;
// Get additional information from database
@@ -489,48 +485,6 @@ class question_multichoice_qtype extends default_questiontype {
}
}
function find_file_links($question, $courseid){
$urls = array();
// find links in the answers table.
$urls += question_find_file_links_from_html($question->options->correctfeedback, $courseid);
$urls += question_find_file_links_from_html($question->options->partiallycorrectfeedback, $courseid);
$urls += question_find_file_links_from_html($question->options->incorrectfeedback, $courseid);
foreach ($question->options->answers as $answer) {
$urls += question_find_file_links_from_html($answer->answer, $courseid);
}
//set all the values of the array to the question id
if ($urls){
$urls = array_combine(array_keys($urls), array_fill(0, count($urls), array($question->id)));
}
$urls = array_merge_recursive($urls, parent::find_file_links($question, $courseid));
return $urls;
}
function replace_file_links($question, $fromcourseid, $tocourseid, $url, $destination){
global $DB;
parent::replace_file_links($question, $fromcourseid, $tocourseid, $url, $destination);
// replace links in the question_match_sub table.
// We need to use a separate object, because in load_question_options, $question->options->answers
// is changed from a comma-separated list of ids to an array, so calling $DB->update_record on
// $question->options stores 'Array' in that column, breaking the question.
$optionschanged = false;
$newoptions = new stdClass;
$newoptions->id = $question->options->id;
$newoptions->correctfeedback = question_replace_file_links_in_html($question->options->correctfeedback, $fromcourseid, $tocourseid, $url, $destination, $optionschanged);
$newoptions->partiallycorrectfeedback = question_replace_file_links_in_html($question->options->partiallycorrectfeedback, $fromcourseid, $tocourseid, $url, $destination, $optionschanged);
$newoptions->incorrectfeedback = question_replace_file_links_in_html($question->options->incorrectfeedback, $fromcourseid, $tocourseid, $url, $destination, $optionschanged);
if ($optionschanged){
$DB->update_record('question_multichoice', $newoptions);
}
$answerchanged = false;
foreach ($question->options->answers as $answer) {
$answer->answer = question_replace_file_links_in_html($answer->answer, $fromcourseid, $tocourseid, $url, $destination, $answerchanged);
if ($answerchanged){
$DB->update_record('question_answers', $answer);
}
}
}
/**
* Runs all the code required to set up and save an essay question for testing purposes.
* Alternate DB table prefix may be used to facilitate data deletion.
@@ -559,48 +513,19 @@ class question_multichoice_qtype extends default_questiontype {
return $this->save_question($question, $form, $course);
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
// move files belonging to question component
parent::move_files($question, $newcategory);
// move files belonging to qtype_multichoice
function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
$component = 'qtype_multichoice';
foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $filearea) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $question->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_multichoice', 'correctfeedback', $questionid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_multichoice', 'partiallycorrectfeedback', $questionid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_multichoice', 'incorrectfeedback', $questionid);
}
function check_file_access($question, $state, $options, $contextid, $component,
+18 -50
View File
@@ -754,7 +754,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
// The student did type a number, so check it with tolerances.
$this->get_tolerance_interval($answer);
return ($answer->min <= $response && $response <= $answer->max);
}else { // $question->options->unitgradingtype > 0
} else { // $question->options->unitgradingtype > 0
/* testing with unitgradingtype $question->options->unitgradingtype > 0
* if the response is at least patially true
* if the numerical value agree in the interval
@@ -1089,10 +1089,10 @@ class question_numerical_qtype extends question_shortanswer_qtype {
}
/**
* function used in function definition_inner()
* of edit_..._form.php for
* numerical, calculated, calculatedsimple
*/
* function used in function definition_inner()
* of edit_..._form.php for
* numerical, calculated, calculatedsimple
*/
function add_units_options(&$mform, &$that){
// Units are graded
$mform->addElement('header', 'unithandling', get_string('unitshandling', 'qtype_numerical'));
@@ -1113,10 +1113,9 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$mform->addGroup($multichoicedisplaygrp, 'multichoicedisplaygrp', get_string('studentunitanswer', 'qtype_numerical'),' OR ' , false);
$unitslefts = array('0' => get_string('rightexample', 'qtype_numerical'),'1' => get_string('leftexample', 'qtype_numerical'));
$mform->addElement('select', 'unitsleft', get_string('unitposition', 'qtype_numerical') , $unitslefts );
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
$mform->addElement('editor', 'instructions', get_string('instructions', 'qtype_numerical'), null, $that->editoroptions);
$showunits1grp = array();
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
@@ -1131,12 +1130,10 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$mform->disabledIf('penaltygrp', 'unitrole','eq','0');
$mform->disabledIf('penaltygrp', 'unitrole','eq','1');
$mform->disabledIf('penaltygrp', 'unitrole','eq','2');
$mform->disabledIf('unitsleft', 'unitrole','eq','0');
$mform->disabledIf('multichoicedisplay','unitrole','eq','0');
$mform->disabledIf('multichoicedisplay','unitrole','eq','1');
$mform->disabledIf('multichoicedisplay','unitrole','eq','2');
$mform->disabledIf('unitsleft', 'unitrole','eq','0');
$mform->disabledIf('multichoicedisplay','unitrole','eq','0');
$mform->disabledIf('multichoicedisplay','unitrole','eq','1');
$mform->disabledIf('multichoicedisplay','unitrole','eq','2');
}
/**
@@ -1383,44 +1380,15 @@ class question_numerical_qtype extends question_shortanswer_qtype {
return $this->save_question($question, $form, $course);
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
parent::move_files($question, $newcategory);
function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
$component = 'qtype_numerical';
$filearea = 'instruction';
$files = $fs->get_area_files($question->contextid, $component, $filearea, $question->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'qtype_numerical', 'instruction', $questionid);
}
function check_file_access($question, $state, $options, $contextid, $component,
+29 -116
View File
@@ -154,14 +154,6 @@ class default_questiontype {
return false;
}
/**
* @return whether the question_answers.answer field needs to have
* restore_decode_content_links_worker called on it.
*/
function has_html_answers() {
return false;
}
/**
* If your question type has a table that extends the question table, and
* you want the base class to automatically save, backup and restore the extra fields,
@@ -1529,93 +1521,6 @@ class default_questiontype {
return format_text($text, $textformat, $formatoptions, $cmoptions === NULL ? NULL : $cmoptions->course);
}
/*
* Find all course / site files linked from a question.
*
* Need to check for links to files in question_answers.answer and feedback
* and in question table in generalfeedback and questiontext fields. Methods
* on child classes will also check extra question specific fields.
*
* Needs to be overriden for child classes that have extra fields containing
* html.
*
* @param string html the html to search
* @param int courseid search for files for courseid course or set to siteid for
* finding site files.
* @return array of url, relative url is key and array with one item = question id as value
* relative url is relative to course/site files directory root.
*/
function find_file_links($question, $courseid){
$urls = array();
/// Questiontext and general feedback.
$urls += question_find_file_links_from_html($question->questiontext, $courseid);
$urls += question_find_file_links_from_html($question->generalfeedback, $courseid);
/// Answers, if this question uses them.
if (isset($question->options->answers)){
foreach ($question->options->answers as $answerkey => $answer){
/// URLs in the answers themselves, if appropriate.
if ($this->has_html_answers()) {
$urls += question_find_file_links_from_html($answer->answer, $courseid);
}
/// URLs in the answer feedback.
$urls += question_find_file_links_from_html($answer->feedback, $courseid);
}
}
/// Set all the values of the array to the question object
if ($urls){
$urls = array_combine(array_keys($urls), array_fill(0, count($urls), array($question->id)));
}
return $urls;
}
/*
* Find all course / site files linked from a question.
*
* Need to check for links to files in question_answers.answer and feedback
* and in question table in generalfeedback and questiontext fields. Methods
* on child classes will also check extra question specific fields.
*
* Needs to be overriden for child classes that have extra fields containing
* html.
*
* @param string html the html to search
* @param int course search for files for courseid course or set to siteid for
* finding site files.
* @return array of files, file name is key and array with one item = question id as value
*/
function replace_file_links($question, $fromcourseid, $tocourseid, $url, $destination){
global $CFG, $DB;
$updateqrec = false;
/// Questiontext and general feedback.
$question->questiontext = question_replace_file_links_in_html($question->questiontext, $fromcourseid, $tocourseid, $url, $destination, $updateqrec);
$question->generalfeedback = question_replace_file_links_in_html($question->generalfeedback, $fromcourseid, $tocourseid, $url, $destination, $updateqrec);
/// If anything has changed, update it in the database.
if ($updateqrec){
$DB->update_record('question', $question);
}
/// Answers, if this question uses them.
if (isset($question->options->answers)){
//answers that do not need updating have been unset
foreach ($question->options->answers as $answer){
$answerchanged = false;
/// URLs in the answers themselves, if appropriate.
if ($this->has_html_answers()) {
$answer->answer = question_replace_file_links_in_html($answer->answer, $fromcourseid, $tocourseid, $url, $destination, $answerchanged);
}
/// URLs in the answer feedback.
$answer->feedback = question_replace_file_links_in_html($answer->feedback, $fromcourseid, $tocourseid, $url, $destination, $answerchanged);
/// If anything has changed, update it in the database.
if ($answerchanged){
$DB->update_record('question_answers', $answer);
}
}
}
}
/**
* @return the best link to pass to print_error.
* @param $cmoptions as passed in from outside.
@@ -1755,31 +1660,39 @@ class default_questiontype {
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
* Move all the files belonging to this question from one context to another.
* @param object $question the question to move.
* @param integer $oldcontextid the context it is moving from.
* @param integer $newcontextid the context it is moving to.
*/
function move_files($question, $newcategory) {
public function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'question', 'questiontext', $questionid);
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'question', 'generalfeedback', $questionid);
}
/**
*
* @param object $question the question to move.
* @param integer $oldcontextid the context it is moving from.
* @param integer $newcontextid the context it is moving to.
* @param boolean $answerstoo whether there is an 'answer' question area,
* as well as an 'answerfeedback' one. Default false.
*/
protected function move_files_in_answers($questionid, $oldcontextid, $newcontextid, $answerstoo = false) {
global $DB;
$fs = get_file_storage();
$component = 'question';
// process general question files
// Currently we have questiontext and generalfeedback areas
foreach (array('questiontext', 'generalfeedback') as $filearea) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $question->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
if ($newcategory->contextid == $question->contextid) {
continue;
}
$newfile = new stdClass();
// only contextid changed
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
// delete old files
$storedfile->delete();
}
$answerids = $DB->get_records_menu('question_answers',
array('question' => $questionid), 'id', 'id,1');
foreach ($answerids as $answerid => $notused) {
if ($answerstoo) {
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'question', 'answer', $answerid);
}
$fs->move_area_files_to_new_context($oldcontextid,
$newcontextid, 'question', 'answerfeedback', $answerid);
}
}
+3 -27
View File
@@ -49,33 +49,9 @@ class question_shortanswer_qtype extends default_questiontype {
return 'question';
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
parent::move_files($question, $newcategory);
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
function move_files($questionid, $oldcontextid, $newcontextid) {
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
}
function save_question_options($question) {
+5 -28
View File
@@ -257,6 +257,11 @@ class question_truefalse_qtype extends default_questiontype {
include("$CFG->dirroot/question/type/truefalse/display.html");
}
function move_files($questionid, $oldcontextid, $newcontextid) {
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
}
function check_file_access($question, $state, $options, $contextid, $component,
$filearea, $args) {
if ($component == 'question' && $filearea == 'answerfeedback') {
@@ -332,34 +337,6 @@ class question_truefalse_qtype extends default_questiontype {
return $this->save_question($question, $form, $course);
}
/**
* When move the category of questions, the belonging files should be moved as well
* @param object $question, question information
* @param object $newcategory, target category information
*/
function move_files($question, $newcategory) {
global $DB;
parent::move_files($question, $newcategory);
$fs = get_file_storage();
// process files in answer
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$component = 'question';
$filearea = 'answerfeedback';
foreach ($oldanswers as $answer) {
$files = $fs->get_area_files($question->contextid, $component, $filearea, $answer->id);
foreach ($files as $storedfile) {
if (!$storedfile->is_directory()) {
$newfile = new stdClass();
$newfile->contextid = (int)$newcategory->contextid;
$fs->create_file_from_storedfile($newfile, $storedfile);
$storedfile->delete();
}
}
}
}
}
//// END OF CLASS ////