Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
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
 
17
namespace qbank_managecategories;
18
 
19
/**
20
 * QUESTION_PAGE_LENGTH - Number of categories to display on page.
1441 ariadna 21
 *
22
 * @deprecated Since Moodle 4.5 MDL-72397. This was only used in moodle_list::display_page_numbers which is now deprecated.
23
 * @todo Final removal in Moodle 6.0 MDL-80804.
1 efrain 24
 */
25
define('QUESTION_PAGE_LENGTH', 25);
26
 
27
use context;
28
use moodle_exception;
29
use moodle_url;
30
use qbank_managecategories\form\question_category_edit_form;
31
use question_bank;
32
use stdClass;
33
 
34
/**
35
 * Class for performing operations on question categories.
36
 *
37
 * @package    qbank_managecategories
38
 * @copyright  1999 onwards Martin Dougiamas {@link http://moodle.com}
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1441 ariadna 40
 * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager or \qbank_managecategories\question_categories.
41
 * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 42
 */
43
class question_category_object {
44
 
45
    /**
46
     * @var array common language strings.
47
     */
48
    public $str;
49
 
50
    /**
51
     * @var array nested lists to display categories.
52
     */
53
    public $editlists = [];
54
 
55
    /**
56
     * @var string tab.
57
     */
58
    public $tab;
59
 
60
    /**
61
     * @var int tab size.
62
     */
63
    public $tabsize = 3;
64
 
65
    /**
66
     * @var moodle_url Object representing url for this page
67
     */
68
    public $pageurl;
69
 
70
    /**
71
     * @var question_category_edit_form Object representing form for adding / editing categories.
72
     */
73
    public $catform;
74
 
75
    /**
76
     * Constructor.
77
     *
78
     * @param int $page page number.
79
     * @param moodle_url $pageurl base URL of the display categories page. Used for redirects.
80
     * @param context[] $contexts contexts where the current user can edit categories.
81
     * @param int $currentcat id of the category to be edited. 0 if none.
82
     * @param int|null $defaultcategory id of the current category. null if none.
83
     * @param int $todelete id of the category to delete. 0 if none.
84
     * @param context[] $addcontexts contexts where the current user can add questions.
1441 ariadna 85
     * @deprecated Since Moodle 4.5 MDL-72397. Use \qbank_managecategories\question_categories or \core_question\category_manager.
86
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 87
     */
1441 ariadna 88
    #[\core\attribute\deprecated(
89
        '\qbank_managecategories\question_categories or \core_question\category_manager',
90
        since: 4.5,
91
        reason: 'API properly divided between qbank_managecategories and core_question',
92
        mdl: 'MDL-72397',
93
    )]
1 efrain 94
    public function __construct($page, $pageurl, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
1441 ariadna 95
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 96
        $this->tab = str_repeat('&nbsp;', $this->tabsize);
97
 
98
        $this->str = new stdClass();
99
        $this->str->course         = get_string('course');
100
        $this->str->category       = get_string('category', 'question');
101
        $this->str->categoryinfo   = get_string('categoryinfo', 'question');
102
        $this->str->questions      = get_string('questions', 'question');
103
        $this->str->add            = get_string('add');
104
        $this->str->delete         = get_string('delete');
105
        $this->str->moveup         = get_string('moveup');
106
        $this->str->movedown       = get_string('movedown');
107
        $this->str->edit           = get_string('editthiscategory', 'question');
108
        $this->str->hide           = get_string('hide');
109
        $this->str->order          = get_string('order');
110
        $this->str->parent         = get_string('parent', 'question');
111
        $this->str->add            = get_string('add');
112
        $this->str->action         = get_string('action');
113
        $this->str->top            = get_string('top');
114
        $this->str->addcategory    = get_string('addcategory', 'question');
115
        $this->str->editcategory   = get_string('editcategory', 'question');
116
        $this->str->cancel         = get_string('cancel');
117
        $this->str->editcategories = get_string('editcategories', 'question');
118
        $this->str->page           = get_string('page');
119
 
120
        $this->pageurl = $pageurl;
121
    }
122
 
