Commit | Line | Data |
---|---|---|
aeb15530 | 1 | <?php |
d1b7e03d TH |
2 | // This file is part of Moodle - http://moodle.org/ |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
516cf3eb | 17 | /** |
b72ff476 | 18 | * Functions used to show question editing interface |
4323d029 | 19 | * |
f7970e3c | 20 | * @package moodlecore |
d1b7e03d | 21 | * @subpackage questionbank |
f7970e3c TH |
22 | * @copyright 1999 onwards Martin Dougiamas and others {@link http://moodle.com} |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
d1b7e03d TH |
24 | */ |
25 | ||
516cf3eb | 26 | |
d62382d1 TH |
27 | use core_question\bank\search\category_condition; |
28 | ||
a17b297d | 29 | defined('MOODLE_INTERNAL') || die(); |
516cf3eb | 30 | |
a17b297d | 31 | require_once($CFG->libdir . '/questionlib.php'); |
d1b7e03d | 32 | |
f92cf442 | 33 | define('DEFAULT_QUESTIONS_PER_PAGE', 20); |
a8524f33 | 34 | define('MAXIMUM_QUESTIONS_PER_PAGE', 1000); |
f92cf442 | 35 | |
f4b879dd | 36 | function get_module_from_cmid($cmid) { |
f34488b2 | 37 | global $CFG, $DB; |
38 | if (!$cmrec = $DB->get_record_sql("SELECT cm.*, md.name as modname | |
39 | FROM {course_modules} cm, | |
40 | {modules} md | |
41 | WHERE cm.id = ? AND | |
42 | md.id = cm.module", array($cmid))){ | |
1eda5201 | 43 | print_error('invalidcoursemodule'); |
f34488b2 | 44 | } elseif (!$modrec =$DB->get_record($cmrec->modname, array('id' => $cmrec->instance))) { |
1eda5201 | 45 | print_error('invalidcoursemodule'); |
86909ce0 | 46 | } |
47 | $modrec->instance = $modrec->id; | |
d0e88092 | 48 | $modrec->cmid = $cmrec->id; |
ea16c547 | 49 | $cmrec->name = $modrec->name; |
271e6dec | 50 | |
86909ce0 | 51 | return array($modrec, $cmrec); |
52 | } | |
4fbfd971 | 53 | /** |
54 | * Function to read all questions for category into big array | |
55 | * | |
56 | * @param int $category category number | |
36e2232e | 57 | * @param bool $noparent if true only questions with NO parent will be selected |
58 | * @param bool $recurse include subdirectories | |
5fd8f999 | 59 | * @param bool $export set true if this is called by questionbank export |
4fbfd971 | 60 | */ |
5fd8f999 | 61 | function get_questions_category( $category, $noparent=false, $recurse=true, $export=true ) { |
f9b0500f | 62 | global $DB; |
4fbfd971 | 63 | |
87b564df | 64 | // Build sql bit for $noparent |
4fbfd971 | 65 | $npsql = ''; |
66 | if ($noparent) { | |
67 | $npsql = " and parent='0' "; | |
68 | } | |
69 | ||
2daffca5 | 70 | // Get list of categories |
36e2232e | 71 | if ($recurse) { |
fe857668 | 72 | $categorylist = question_categorylist($category->id); |
2daffca5 TH |
73 | } else { |
74 | $categorylist = array($category->id); | |
36e2232e | 75 | } |
76 | ||
87b564df | 77 | // Get the list of questions for the category |
2daffca5 | 78 | list($usql, $params) = $DB->get_in_or_equal($categorylist); |
1dab8faa | 79 | $questions = $DB->get_records_select('question', "category {$usql} {$npsql}", $params, 'category, qtype, name'); |
4fbfd971 | 80 | |
87b564df TH |
81 | // Iterate through questions, getting stuff we need |
82 | $qresults = array(); | |
83 | foreach($questions as $key => $question) { | |
84 | $question->export_process = $export; | |
85 | $qtype = question_bank::get_qtype($question->qtype, false); | |
86 | if ($export && $qtype->name() == 'missingtype') { | |
87 | // Unrecognised question type. Skip this question when exporting. | |
88 | continue; | |
4fbfd971 | 89 | } |
87b564df TH |
90 | $qtype->get_question_options($question); |
91 | $qresults[] = $question; | |
4fbfd971 | 92 | } |
93 | ||
94 | return $qresults; | |
95 | } | |
96 | ||
df4e2244 | 97 | /** |
9275220d SR |
98 | * Checks whether this is the only child of a top category in a context. |
99 | * | |
f7970e3c | 100 | * @param int $categoryid a category id. |
9275220d | 101 | * @return bool |
df4e2244 | 102 | */ |
9275220d | 103 | function question_is_only_child_of_top_category_in_context($categoryid) { |
df4e2244 | 104 | global $DB; |
105 | return 1 == $DB->count_records_sql(" | |
106 | SELECT count(*) | |
9275220d SR |
107 | FROM {question_categories} c |
108 | JOIN {question_categories} p ON c.parent = p.id | |
109 | JOIN {question_categories} s ON s.parent = c.parent | |
110 | WHERE c.id = ? AND p.parent = 0", array($categoryid)); | |
111 | } | |
112 | ||
113 | /** | |
114 | * Checks whether the category is a "Top" category (with no parent). | |
115 | * | |
116 | * @param int $categoryid a category id. | |
117 | * @return bool | |
118 | */ | |
119 | function question_is_top_category($categoryid) { | |
120 | global $DB; | |
121 | return 0 == $DB->get_field('question_categories', 'parent', array('id' => $categoryid)); | |
df4e2244 | 122 | } |
4fbfd971 | 123 | |
df4e2244 | 124 | /** |
9275220d | 125 | * Ensures that this user is allowed to delete this category. |
df4e2244 | 126 | * |
f7970e3c | 127 | * @param int $todelete a category id. |
df4e2244 | 128 | */ |
129 | function question_can_delete_cat($todelete) { | |
130 | global $DB; | |
9275220d SR |
131 | if (question_is_top_category($todelete)) { |
132 | print_error('cannotdeletetopcat', 'question'); | |
133 | } else if (question_is_only_child_of_top_category_in_context($todelete)) { | |
ac93d63d | 134 | print_error('cannotdeletecate', 'question'); |
271e6dec | 135 | } else { |
df4e2244 | 136 | $contextid = $DB->get_field('question_categories', 'contextid', array('id' => $todelete)); |
d197ea43 | 137 | require_capability('moodle/question:managecategory', context::instance_by_id($contextid)); |
271e6dec | 138 | } |
139 | } | |
f4b879dd | 140 | |
f7970e3c TH |
141 | |
142 | /** | |
143 | * Base class for representing a column in a {@link question_bank_view}. | |
144 | * | |
145 | * @copyright 2009 Tim Hunt | |
146 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 147 | * @deprecated since Moodle 2.7 MDL-40457 |
f7970e3c | 148 | */ |
17f229fa | 149 | class_alias('core_question\bank\column_base', 'question_bank_column_base', true); |
f7970e3c | 150 | |
46795afc | 151 | /** |
152 | * A column with a checkbox for each question with name q{questionid}. | |
f7970e3c TH |
153 | * |
154 | * @copyright 2009 Tim Hunt | |
155 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 156 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 157 | */ |
17f229fa | 158 | class_alias('core_question\bank\checkbox_column', 'question_bank_checkbox_column', true); |
f7970e3c | 159 | |
46795afc | 160 | /** |
161 | * A column type for the name of the question type. | |
f7970e3c TH |
162 | * |
163 | * @copyright 2009 Tim Hunt | |
164 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 165 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 166 | */ |
17f229fa | 167 | class_alias('core_question\bank\question_type_column', 'question_bank_question_type_column', true); |
46795afc | 168 | |
f7970e3c | 169 | |
46795afc | 170 | /** |
171 | * A column type for the name of the question name. | |
f7970e3c TH |
172 | * |
173 | * @copyright 2009 Tim Hunt | |
174 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 175 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 176 | */ |
17f229fa | 177 | class_alias('core_question\bank\question_name_column', 'question_bank_question_name_column', true); |
46795afc | 178 | |
f7970e3c | 179 | |
46795afc | 180 | /** |
181 | * A column type for the name of the question creator. | |
f7970e3c TH |
182 | * |
183 | * @copyright 2009 Tim Hunt | |
184 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 185 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 186 | */ |
17f229fa | 187 | class_alias('core_question\bank\creator_name_column', 'question_bank_creator_name_column', true); |
46795afc | 188 | |
f7970e3c | 189 | |
46795afc | 190 | /** |
191 | * A column type for the name of the question last modifier. | |
f7970e3c TH |
192 | * |
193 | * @copyright 2009 Tim Hunt | |
194 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 195 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 196 | */ |
17f229fa | 197 | class_alias('core_question\bank\modifier_name_column', 'question_bank_modifier_name_column', true); |
46795afc | 198 | |
f7970e3c | 199 | |
46795afc | 200 | /** |
201 | * A base class for actions that are an icon that lets you manipulate the question in some way. | |
f7970e3c TH |
202 | * |
203 | * @copyright 2009 Tim Hunt | |
204 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 205 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 206 | */ |
17f229fa | 207 | class_alias('core_question\bank\action_column_base', 'question_bank_action_column_base', true); |
46795afc | 208 | |
f7970e3c TH |
209 | |
210 | /** | |
211 | * Base class for question bank columns that just contain an action icon. | |
212 | * | |
213 | * @copyright 2009 Tim Hunt | |
214 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 215 | * @deprecated since Moodle 2.7 MDL-40457 |
f7970e3c | 216 | */ |
17f229fa | 217 | class_alias('core_question\bank\edit_action_column', 'question_bank_edit_action_column', true); |
46795afc | 218 | |
e0c41591 K |
219 | /** |
220 | * Question bank column for the duplicate action icon. | |
221 | * | |
222 | * @copyright 2013 The Open University | |
223 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 224 | * @deprecated since Moodle 2.7 MDL-40457 |
e0c41591 | 225 | */ |
17f229fa | 226 | class_alias('core_question\bank\copy_action_column', 'question_bank_copy_action_column', true); |
f7970e3c TH |
227 | |
228 | /** | |
229 | * Question bank columns for the preview action icon. | |
230 | * | |
231 | * @copyright 2009 Tim Hunt | |
232 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 233 | * @deprecated since Moodle 2.7 MDL-40457 |
f7970e3c | 234 | */ |
17f229fa | 235 | class_alias('core_question\bank\preview_action_column', 'question_bank_preview_action_column', true); |
46795afc | 236 | |
f7970e3c | 237 | |
46795afc | 238 | /** |
239 | * action to delete (or hide) a question, or restore a previously hidden question. | |
f7970e3c TH |
240 | * |
241 | * @copyright 2009 Tim Hunt | |
242 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 243 | * @deprecated since Moodle 2.7 MDL-40457 |
46795afc | 244 | */ |
17f229fa | 245 | class_alias('core_question\bank\delete_action_column', 'question_bank_delete_action_column', true); |
46795afc | 246 | |
e4d1d5e0 | 247 | /** |
248 | * Base class for 'columns' that are actually displayed as a row following the main question row. | |
f7970e3c TH |
249 | * |
250 | * @copyright 2009 Tim Hunt | |
251 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 252 | * @deprecated since Moodle 2.7 MDL-40457 |
e4d1d5e0 | 253 | */ |
17f229fa | 254 | class_alias('core_question\bank\row_base', 'question_bank_row_base', true); |
e4d1d5e0 | 255 | |
256 | /** | |
257 | * A column type for the name of the question name. | |
f7970e3c TH |
258 | * |
259 | * @copyright 2009 Tim Hunt | |
260 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 261 | * @deprecated since Moodle 2.7 MDL-40457 |
e4d1d5e0 | 262 | */ |
17f229fa | 263 | class_alias('core_question\bank\question_text_row', 'question_bank_question_text_row', true); |
e4d1d5e0 | 264 | |
4fbfd971 | 265 | /** |
f7970e3c TH |
266 | * @copyright 2009 Tim Hunt |
267 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
17f229fa | 268 | * @deprecated since Moodle 2.7 MDL-40457 |
4fbfd971 | 269 | */ |
17f229fa | 270 | class_alias('core_question\bank\view', 'question_bank_view', true); |
f4b879dd | 271 | |
b72ff476 | 272 | /** |
273 | * Common setup for all pages for editing questions. | |
453b28d8 | 274 | * @param string $baseurl the name of the script calling this funciton. For examle 'qusetion/edit.php'. |
271e6dec | 275 | * @param string $edittab code for this edit tab |
f7970e3c | 276 | * @param bool $requirecmid require cmid? default false |
5aeba199 | 277 | * @param bool $unused no longer used, do no pass |
271e6dec | 278 | * @return array $thispageurl, $contexts, $cmid, $cm, $module, $pagevars |
b72ff476 | 279 | */ |
5aeba199 | 280 | function question_edit_setup($edittab, $baseurl, $requirecmid = false, $unused = null) { |
73d16fc6 | 281 | global $PAGE; |
5aeba199 DP |
282 | |
283 | if ($unused !== null) { | |
284 | debugging('Deprecated argument passed to question_edit_setup()', DEBUG_DEVELOPER); | |
285 | } | |
271e6dec | 286 | |
73d16fc6 RW |
287 | $params = []; |
288 | ||
289 | if ($requirecmid) { | |
290 | $params['cmid'] = required_param('cmid', PARAM_INT); | |
291 | } else { | |
292 | $params['cmid'] = optional_param('cmid', null, PARAM_INT); | |
293 | } | |
294 | ||
295 | if (!$params['cmid']) { | |
296 | $params['courseid'] = required_param('courseid', PARAM_INT); | |
297 | } | |
298 | ||
299 | $params['qpage'] = optional_param('qpage', null, PARAM_INT); | |
300 | ||
301 | // Pass 'cat' from page to page and when 'category' comes from a drop down menu | |
302 | // then we also reset the qpage so we go to page 1 of | |
303 | // a new cat. | |
304 | $params['cat'] = optional_param('cat', null, PARAM_SEQUENCE); // If empty will be set up later. | |
305 | $params['category'] = optional_param('category', null, PARAM_SEQUENCE); | |
306 | $params['qperpage'] = optional_param('qperpage', null, PARAM_INT); | |
307 | ||
308 | // Question table sorting options. | |
309 | for ($i = 1; $i <= question_bank_view::MAX_SORTS; $i++) { | |
310 | $param = 'qbs' . $i; | |
311 | if ($sort = optional_param($param, '', PARAM_TEXT)) { | |
312 | $params[$param] = $sort; | |
313 | } else { | |
314 | break; | |
315 | } | |
316 | } | |
317 | ||
318 | // Display options. | |
319 | $params['recurse'] = optional_param('recurse', null, PARAM_BOOL); | |
320 | $params['showhidden'] = optional_param('showhidden', null, PARAM_BOOL); | |
321 | $params['qbshowtext'] = optional_param('qbshowtext', null, PARAM_BOOL); | |
322 | // Category list page. | |
323 | $params['cpage'] = optional_param('cpage', null, PARAM_INT); | |
324 | $params['qtagids'] = optional_param_array('qtagids', null, PARAM_INT); | |
325 | ||
326 | $PAGE->set_pagelayout('admin'); | |
327 | ||
328 | return question_build_edit_resources($edittab, $baseurl, $params); | |
329 | } | |
330 | ||
331 | /** | |
332 | * Common function for building the generic resources required by the | |
333 | * editing questions pages. | |
334 | * | |
335 | * Either a cmid or a course id must be provided as keys in $params or | |
336 | * an exception will be thrown. All other params are optional and will have | |
337 | * sane default applied if not provided. | |
338 | * | |
339 | * The acceptable keys for $params are: | |
340 | * [ | |
341 | * 'cmid' => PARAM_INT, | |
342 | * 'courseid' => PARAM_INT, | |
343 | * 'qpage' => PARAM_INT, | |
344 | * 'cat' => PARAM_SEQUENCE, | |
345 | * 'category' => PARAM_SEQUENCE, | |
346 | * 'qperpage' => PARAM_INT, | |
347 | * 'recurse' => PARAM_INT, | |
348 | * 'showhidden' => PARAM_INT, | |
349 | * 'qbshowtext' => PARAM_INT, | |
350 | * 'cpage' => PARAM_INT, | |
351 | * 'recurse' => PARAM_BOOL, | |
352 | * 'showhidden' => PARAM_BOOL, | |
353 | * 'qbshowtext' => PARAM_BOOL, | |
354 | * 'qtagids' => [PARAM_INT], (array of integers) | |
355 | * 'qbs1' => PARAM_TEXT, | |
356 | * 'qbs2' => PARAM_TEXT, | |
357 | * 'qbs3' => PARAM_TEXT, | |
358 | * ... and more qbs keys up to question_bank_view::MAX_SORTS ... | |
359 | * ]; | |
360 | * | |
361 | * @param string $edittab Code for this edit tab | |
362 | * @param string $baseurl The name of the script calling this funciton. For examle 'qusetion/edit.php'. | |
363 | * @param array $params The provided parameters to construct the resources with. | |
364 | * @return array $thispageurl, $contexts, $cmid, $cm, $module, $pagevars | |
365 | */ | |
366 | function question_build_edit_resources($edittab, $baseurl, $params) { | |
367 | global $DB, $PAGE, $CFG; | |
368 | ||
453b28d8 | 369 | $thispageurl = new moodle_url($baseurl); |
47ce714b | 370 | $thispageurl->remove_all_params(); // We are going to explicity add back everything important - this avoids unwanted params from being retained. |
b4a2e413 | 371 | |
73d16fc6 RW |
372 | $cleanparams = [ |
373 | 'qsorts' => [], | |
374 | 'qtagids' => [] | |
375 | ]; | |
376 | $paramtypes = [ | |
377 | 'cmid' => PARAM_INT, | |
378 | 'courseid' => PARAM_INT, | |
379 | 'qpage' => PARAM_INT, | |
380 | 'cat' => PARAM_SEQUENCE, | |
381 | 'category' => PARAM_SEQUENCE, | |
382 | 'qperpage' => PARAM_INT, | |
383 | 'recurse' => PARAM_INT, | |
384 | 'showhidden' => PARAM_INT, | |
385 | 'qbshowtext' => PARAM_INT, | |
386 | 'cpage' => PARAM_INT, | |
387 | 'recurse' => PARAM_BOOL, | |
388 | 'showhidden' => PARAM_BOOL, | |
389 | 'qbshowtext' => PARAM_BOOL | |
390 | ]; | |
391 | ||
392 | foreach ($paramtypes as $name => $type) { | |
393 | if (isset($params[$name])) { | |
394 | $cleanparams[$name] = clean_param($params[$name], $type); | |
395 | } else { | |
396 | $cleanparams[$name] = null; | |
397 | } | |
398 | } | |
399 | ||
400 | if (!empty($params['qtagids'])) { | |
401 | $cleanparams['qtagids'] = clean_param_array($params['qtagids'], PARAM_INT); | |
402 | } | |
403 | ||
404 | $cmid = $cleanparams['cmid']; | |
405 | $courseid = $cleanparams['courseid']; | |
406 | $qpage = $cleanparams['qpage'] ?: -1; | |
407 | $cat = $cleanparams['cat'] ?: 0; | |
408 | $category = $cleanparams['category'] ?: 0; | |
409 | $qperpage = $cleanparams['qperpage']; | |
410 | $recurse = $cleanparams['recurse']; | |
411 | $showhidden = $cleanparams['showhidden']; | |
412 | $qbshowtext = $cleanparams['qbshowtext']; | |
413 | $cpage = $cleanparams['cpage'] ?: 1; | |
414 | $recurse = $cleanparams['recurse']; | |
415 | $showhidden = $cleanparams['showhidden']; | |
416 | $qbshowtext = $cleanparams['qbshowtext']; | |
417 | $qsorts = $cleanparams['qsorts']; | |
418 | $qtagids = $cleanparams['qtagids']; | |
419 | ||
420 | if (is_null($cmid) && is_null($courseid)) { | |
421 | throw new \moodle_exception('Must provide a cmid or courseid'); | |
b72ff476 | 422 | } |
73d16fc6 RW |
423 | |
424 | if ($cmid) { | |
271e6dec | 425 | list($module, $cm) = get_module_from_cmid($cmid); |
b72ff476 | 426 | $courseid = $cm->course; |
427 | $thispageurl->params(compact('cmid')); | |
271e6dec | 428 | require_login($courseid, false, $cm); |
21c08c63 | 429 | $thiscontext = context_module::instance($cmid); |
b72ff476 | 430 | } else { |
431 | $module = null; | |
432 | $cm = null; | |
5aeba199 DP |
433 | $thispageurl->params(compact('courseid')); |
434 | require_login($courseid, false); | |
435 | $thiscontext = context_course::instance($courseid); | |
b72ff476 | 436 | } |
271e6dec | 437 | |
438 | if ($thiscontext){ | |
439 | $contexts = new question_edit_contexts($thiscontext); | |
440 | $contexts->require_one_edit_tab_cap($edittab); | |
271e6dec | 441 | } else { |
442 | $contexts = null; | |
443 | } | |
444 | ||
73d16fc6 | 445 | $pagevars['qpage'] = $qpage; |
271e6dec | 446 | |
73d16fc6 RW |
447 | // Pass 'cat' from page to page and when 'category' comes from a drop down menu |
448 | // then we also reset the qpage so we go to page 1 of | |
449 | // a new cat. | |
450 | if ($category && $category != $cat) { // Is this a move to a new category? | |
451 | $pagevars['cat'] = $category; | |
452 | $pagevars['qpage'] = 0; | |
453 | } else { | |
454 | $pagevars['cat'] = $cat; // If empty will be set up later. | |
7bc26c8f | 455 | } |
73d16fc6 | 456 | |
7bc26c8f | 457 | if ($pagevars['cat']){ |
458 | $thispageurl->param('cat', $pagevars['cat']); | |
459 | } | |
73d16fc6 | 460 | |
f19ed874 TH |
461 | if (strpos($baseurl, '/question/') === 0) { |
462 | navigation_node::override_active_url($thispageurl); | |
463 | } | |
464 | ||
73d16fc6 RW |
465 | // This need to occur after the override_active_url call above because |
466 | // these values change on the page request causing the URLs to mismatch | |
467 | // when trying to work out the active node. | |
468 | for ($i = 1; $i <= question_bank_view::MAX_SORTS; $i++) { | |
469 | $param = 'qbs' . $i; | |
470 | if (isset($params[$param])) { | |
471 | $value = clean_param($params[$param], PARAM_TEXT); | |
472 | } else { | |
473 | break; | |
474 | } | |
475 | $thispageurl->param($param, $value); | |
476 | } | |
477 | ||
b72ff476 | 478 | if ($pagevars['qpage'] > -1) { |
479 | $thispageurl->param('qpage', $pagevars['qpage']); | |
480 | } else { | |
481 | $pagevars['qpage'] = 0; | |
482 | } | |
483 | ||
728e195c | 484 | $pagevars['qperpage'] = question_set_or_get_user_preference( |
73d16fc6 | 485 | 'qperpage', $qperpage, DEFAULT_QUESTIONS_PER_PAGE, $thispageurl); |
36e298bc | 486 | |
271e6dec | 487 | $defaultcategory = question_make_default_categories($contexts->all()); |
488 | ||
73d16fc6 | 489 | $contextlistarr = []; |
271e6dec | 490 | foreach ($contexts->having_one_edit_tab_cap($edittab) as $context){ |
f4fe3968 | 491 | $contextlistarr[] = "'{$context->id}'"; |
271e6dec | 492 | } |
ee439d01 | 493 | $contextlist = join(' ,', $contextlistarr); |
271e6dec | 494 | if (!empty($pagevars['cat'])){ |
495 | $catparts = explode(',', $pagevars['cat']); | |
e0736817 | 496 | if (!$catparts[0] || (false !== array_search($catparts[1], $contextlistarr)) || |
f34488b2 | 497 | !$DB->count_records_select("question_categories", "id = ? AND contextid = ?", array($catparts[0], $catparts[1]))) { |
5e8a85aa | 498 | print_error('invalidcategory', 'question'); |
271e6dec | 499 | } |
500 | } else { | |
501 | $category = $defaultcategory; | |
f4fe3968 | 502 | $pagevars['cat'] = "{$category->id},{$category->contextid}"; |
36e298bc | 503 | } |
504 | ||
be77e9b6 | 505 | // Display options. |
728e195c SL |
506 | $pagevars['recurse'] = question_set_or_get_user_preference('recurse', $recurse, 1, $thispageurl); |
507 | $pagevars['showhidden'] = question_set_or_get_user_preference('showhidden', $showhidden, 0, $thispageurl); | |
508 | $pagevars['qbshowtext'] = question_set_or_get_user_preference('qbshowtext', $qbshowtext, 0, $thispageurl); | |
271e6dec | 509 | |
be77e9b6 | 510 | // Category list page. |
73d16fc6 | 511 | $pagevars['cpage'] = $cpage; |
986effb6 | 512 | if ($pagevars['cpage'] != 1){ |
513 | $thispageurl->param('cpage', $pagevars['cpage']); | |
514 | } | |
36e298bc | 515 | |
73d16fc6 RW |
516 | $pagevars['qtagids'] = $qtagids; |
517 | foreach ($pagevars['qtagids'] as $index => $qtagid) { | |
518 | $thispageurl->param("qtagids[{$index}]", $qtagid); | |
519 | } | |
520 | ||
271e6dec | 521 | return array($thispageurl, $contexts, $cmid, $cm, $module, $pagevars); |
522 | } | |
271e6dec | 523 | |
e1a2d0d9 CC |
524 | /** |
525 | * Get the category id from $pagevars. | |
526 | * @param array $pagevars from {@link question_edit_setup()}. | |
527 | * @return int the category id. | |
528 | */ | |
529 | function question_get_category_id_from_pagevars(array $pagevars) { | |
530 | list($questioncategoryid) = explode(',', $pagevars['cat']); | |
531 | return $questioncategoryid; | |
532 | } | |
533 | ||
be77e9b6 TH |
534 | /** |
535 | * Get a particular question preference that is also stored as a user preference. | |
536 | * If the the value is given in the GET/POST request, then that value is used, | |
537 | * and the user preference is updated to that value. Otherwise, the last set | |
538 | * value of the user preference is used, or if it has never been set the default | |
539 | * passed to this function. | |
540 | * | |
541 | * @param string $param the param name. The URL parameter set, and the GET/POST | |
542 | * parameter read. The user_preference name is 'question_bank_' . $param. | |
543 | * @param mixed $default The default value to use, if not otherwise set. | |
544 | * @param int $type one of the PARAM_... constants. | |
545 | * @param moodle_url $thispageurl if the value has been explicitly set, we add | |
546 | * it to this URL. | |
547 | * @return mixed the parameter value to use. | |
548 | */ | |
549 | function question_get_display_preference($param, $default, $type, $thispageurl) { | |
550 | $submittedvalue = optional_param($param, null, $type); | |
728e195c | 551 | return question_set_or_get_user_preference($param, $submittedvalue, $default, $thispageurl); |
73d16fc6 RW |
552 | } |
553 | ||
554 | /** | |
555 | * Get a user preference by name or set the user preference to a given value. | |
556 | * | |
557 | * If $value is null then the function will only attempt to retrieve the | |
558 | * user preference requested by $name. If no user preference is found then the | |
559 | * $default value will be returned. In this case the user preferences are not | |
560 | * modified and nor are the params on $thispageurl. | |
561 | * | |
562 | * If $value is anything other than null then the function will set the user | |
563 | * preference $name to the provided $value and will also set it as a param | |
564 | * on $thispageurl. | |
565 | * | |
566 | * @param string $name The user_preference name is 'question_bank_' . $name. | |
567 | * @param mixed $value The preference value. | |
568 | * @param mixed $default The default value to use, if not otherwise set. | |
569 | * @param moodle_url $thispageurl if the value has been explicitly set, we add | |
570 | * it to this URL. | |
571 | * @return mixed the parameter value to use. | |
572 | */ | |
728e195c | 573 | function question_set_or_get_user_preference($name, $value, $default, $thispageurl) { |
73d16fc6 RW |
574 | if (is_null($value)) { |
575 | return get_user_preferences('question_bank_' . $name, $default); | |
be77e9b6 TH |
576 | } |
577 | ||
73d16fc6 RW |
578 | set_user_preference('question_bank_' . $name, $value); |
579 | $thispageurl->param($name, $value); | |
580 | return $value; | |
be77e9b6 TH |
581 | } |
582 | ||
271e6dec | 583 | /** |
584 | * Make sure user is logged in as required in this context. | |
585 | */ | |
586 | function require_login_in_context($contextorid = null){ | |
042a8403 | 587 | global $DB, $CFG; |
271e6dec | 588 | if (!is_object($contextorid)){ |
5fbe2118 | 589 | $context = context::instance_by_id($contextorid, IGNORE_MISSING); |
271e6dec | 590 | } else { |
591 | $context = $contextorid; | |
592 | } | |
593 | if ($context && ($context->contextlevel == CONTEXT_COURSE)) { | |
594 | require_login($context->instanceid); | |
595 | } else if ($context && ($context->contextlevel == CONTEXT_MODULE)) { | |
f34488b2 | 596 | if ($cm = $DB->get_record('course_modules',array('id' =>$context->instanceid))) { |
597 | if (!$course = $DB->get_record('course', array('id' => $cm->course))) { | |
0be2c858 | 598 | print_error('invalidcourseid'); |
271e6dec | 599 | } |
600 | require_course_login($course, true, $cm); | |
601 | ||
602 | } else { | |
0be2c858 | 603 | print_error('invalidcoursemodule'); |
271e6dec | 604 | } |
605 | } else if ($context && ($context->contextlevel == CONTEXT_SYSTEM)) { | |
606 | if (!empty($CFG->forcelogin)) { | |
607 | require_login(); | |
608 | } | |
609 | ||
610 | } else { | |
611 | require_login(); | |
612 | } | |
b72ff476 | 613 | } |
cd120b23 | 614 | |
615 | /** | |
616 | * Print a form to let the user choose which question type to add. | |
617 | * When the form is submitted, it goes to the question.php script. | |
618 | * @param $hiddenparams hidden parameters to add to the form, in addition to | |
75733895 TH |
619 | * the qtype radio buttons. |
620 | * @param $allowedqtypes optional list of qtypes that are allowed. If given, only | |
621 | * those qtypes will be shown. Example value array('description', 'multichoice'). | |
cd120b23 | 622 | */ |
ac32c27e | 623 | function print_choose_qtype_to_add_form($hiddenparams, array $allowedqtypes = null, $enablejs = true) { |
f9b0500f | 624 | global $CFG, $PAGE, $OUTPUT; |
7b66b651 | 625 | |
891750bc | 626 | $chooser = core_question\output\qbank_chooser::get($PAGE->course, $hiddenparams, $allowedqtypes); |
ac32c27e | 627 | $renderer = $PAGE->get_renderer('question', 'bank'); |
891750bc FM |
628 | |
629 | return $renderer->render($chooser); | |
cd120b23 | 630 | } |
631 | ||
632 | /** | |
633 | * Print a button for creating a new question. This will open question/addquestion.php, | |
634 | * which in turn goes to question/question.php before getting back to $params['returnurl'] | |
635 | * (by default the question bank screen). | |
636 | * | |
f7970e3c | 637 | * @param int $categoryid The id of the category that the new question should be added to. |
cd120b23 | 638 | * @param array $params Other paramters to add to the URL. You need either $params['cmid'] or |
639 | * $params['courseid'], and you should probably set $params['returnurl'] | |
640 | * @param string $caption the text to display on the button. | |
641 | * @param string $tooltip a tooltip to add to the button (optional). | |
f7970e3c | 642 | * @param bool $disabled if true, the button will be disabled. |
cd120b23 | 643 | */ |
644 | function create_new_question_button($categoryid, $params, $caption, $tooltip = '', $disabled = false) { | |
fef8f84e | 645 | global $CFG, $PAGE, $OUTPUT; |
cd120b23 | 646 | static $choiceformprinted = false; |
647 | $params['category'] = $categoryid; | |
a6855934 | 648 | $url = new moodle_url('/question/addquestion.php', $params); |
5c2ed7e2 | 649 | echo $OUTPUT->single_button($url, $caption, 'get', array('disabled'=>$disabled, 'title'=>$tooltip)); |
a941387a | 650 | |
cd120b23 | 651 | if (!$choiceformprinted) { |
652 | echo '<div id="qtypechoicecontainer">'; | |
e1a2d0d9 | 653 | echo print_choose_qtype_to_add_form(array()); |
cd120b23 | 654 | echo "</div>\n"; |
655 | $choiceformprinted = true; | |
656 | } | |
657 | } | |
658 | ||
aeb15530 | 659 |