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
use core\output\datafilter;
20
use core_question\local\bank\condition;
21
use core_question\local\bank\view;
22
 
23
/**
24
 * This class controls from which category questions are listed.
25
 *
26
 * @package   qbank_managecategories
27
 * @copyright 2013 Ray Morris
28
 * @author    2021 Safat Shahin <safatshahin@catalyst-au.net>
29
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 */
31
class category_condition extends condition {
32
    /** @var \stdClass The course record. */
33
    protected $course;
34
 
1441 ariadna 35
    /** @var \stdClass The course_modules record. */
36
    protected \stdClass $cm;
37
 
1 efrain 38
    /** @var \stdClass The category record. */
39
    protected $category;
40
 
41
    /** @var array of contexts. */
42
    protected $contexts;
43
 
44
    /** @var string categoryID,contextID as used with question_bank_view->display(). */
45
    protected $cat;
46
 
47
    /** @var int The maximum displayed length of the category info. */
48
    public $maxinfolength;
49
 
50
    /** @var bool Include questions in subcategories of the specified category? */
51
    public $includesubcategories;
52
 
53
    /**
54
     * Constructor to initialize the category filter condition.
55
     *
56
     * @param view $qbank qbank view
57
     */
1441 ariadna 58
    public function __construct(?view $qbank = null) {
1 efrain 59
        if (is_null($qbank)) {
60
            return;
61
        }
62
        $this->cat = $qbank->get_pagevars('cat');
1441 ariadna 63
        $this->contexts = array_filter($qbank->contexts->having_one_edit_tab_cap($qbank->get_pagevars('tabname')),
64
            static fn($context) => $context->contextlevel === CONTEXT_MODULE
65
        );
1 efrain 66
        $this->course = $qbank->course;
1441 ariadna 67
        $this->cm = $qbank->cm;
1 efrain 68
 
69
        [$categoryid, $contextid] = self::validate_category_param($this->cat);
70
        if (is_null($categoryid)) {
71
            return;
72
        }
73
 
74
        $this->category = self::get_category_record($categoryid, $contextid);
75
 
76
        parent::__construct($qbank);
1441 ariadna 77
        if (isset($this->filter['filteroptions']['includesubcategories'])) {
78
            set_user_preference('qbank_managecategories_includesubcategories_filter_default',
79
                $this->filter['filteroptions']['includesubcategories']);
80
        }
81
        $this->includesubcategories = $this->filter['filteroptions']['includesubcategories'] ??
82
            get_user_preferences('qbank_managecategories_includesubcategories_filter_default', false);
1 efrain 83
    }
84
 
85
    /**
86
     * Return default category
87
     *
88
     * @return \stdClass default category
89
     */
90
    public function get_default_category(): \stdClass {
91
        if (empty($this->category)) {
1441 ariadna 92
            return question_get_default_category(\context_module::instance($this->cm->id)->id, true);
1 efrain 93
        }
94
 
95
        return $this->category;
96
    }
97
 
98
    public static function get_condition_key() {
99
        return 'category';
100
    }
101
 
102
    /**
103
     * Returns course id.
104
     *
105
     * @return string Course id.
106
     */
107
    public function get_course_id() {
108
        return $this->course->id;
109
    }
110
 
111
    /**
112
     * @deprecated since Moodle 4.3 MDL-72321 - please do not use this function any more.
113
     */
1441 ariadna 114
    #[\core\attribute\deprecated('filtering objects', since: '4.3', mdl: 'MDL-72321', final: true)]
1 efrain 115
    public function display_options() {
1441 ariadna 116
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 117
    }
118
 
119
    /**
120
     * @deprecated since Moodle 4.3 MDL-72321 - please do not use this function any more.
121
     */
1441 ariadna 122
    #[\core\attribute\deprecated('foobar::blah()', since: '4.3', mdl: 'MDL-72321', final: true)]
1 efrain 123
    public function display_options_adv() {
1441 ariadna 124
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 125
    }
126
 
127
    /**
128
     * @deprecated since Moodle 4.3
129
     */
1441 ariadna 130
    #[\core\attribute\deprecated('core_question renderer', since: '4.3', mdl: 'MDL-72321', final: true)]
1 efrain 131
    protected function display_category_form($contexts, $pageurl, $current) {
1441 ariadna 132
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 133
    }
134
 
135
    /**
136
     * @deprecated since Moodle 4.3
137
     */
1441 ariadna 138
    #[\core\attribute\deprecated('qbank_managecategories/choose_category template', since: '4.3', mdl: 'MDL-72321', final: true)]
1 efrain 139
    public static function print_choose_category_message(): void {
1441 ariadna 140
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 141
    }
142
 
143
    /**
144
     * @deprecated since Moodle 4.3
145
     */
1441 ariadna 146
    #[\core\attribute\deprecated(null, since: '4.3', mdl: 'MDL-72321', final: true)]
1 efrain 147
    public static function get_current_category($categoryandcontext) {
1441 ariadna 148
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 149
    }
150
 
151
    /**
152
     * Return category and context ID from compound parameter.
153
     *
154
     * @param string $categoryandcontext Comma-separated list of category and context IDs.
155
     * @return int[]|null[]
156
     */
157
    public static function validate_category_param(string $categoryandcontext): array {
158
        [$categoryid, $contextid] = explode(',', $categoryandcontext);
159
        if (!$categoryid) {
160
            return [null, null];
161
        }
162
        return [clean_param($categoryid, PARAM_INT), clean_param($contextid, PARAM_INT)];
163
    }
164
 
165
    /**
166
     * Fetch the question category record matching the provided category and context IDs.
167
     *
168
     * @param int $categoryid
169
     * @param int $contextid
170
     * @return \stdClass
171
     * @throws \dml_exception
172
     */
173
    public static function get_category_record($categoryid, $contextid): \stdClass {
174
        global $DB;
175
        return $DB->get_record('question_categories',
176
                ['id' => $categoryid, 'contextid' => $contextid],
177
                '*',
178
                MUST_EXIST);
179
    }
180
 
181
    /**
182
     * @deprecated since Moodle 4.3 MDL-72321 - please do not use this function any more.
183
     */
1441 ariadna 184
    #[\core\attribute\deprecated(null, since: '4.3', mdl: 'MDL-72321', final: true)]
1 efrain 185
    protected function print_category_info($category): string {
1441 ariadna 186
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 187
    }
188
 
189
    public static function build_query_from_filter(array $filter): array {
190
        global $DB;
191
        $recursive = false;
192
        if (isset($filter['filteroptions']['includesubcategories'])) {
193
            $recursive = (bool)$filter['filteroptions']['includesubcategories'];
194
        }
195
 
196
        // Sub categories.
197
        if ($recursive) {
198
            $categories = $filter['values'];
199
            $categoriesandsubcategories = [];
200
            foreach ($categories as $categoryid) {
201
                $categoriesandsubcategories += question_categorylist($categoryid);
202
            }
203
        } else {
204
            $categoriesandsubcategories = $filter['values'];
205
        }
206
 
207
        $jointype = $filter['jointype'] ?? self::JOINTYPE_DEFAULT;
208
        $equal = !($jointype === datafilter::JOINTYPE_NONE);
209
        [$insql, $params] = $DB->get_in_or_equal($categoriesandsubcategories, SQL_PARAMS_NAMED, 'cat', $equal);
210
        $where = 'qbe.questioncategoryid ' . $insql;
211
        return [$where, $params];
212
    }
213
 
214
    public function get_title() {
215
        return get_string('category', 'core_question');
216
    }
217
 
218
    public function get_filter_class() {
219
        return 'qbank_managecategories/datafilter/filtertypes/categories';
220
    }
221
 
222
    public function allow_custom() {
223
        return false;
224
    }
225
 
226
    public function allow_multiple() {
227
        return false;
228
    }
229
 
230
    public function allow_empty() {
231
        return false;
232
    }
233
 
234
    public function get_join_list(): array {
235
        return [
236
                datafilter::JOINTYPE_ANY,
237
        ];
238
    }
239
 
240
    public function get_initial_values() {
241
        $catmenu = helper::question_category_options($this->contexts, true, 0, true, -1, false);
242
        $values = [];
243
        foreach ($catmenu as $menu) {
244
            foreach ($menu as $heading => $catlist) {
245
                $values[] = (object) [
246
                    // Add a list item for each question category context. This will serve as a "heading" within the list
247
                    // and we will use CSS to disable pointer events so it cannot be selected.
248
                    'value' => '',
249
                    'title' => $heading,
250
                    'disabled' => true,
251
                    'classes' => 'suggestions-heading',
252
                ];
253
                foreach ($catlist as $key => $value) {
254
                    $values[] = (object) [
255
                        // Remove contextid from value.
256
                        'value' => str_contains($key, ',') ? substr($key, 0, strpos($key, ',')) : $key,
257
                        'title' => $value,
258
                        'selected' => ($key === $this->cat),
259
                    ];
260
                }
261
            }
262
        }
263
        return $values;
264
    }
265
 
266
    public function get_filteroptions(): \stdClass {
267
        return (object)[
268
            'includesubcategories' => $this->includesubcategories,
269
        ];
270
    }
271
 
272
    public function is_required(): bool {
273
        return true;
274
    }
1441 ariadna 275
 
276
    #[\Override]
277
    public function filter_invalid_values(array $filterconditions): array {
278
 
279
        global $DB;
280
 
281
        $defaultcatid = explode(',', $filterconditions['cat'])[0];
282
 
283
        [$insql, $inparams] = $DB->get_in_or_equal($filterconditions['filter']['category']['values']);
284
        $categories = $DB->get_records_select('question_categories', "id {$insql}",
285
            $inparams, null, 'id');
286
        $categoryids = array_keys($categories);
287
 
288
        foreach ($filterconditions['filter']['category']['values'] as $key => $catid) {
289
 
290
            // Check that the category still exists, and if not, remove it from the conditions.
291
            if (!in_array($catid, $categoryids)) {
292
                unset($filterconditions['filter']['category']['values'][$key]);
293
            }
294
 
295
        }
296
 
297
        // If we now don't have any valid categories, use the default loaded from the page.
298
        if (count($filterconditions['filter']['category']['values']) === 0) {
299
            $filterconditions['filter']['category']['values'] = [$defaultcatid];
300
        }
301
 
302
        return $filterconditions;
303
 
304
    }
305
 
1 efrain 306
}