123
    /**
124
     * Initializes this classes general category-related variables
125
     *
126
     * @param int $page page number.
127
     * @param context[] $contexts contexts where the current user can edit categories.
128
     * @param int $currentcat id of the category to be edited. 0 if none.
129
     * @param int|null $defaultcategory id of the current category. null if none.
130
     * @param int $todelete id of the category to delete. 0 if none.
131
     * @param context[] $addcontexts contexts where the current user can add questions.
1441 ariadna 132
     * @deprecated Since Moodle 4.5 MDL-72397. Use \qbank_managecategories\question_categories instead.
133
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 134
     */
1441 ariadna 135
    #[\core\attribute\deprecated(
136
        '\qbank_managecategories\question_categories',
137
        since: 4.5,
138
        reason: 'API properly divided between qbank_managecategories and core_question',
139
        mdl: 'MDL-72397',
140
    )]
1 efrain 141
    public function initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts): void {
1441 ariadna 142
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 143
        $lastlist = null;
144
        foreach ($contexts as $context) {
145
            $this->editlists[$context->id] =
146
                new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context);
147
            $this->editlists[$context->id]->lastlist =& $lastlist;
148
            if ($lastlist !== null) {
149
                $lastlist->nextlist =& $this->editlists[$context->id];
150
            }
151
            $lastlist =& $this->editlists[$context->id];
152
        }
153
 
154
        $count = 1;
155
        $paged = false;
156
        foreach ($this->editlists as $key => $list) {
157
            list($paged, $count) = $this->editlists[$key]->list_from_records($paged, $count);
158
        }
159
        $this->catform = new question_category_edit_form($this->pageurl,
160
                ['contexts' => $contexts, 'currentcat' => $currentcat ?? 0]);
161
        if (!$currentcat) {
162
            $this->catform->set_data(['parent' => $defaultcategory]);
163
        }
164
    }
165
 
166
    /**
167
     * Displays the user interface.
168
     *
1441 ariadna 169
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
170
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 171
     */
1441 ariadna 172
    #[\core\attribute\deprecated(
173
        '\core_question\category_manager::get_real_question_ids_in_category',
174
        since: 4.5,
175
        reason: 'No longer used',
176
        mdl: 'MDL-72397',
177
    )]
1 efrain 178
    public function display_user_interface(): void {
1441 ariadna 179
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 180
        // Interface for editing existing categories.
181
        $this->output_edit_lists();
182
    }
183
 
184
    /**
185
     * Outputs a table to allow entry of a new category
1441 ariadna 186
     *
187
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
188
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 189
     */
1441 ariadna 190
    #[\core\attribute\deprecated(
191
        '\core_question\category_manager::get_real_question_ids_in_category',
192
        since: 4.5,
193
        reason: 'No longer used',
194
        mdl: 'MDL-72397',
195
    )]
1 efrain 196
    public function output_new_table(): void {
1441 ariadna 197
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 198
        $this->catform->display();
199
    }
200
 
201
    /**
202
     * Outputs a list to allow editing/rearranging of existing categories.
203
     *
204
     * $this->initialize() must have already been called
205
     *
1441 ariadna 206
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
207
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 208
     */
1441 ariadna 209
    #[\core\attribute\deprecated(
210
        '\core_question\category_manager::get_real_question_ids_in_category',
211
        since: 4.5,
212
        reason: 'No longer used',
213
        mdl: 'MDL-72397',
214
    )]
1 efrain 215
    public function output_edit_lists(): void {
1441 ariadna 216
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 217
        global $OUTPUT;
218
 
219
        echo $OUTPUT->heading_with_help(get_string('questioncategories', 'question'), 'editcategories', 'question');
220
 
221
        foreach ($this->editlists as $context => $list) {
222
            $listhtml = $list->to_html(0, ['str' => $this->str]);
223
            if ($listhtml) {
224
                echo $OUTPUT->box_start('boxwidthwide boxaligncenter generalbox questioncategories contextlevel' .
225
                    $list->context->contextlevel);
226
                $fullcontext = context::instance_by_id($context);
227
                echo $OUTPUT->heading(get_string('questioncatsfor', 'question', $fullcontext->get_context_name()), 3);
228
                echo $listhtml;
229
                echo $OUTPUT->box_end();
230
            }
231
        }
232
        echo $list->display_page_numbers();
233
    }
234
 
