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:
+47
-169
@@ -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
@@ -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 .= ' '. $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>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ////
|
||||
|
||||
|
||||
Reference in New Issue
Block a user