MDL-19213 testing ifthe wizardpage allows editng the tags
[moodle.git] / question / question.php
1 <?php // $Id$
2 /**
3  * Page for editing questions using the new form library.
4  *
5  * @author T.J.Hunt@open.ac.uk
6  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
7  * @package questionbank
8  *//** */
10 // Includes.
11 require_once(dirname(__FILE__) . '/../config.php');
12 require_once(dirname(__FILE__) . '/editlib.php');
13 require_once($CFG->libdir . '/filelib.php');
14 require_once($CFG->libdir . '/formslib.php');
16 // Read URL parameters telling us which question to edit.
17 $id = optional_param('id', 0, PARAM_INT); // question id
18 $qtype = optional_param('qtype', '', PARAM_FILE);
19 $categoryid = optional_param('category', 0, PARAM_INT);
20 $cmid = optional_param('cmid', 0, PARAM_INT);
21 $courseid = optional_param('courseid', 0, PARAM_INT);
22 $wizardnow = optional_param('wizardnow', '', PARAM_ALPHA);
23 $movecontext = optional_param('movecontext', 0, PARAM_BOOL); // Switch to make
24         // question uneditable - form is displayed to edit category only
25 $returnurl = optional_param('returnurl', 0, PARAM_LOCALURL);
26 $appendqnumstring = optional_param('appendqnumstring', '', PARAM_ALPHA);
27 $inpopup = optional_param('inpopup', 0, PARAM_BOOL);
29 if ($movecontext && !$id){
30     print_error('questiondoesnotexist', 'question', $returnurl);
31 }
33 if ($cmid){
34     list($module, $cm) = get_module_from_cmid($cmid);
35     require_login($cm->course, false, $cm);
36     $thiscontext = get_context_instance(CONTEXT_MODULE, $cmid);
37 } elseif ($courseid) {
38     require_login($courseid, false);
39     $thiscontext = get_context_instance(CONTEXT_COURSE, $courseid);
40     $module = null;
41     $cm = null;
42 } else {
43     print_error('missingcourseorcmid', 'question');
44 }
45 $contexts = new question_edit_contexts($thiscontext);
47 if (!$returnurl) {
48     $returnurl = "{$CFG->wwwroot}/question/edit.php?courseid={$COURSE->id}";
49 }
51 if (optional_param('addcancel', false, PARAM_BOOL)) {
52     redirect($returnurl);
53 }
55 if ($id) {
56     if (!$question = $DB->get_record('question', array('id' => $id))) {
57         print_error('questiondoesnotexist', 'question', $returnurl);
58     }
59     get_question_options($question, true);
60 } else if ($categoryid && $qtype) { // only for creating new questions
61     $question = new stdClass;
62     $question->category = $categoryid;
63     $question->qtype = $qtype;
65     // Check that users are allowed to create this question type at the moment.
66     $allowedtypes = question_type_menu();
67     if (!isset($allowedtypes[$qtype])) {
68         print_error('cannotenable', 'question', $returnurl, $qtype);
69     }
70 } else {
71     print_error('notenoughdatatoeditaquestion', 'question', $returnurl);
72 }
74 // Validate the question category.
75 if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
76     print_error('categorydoesnotexist', 'question', $returnurl);
77 }
79 // Check permissions
80 $question->formoptions = new stdClass;
82 $categorycontext = get_context_instance_by_id($category->contextid);
83 $addpermission = has_capability('moodle/question:add', $categorycontext);
85 if ($id) {
86     $canview = question_has_capability_on($question, 'view');
87     if ($movecontext){
88         $question->formoptions->canedit = false;
89         $question->formoptions->canmove = (question_has_capability_on($question, 'move') && $contexts->have_cap('moodle/question:add'));
90         $question->formoptions->cansaveasnew = false;
91         $question->formoptions->repeatelements = false;
92         $question->formoptions->movecontext = true;
93         $formeditable = true;
94         question_require_capability_on($question, 'view');
95     } else {
96         $question->formoptions->canedit = question_has_capability_on($question, 'edit');
97         $question->formoptions->canmove = (question_has_capability_on($question, 'move') && $addpermission);
98         $question->formoptions->cansaveasnew = (($canview ||question_has_capability_on($question, 'edit')) && $addpermission);
99         $question->formoptions->repeatelements = ($question->formoptions->canedit || $question->formoptions->cansaveasnew);
100         $formeditable =  $question->formoptions->canedit || $question->formoptions->cansaveasnew || $question->formoptions->canmove;
101         $question->formoptions->movecontext = false;
102         if (!$formeditable){
103             question_require_capability_on($question, 'view');
104         }
105     }
107 } else  { // creating a new question
108     require_capability('moodle/question:add', $categorycontext);
109     $formeditable = true;
110     $question->formoptions->repeatelements = true;
111     $question->formoptions->movecontext = false;
114 // Validate the question type.
115 if (!isset($QTYPES[$question->qtype])) {
116     print_error('unknownquestiontype', 'question', $returnurl, $question->qtype);
118 $PAGE->set_pagetype('question-type-' . $question->qtype);
120 // Create the question editing form.
121 if ($wizardnow!=='' && !$movecontext){
122     if (!method_exists($QTYPES[$question->qtype], 'next_wizard_form')){
123         print_error('missingimportantcode', 'question', $returnurl, 'wizard form definition');
124     } else {
125         $mform = $QTYPES[$question->qtype]->next_wizard_form('question.php', $question, $wizardnow, $formeditable);
126     }
127 } else {
128     $mform = $QTYPES[$question->qtype]->create_editing_form('question.php', $question, $category, $contexts, $formeditable);
130 if ($mform === null) {
131     print_error('missingimportantcode', 'question', $returnurl, 'question editing form definition for "'.$question->qtype.'"');
133 $toform = fullclone($question); // send the question object and a few more parameters to the form
134 $toform->category = "$category->id,$category->contextid";
135 if ($formeditable && $id){
136     $toform->categorymoveto = $toform->category;
139 $toform->appendqnumstring = $appendqnumstring;
140 $toform->returnurl = $returnurl;
141 $toform->movecontext = $movecontext;
142 if ($cm !== null){
143     $toform->cmid = $cm->id;
144     $toform->courseid = $cm->course;
145 } else {
146     $toform->courseid = $COURSE->id;
148 $toform->inpopup = $inpopup;
149 $mform->set_data($toform);
151 if ($mform->is_cancelled()){
152     if ($inpopup) {
153         close_window();
154     } else {
155         redirect($returnurl);
156     }
157 } elseif ($fromform = $mform->get_data()) {
158     /// If we are saving as a copy, break the connection to the old question.
159     if (!empty($fromform->makecopy)) {
160         $question->id = 0;
161         $question->hidden = 0; // Copies should not be hidden
162     }
164     /// Process the combination of usecurrentcat, categorymoveto and category form
165     /// fields, so the save_question method only has to consider $fromform->category
166     if (!empty($fromform->usecurrentcat)) {
167         // $fromform->category is the right category to save in.
168     } else {
169         if (!empty($fromform->categorymoveto)) {
170             $fromform->category = $fromform->categorymoveto;
171         } else {
172             // $fromform->category is the right category to save in.
173         }
174     }
176     /// If we are moving a question, check we have permission to move it from
177     /// whence it came. (Where we are moving to is validated by the form.)
178     list($newcatid) = explode(',', $fromform->category);
179     if (!empty($question->id) && $newcatid != $question->category) {
180         question_require_capability_on($question, 'move');
181     }
183     /// Ensure we redirect back to the category the question is being saved into.
184     $returnurl = new moodle_url($returnurl);
185     $returnurl->param('category', $fromform->category);
186     $returnurl = $returnurl->out();
188     /// Call the appropriate method.
189     if ($movecontext) {
190         list($tocatid, $tocontextid) = explode(',', $fromform->categorymoveto);
191         $tocontext = get_context_instance_by_id($tocontextid);
192         require_capability('moodle/question:add', $tocontext);
193         if (get_filesdir_from_context($categorycontext) != get_filesdir_from_context($tocontext)){
194             $movecontexturl  = new moodle_url($CFG->wwwroot.'/question/contextmoveq.php',
195                                             array('returnurl' => $returnurl,
196                                                     'ids'=>$question->id,
197                                                     'tocatid'=> $tocatid));
198             if ($cmid){
199                 $movecontexturl->param('cmid', $cmid);
200             } else {
201                 $movecontexturl->param('courseid', $COURSE->id);
202             }
203             redirect($movecontexturl->out());
204         }
205     }
207     $question = $QTYPES[$question->qtype]->save_question($question, $fromform, $COURSE, $wizardnow, true);
208     // a wizardpage from multipe pages questiontype like calculated may not allow editing the question tags 
209     if (!empty($CFG->usetags) && isset($fromform->tags)) {
210         require_once($CFG->dirroot.'/tag/lib.php');
211         tag_set('question', $question->id, $fromform->tags);
212     }
214     if (($QTYPES[$question->qtype]->finished_edit_wizard($fromform)) || $movecontext){
215         if ($inpopup) {
216             notify(get_string('changessaved'), '');
217             close_window(3);
218         } else {
219             if($appendqnumstring){
220                 $returnurl_object=new moodle_url($returnurl);
221                 $returnurl=$returnurl_object->out(false,array($appendqnumstring=>($question->id), "sesskey"=>sesskey(), "cmid"=>$cmid));
222             }
223             redirect($returnurl);
224         }
225     } else {
226         $nexturlparams = array('returnurl'=>$returnurl, 'appendqnumstring'=>$appendqnumstring);
227         if (isset($fromform->nextpageparam) && is_array($fromform->nextpageparam)){
228             $nexturlparams += $fromform->nextpageparam;//useful for passing data to the next page which is not saved in the database
229         }
230         $nexturlparams['id'] = $question->id;
231         $nexturlparams['wizardnow'] = $fromform->wizard;
232         $nexturl = new moodle_url('question.php', $nexturlparams);
233         if ($cmid){
234             $nexturl->param('cmid', $cmid);
235         } else {
236             $nexturl->param('courseid', $COURSE->id);
237         }
238         redirect($nexturl->out());
239     }
240 } else {
242     $streditingquestion = $QTYPES[$question->qtype]->get_heading();
243     $headtags = get_editing_head_contributions($question);
244     if ($cm !== null) {
245         $strmodule = get_string('modulename', $cm->modname);
246         $strupdatemodule = has_capability('moodle/course:manageactivities', get_context_instance(CONTEXT_COURSE, $COURSE->id))
247             ? update_module_button($cm->id, $cm->course, $strmodule)
248             : "";
250         $streditingmodule = get_string('editinga', 'moodle', $strmodule);
252         $navlinks = array();
253         $navlinks[] = array('name' => get_string('modulenameplural', $cm->modname), 'link' => "$CFG->wwwroot/mod/{$cm->modname}/index.php?id=$cm->course", 'type' => 'activity');
254         $navlinks[] = array('name' => format_string($module->name), 'link' => "$CFG->wwwroot/mod/{$cm->modname}/view.php?id={$cm->id}", 'type' => 'title');
255         if (stripos($returnurl, "$CFG->wwwroot/mod/{$cm->modname}/view.php")!== 0){
256             //don't need this link if returnurl returns to view.php
257             $navlinks[] = array('name' => $streditingmodule, 'link' => $returnurl, 'type' => 'title');
258         }
259         $navlinks[] = array('name' => $streditingquestion, 'link' => '', 'type' => 'title');
260         $navigation = build_navigation($navlinks);
261         print_header_simple($streditingquestion, '', $navigation, '', $headtags, true, $strupdatemodule);
263     } else {
264         $navlinks = array();
265         $navlinks[] = array('name' => get_string('editquestions', "quiz"), 'link' => $returnurl, 'type' => 'title');
266         $navlinks[] = array('name' => $streditingquestion, 'link' => '', 'type' => 'title');
267         $strediting = '<a href="edit.php?courseid='.$COURSE->id.'">'.
268                 get_string("editquestions", "quiz").'</a> -> '.$streditingquestion;
269         $navigation = build_navigation($navlinks);
270         print_header_simple($streditingquestion, '', $navigation, '', $headtags);
271     }
273     // Display a heading, question editing form and possibly some extra content needed for
274     // for this question type.
275     $QTYPES[$question->qtype]->display_question_editing_page($mform, $question, $wizardnow);
276     print_footer($COURSE);
278 ?>