235
    /**
236
     * Gets all the courseids for the given categories.
237
     *
238
     * @param array $categories contains category objects in  a tree representation
239
     * @return array courseids flat array in form categoryid=>courseid
1441 ariadna 240
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
241
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 242
     */
1441 ariadna 243
    #[\core\attribute\deprecated(
244
        '\core_question\category_manager::get_real_question_ids_in_category',
245
        since: 4.5,
246
        reason: 'No longer used',
247
        mdl: 'MDL-72397',
248
    )]
1 efrain 249
    public function get_course_ids(array $categories): array {
1441 ariadna 250
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 251
        $courseids = [];
252
        foreach ($categories as $key => $cat) {
253
            $courseids[$key] = $cat->course;
254
            if (!empty($cat->children)) {
255
                $courseids = array_merge($courseids, $this->get_course_ids($cat->children));
256
            }
257
        }
258
        return $courseids;
259
    }
260
 
261
    /**
262
     * Edit a category, or add a new one if the id is zero.
263
     *
264
     * @param int $categoryid Category id.
1441 ariadna 265
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
266
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 267
     */
1441 ariadna 268
    #[\core\attribute\deprecated(
269
        '\core_question\category_manager::get_real_question_ids_in_category',
270
        since: 4.5,
271
        reason: 'No longer used',
272
        mdl: 'MDL-72397',
273
    )]
1 efrain 274
    public function edit_single_category(int $categoryid): void {
1441 ariadna 275
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 276
        // Interface for adding a new category.
277
        global $DB;
278
 
279
        if ($categoryid) {
280
            // Editing an existing category.
281
            $category = $DB->get_record("question_categories", ["id" => $categoryid], '*', MUST_EXIST);
282
            if ($category->parent == 0) {
283
                throw new moodle_exception('cannotedittopcat', 'question', '', $categoryid);
284
            }
285
 
286
            $category->parent = "{$category->parent},{$category->contextid}";
287
            $category->submitbutton = get_string('savechanges');
288
            $category->categoryheader = $this->str->edit;
289
            $this->catform->set_data($category);
290
        }
291
 
292
        // Show the form.
293
        $this->catform->display();
294
    }
295
 
296
    /**
297
     * Sets the viable parents.
298
     *
299
     *  Viable parents are any except for the category itself, or any of it's descendants
300
     *  The parentstrings parameter is passed by reference and changed by this function.
301
     *
302
     * @param array $parentstrings a list of parentstrings
303
     * @param object $category Category object
1441 ariadna 304
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
305
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 306
     */
1441 ariadna 307
    #[\core\attribute\deprecated(
308
        '\core_question\category_manager::get_real_question_ids_in_category',
309
        since: 4.5,
310
        reason: 'No longer used',
311
        mdl: 'MDL-72397',
312
    )]
1 efrain 313
    public function set_viable_parents(array &$parentstrings, object $category): void {
1441 ariadna 314
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 315
        unset($parentstrings[$category->id]);
316
        if (isset($category->children)) {
317
            foreach ($category->children as $child) {
318
                $this->set_viable_parents($parentstrings, $child);
319
            }
320
        }
321
    }
322
 
323
    /**
324
     * Gets question categories.
325
     *
326
     * @param int|null $parent - if given, restrict records to those with this parent id.
327
     * @param string $sort - [[sortfield [,sortfield]] {ASC|DESC}].
328
     * @return array categories.
1441 ariadna 329
     * @deprecated Since Moodle 4.5 MDL-72397. No longer used.
330
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 331
     */
1441 ariadna 332
    #[\core\attribute\deprecated(
333
        '\core_question\category_manager::get_real_question_ids_in_category',
334
        since: 4.5,
335
        reason: 'No longer used',
336
        mdl: 'MDL-72397',
337
    )]
338
    public function get_question_categories(?int $parent = null, string $sort = "sortorder ASC"): array {
339
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 340
        global $COURSE, $DB;
341
        if (is_null($parent)) {
342
            $categories = $DB->get_records('question_categories', ['course' => $COURSE->id], $sort);
343
        } else {
344
            $select = "parent = ? AND course = ?";
345
            $categories = $DB->get_records_select('question_categories', $select, [$parent, $COURSE->id], $sort);
346
        }
347
        return $categories;
348
    }
349
 
350
    /**
351
     * Deletes an existing question category.
352
     *
353
     * @param int $categoryid id of category to delete.
1441 ariadna 354
     * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager instead.
355
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 356
     */
1441 ariadna 357
    #[\core\attribute\deprecated(
358
        '\core_question\category_manager::delete_category',
359
        since: 4.5,
360
        reason: 'API properly divided between qbank_managecategories and core_question',
361
        mdl: 'MDL-72397',
362
    )]
1 efrain 363
    public function delete_category(int $categoryid): void {
1441 ariadna 364
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 365
        global $CFG, $DB;
366
        helper::question_can_delete_cat($categoryid);
367
        if (!$category = $DB->get_record("question_categories", ["id" => $categoryid])) {  // Security.
368
            throw new moodle_exception('unknowcategory');
369
        }
370
        // Send the children categories to live with their grandparent.
371
        $DB->set_field("question_categories", "parent", $category->parent, ["parent" => $category->id]);
372
 
373
        // Finally delete the category itself.
374
        $DB->delete_records("question_categories", ["id" => $category->id]);
375
 
376
        // Log the deletion of this category.
377
        $event = \core\event\question_category_deleted::create_from_question_category_instance($category);
378
        $event->add_record_snapshot('question_categories', $category);
379
        $event->trigger();
380
 
381
    }
382
 
383
    /**
384
     * Move questions and then delete the category.
385
     *
386
     * @param int $oldcat id of the old category.
387
     * @param int $newcat id of the new category.
1441 ariadna 388
     * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager instead.
389
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 390
     */
1441 ariadna 391
    #[\core\attribute\deprecated(
392
        '\core_question\category_manager::move_questions_and_delete_category',
393
        since: 4.5,
394
        reason: 'API properly divided between qbank_managecategories and core_question',
395
        mdl: 'MDL-72397',
396
    )]
1 efrain 397
    public function move_questions_and_delete_category(int $oldcat, int $newcat): void {
1441 ariadna 398
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 399
        helper::question_can_delete_cat($oldcat);
400
        $this->move_questions($oldcat, $newcat);
401
        $this->delete_category($oldcat);
402
    }
403
 
404
    /**
405
     * Display the form to move a category.
406
     *
407
     * @param int $questionsincategory
408
     * @param object $category
409
     * @throws \coding_exception
410
     *
411
     * @deprecated No longer used by internal code and not recommended since Moodle 4.2 MDL-77299.
412
     */
413
    public function display_move_form($questionsincategory, $category): void {
1441 ariadna 414
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 415
        debugging(
416
            'display_move_form() is deprecated and no longer used by internal code.',
417
            DEBUG_DEVELOPER
418
        );
419
        global $OUTPUT;
420
        $vars = new stdClass();
421
        $vars->name = $category->name;
422
        $vars->count = $questionsincategory;
423
        echo $OUTPUT->box(get_string('categorymove', 'question', $vars), 'generalbox boxaligncenter');
424
        $this->moveform->display();
425
    }
426
 
427
    /**
428
     * Move questions to another category.
429
     *
430
     * @param int $oldcat id of the old category.
431
     * @param int $newcat id of the new category.
432
     * @throws \dml_exception
1441 ariadna 433
     * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager instead.
434
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 435
     */
1441 ariadna 436
    #[\core\attribute\deprecated(
437
        '\core_question\category_manager::move_questions',
438
        since: 4.5,
439
        reason: 'API properly divided between qbank_managecategories and core_question',
440
        mdl: 'MDL-72397',
441
    )]
1 efrain 442
    public function move_questions(int $oldcat, int $newcat): void {
1441 ariadna 443
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 444
        $questionids = $this->get_real_question_ids_in_category($oldcat);
445
        question_move_questions_to_category($questionids, $newcat);
446
    }
447
 
448
    /**
449
     * Create a new category.
450
     *
451
     * Data is expected to come from question_category_edit_form.
452
     *
453
     * By default redirects on success, unless $return is true.
454
     *
455
     * @param string $newparent 'categoryid,contextid' of the parent category.
456
     * @param string $newcategory the name.
457
     * @param string $newinfo the description.
458
     * @param bool $return if true, return rather than redirecting.
459
     * @param int|string $newinfoformat description format. One of the FORMAT_ constants.
460
     * @param null $idnumber the idnumber. '' is converted to null.
461
     * @return bool|int New category id if successful, else false.
1441 ariadna 462
     * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager instead.
463
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 464
     */
1441 ariadna 465
    #[\core\attribute\deprecated(
466
        '\core_question\category_manager::add_category',
467
        since: 4.5,
468
        reason: 'API properly divided between qbank_managecategories and core_question',
469
        mdl: 'MDL-72397',
470
    )]
1 efrain 471
    public function add_category($newparent, $newcategory, $newinfo, $return = false, $newinfoformat = FORMAT_HTML,
472
            $idnumber = null): int {
1441 ariadna 473
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 474
        global $DB;
475
        if (empty($newcategory)) {
476
            throw new moodle_exception('categorynamecantbeblank', 'question');
477
        }
478
        list($parentid, $contextid) = explode(',', $newparent);
479
        // ...moodle_form makes sure select element output is legal no need for further cleaning.
480
        require_capability('moodle/question:managecategory', context::instance_by_id($contextid));
481
 
482
        if ($parentid) {
483
            if (!($DB->get_field('question_categories', 'contextid', ['id' => $parentid]) == $contextid)) {
484
                throw new moodle_exception('cannotinsertquestioncatecontext', 'question', '',
485
                    ['cat' => $newcategory, 'ctx' => $contextid]);
486
            }
487
        }
488
 
489
        if ((string) $idnumber === '') {
490
            $idnumber = null;
491
        } else if (!empty($contextid)) {
492
            // While this check already exists in the form validation, this is a backstop preventing unnecessary errors.
493
            if ($DB->record_exists('question_categories',
494
                    ['idnumber' => $idnumber, 'contextid' => $contextid])) {
495
                $idnumber = null;
496
            }
497
        }
498
 
499
        $cat = new stdClass();
500
        $cat->parent = $parentid;
501
        $cat->contextid = $contextid;
502
        $cat->name = $newcategory;
503
        $cat->info = $newinfo;
504
        $cat->infoformat = $newinfoformat;
505
        $cat->sortorder = 999;
506
        $cat->stamp = make_unique_id_code();
507
        $cat->idnumber = $idnumber;
508
        $categoryid = $DB->insert_record("question_categories", $cat);
509
 
510
        // Log the creation of this category.
511
        $category = new stdClass();
512
        $category->id = $categoryid;
513
        $category->contextid = $contextid;
514
        $event = \core\event\question_category_created::create_from_question_category_instance($category);
515
        $event->trigger();
516
 
517
        if ($return) {
518
            return $categoryid;
519
        } else {
520
            // Always redirect after successful action.
521
            redirect($this->pageurl);
522
        }
523
    }
524
 
525
    /**
526
     * Updates an existing category with given params.
527
     *
528
     * Warning! parameter order and meaning confusingly different from add_category in some ways!
529
     *
530
     * @param int $updateid id of the category to update.
531
     * @param int $newparent 'categoryid,contextid' of the parent category to set.
532
     * @param string $newname category name.
533
     * @param string $newinfo category description.
534
     * @param int|string $newinfoformat description format. One of the FORMAT_ constants.
535
     * @param int $idnumber the idnumber. '' is converted to null.
536
     * @param bool $redirect if true, will redirect once the DB is updated (default).
1441 ariadna 537
     * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager instead.
538
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 539
     */
1441 ariadna 540
    #[\core\attribute\deprecated(
541
        '\core_question\category_manager::update_category',
542
        since: 4.5,
543
        reason: 'API properly divided between qbank_managecategories and core_question',
544
        mdl: 'MDL-72397',
545
    )]
1 efrain 546
    public function update_category($updateid, $newparent, $newname, $newinfo, $newinfoformat = FORMAT_HTML,
547
            $idnumber = null, $redirect = true): void {
1441 ariadna 548
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 549
        global $CFG, $DB;
550
        if (empty($newname)) {
551
            throw new moodle_exception('categorynamecantbeblank', 'question');
552
        }
553
 
554
        // Get the record we are updating.
555
        $oldcat = $DB->get_record('question_categories', ['id' => $updateid]);
556
        $lastcategoryinthiscontext = helper::question_is_only_child_of_top_category_in_context($updateid);
557
 
558
        if (!empty($newparent) && !$lastcategoryinthiscontext) {
559
            list($parentid, $tocontextid) = explode(',', $newparent);
560
        } else {
561
            $parentid = $oldcat->parent;
562
            $tocontextid = $oldcat->contextid;
563
        }
564
 
565
        // Check permissions.
566
        $fromcontext = context::instance_by_id($oldcat->contextid);
567
        require_capability('moodle/question:managecategory', $fromcontext);
568
 
569
        // If moving to another context, check permissions some more, and confirm contextid,stamp uniqueness.
570
        $newstamprequired = false;
571
        if ($oldcat->contextid != $tocontextid) {
572
            $tocontext = context::instance_by_id($tocontextid);
573
            require_capability('moodle/question:managecategory', $tocontext);
574
 
575
            // Confirm stamp uniqueness in the new context. If the stamp already exists, generate a new one.
576
            if ($DB->record_exists('question_categories', ['contextid' => $tocontextid, 'stamp' => $oldcat->stamp])) {
577
                $newstamprequired = true;
578
            }
579
        }
580
 
581
        if ((string) $idnumber === '') {
582
            $idnumber = null;
583
        } else if (!empty($tocontextid)) {
584
            // While this check already exists in the form validation, this is a backstop preventing unnecessary errors.
585
            if ($DB->record_exists_select('question_categories',
586
                    'idnumber = ? AND contextid = ? AND id <> ?',
587
                    [$idnumber, $tocontextid, $updateid])) {
588
                $idnumber = null;
589
            }
590
        }
591
 
592
        // Update the category record.
593
        $cat = new stdClass();
594
        $cat->id = $updateid;
595
        $cat->name = $newname;
596
        $cat->info = $newinfo;
597
        $cat->infoformat = $newinfoformat;
598
        $cat->parent = $parentid;
599
        $cat->contextid = $tocontextid;
600
        $cat->idnumber = $idnumber;
601
        if ($newstamprequired) {
602
            $cat->stamp = make_unique_id_code();
603
        }
604
        $DB->update_record('question_categories', $cat);
605
        // Update the set_reference records when moving a category to a different context.
606
        move_question_set_references($cat->id, $cat->id, $oldcat->contextid, $tocontextid);
607
 
608
        // Log the update of this category.
609
        $event = \core\event\question_category_updated::create_from_question_category_instance($cat);
610
        $event->trigger();
611
 
612
        if ($oldcat->contextid != $tocontextid) {
613
            // Moving to a new context. Must move files belonging to questions.
614
            question_move_category_to_context($cat->id, $oldcat->contextid, $tocontextid);
615
        }
616
 
617
        // Cat param depends on the context id, so update it.
618
        $this->pageurl->param('cat', $updateid . ',' . $tocontextid);
619
        if ($redirect) {
620
            // Always redirect after successful action.
621
            redirect($this->pageurl);
622
        }
623
    }
624
 
625
    /**
626
     * Returns ids of the question in the given question category.
627
     *
628
     * This method only returns the real question. It does not include
629
     * subquestions of question types like multianswer.
630
     *
631
     * @param int $categoryid id of the category.
632
     * @return int[] array of question ids.
1441 ariadna 633
     * @deprecated Since Moodle 4.5 MDL-72397. Use \core_question\category_manager instead.
634
     * @todo Final removal in Moodle 6.0 MDL-80804
1 efrain 635
     */
1441 ariadna 636
    #[\core\attribute\deprecated(
637
        '\core_question\category_manager::get_real_question_ids_in_category',
638
        since: 4.5,
639
        reason: 'API properly divided between qbank_managecategories and core_question',
640
        mdl: 'MDL-72397',
641
    )]
1 efrain 642
    public function get_real_question_ids_in_category(int $categoryid): array {
1441 ariadna 643
        \core\deprecation::emit_deprecation([$this, __FUNCTION__]);
1 efrain 644
        global $DB;
645
 
646
        $sql = "SELECT q.id
647
                  FROM {question} q
648
                  JOIN {question_versions} qv ON qv.questionid = q.id
649
                  JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
650
                 WHERE qbe.questioncategoryid = :categoryid
651
                   AND (q.parent = 0 OR q.parent = q.id)";
652
 
653
        $questionids = $DB->get_records_sql($sql, ['categoryid' => $categoryid]);
654
        return array_keys($questionids);
655
    }
656
}