Proyectos de Subversion Moodle

Rev

| 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
/**
18
 * This file contains components used by the restore UI
19
 *
20
 * @package   core_backup
21
 * @copyright 2010 Sam Hemelryk
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
/**
26
 * A base class that can be used to build a specific search upon
27
 *
28
 * @package   core_backup
29
 * @copyright 2010 Sam Hemelryk
30
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31
 */
32
abstract class restore_search_base implements renderable {
33
 
34
    /**
35
     * The default values for this components params
36
     */
37
    const DEFAULT_SEARCH = '';
38
 
39
    /**
40
     * The param used to convey the current search string
41
     * @var string
42
     */
43
    static $VAR_SEARCH = 'search';
44
 
45
    /**
46
     * The current search string
47
     * @var string|null
48
     */
49
    private $search = null;
50
    /**
51
     * The URL for this page including required params to return to it
52
     * @var moodle_url
53
     */
54
    private $url = null;
55
    /**
56
     * The results of the search
57
     * @var array|null
58
     */
59
    private $results = null;
60
    /**
61
     * The total number of results available
62
     * @var int
63
     */
64
    private $totalcount = null;
65
    /**
66
     * Array of capabilities required for each item in the search
67
     * @var array
68
     */
69
    private $requiredcapabilities = array();
70
    /**
71
     * Max number of courses to return in a search.
72
     * @var int
73
     */
74
    private $maxresults = null;
75
    /**
76
     * Indicates if we have more than maxresults found.
77
     * @var boolean
78
     */
79
    private $hasmoreresults = false;
80
 
81
    /**
82
     * Constructor
83
     * @param array $config Config options
84
     */
85
    public function __construct(array $config = array()) {
86
 
87
        $this->search = optional_param($this->get_varsearch(), self::DEFAULT_SEARCH, PARAM_NOTAGS);
88
        $this->search = trim($this->search);
89
        $this->maxresults = get_config('backup', 'import_general_maxresults');
90
 
91
        foreach ($config as $name => $value) {
92
            $method = 'set_'.$name;
93
            if (method_exists($this, $method)) {
94
                $this->$method($value);
95
            }
96
        }
97
    }
98
 
99
    /**
100
     * The URL for this search
101
     * @global moodle_page $PAGE
102
     * @return moodle_url The URL for this page
103
     */
104
    final public function get_url() {
105
        global $PAGE;
106
        $params = array(
107
            $this->get_varsearch()    => $this->get_search()
108
        );
109
        return ($this->url !== null) ? new moodle_url($this->url, $params) : new moodle_url($PAGE->url, $params);
110
    }
111
 
112
    /**
113
     * The current search string
114
     * @return string
115
     */
116
    final public function get_search() {
117
        return ($this->search !== null) ? $this->search : self::DEFAULT_SEARCH;
118
    }
119
 
120
    /**
121
     * The total number of results
122
     * @return int
123
     */
124
    final public function get_count() {
125
        if ($this->totalcount === null) {
126
            $this->search();
127
        }
128
        return $this->totalcount;
129
    }
130
 
131
    /**
132
     * Returns an array of results from the search
133
     * @return array
134
     */
135
    final public function get_results() {
136
        if ($this->results === null) {
137
            $this->search();
138
        }
139
        return $this->results;
140
    }
141
 
142
    /**
143
     * Sets the page URL
144
     * @param moodle_url $url
145
     */
146
    final public function set_url(moodle_url $url) {
147
        $this->url = $url;
148
    }
149
 
150
    /**
151
     * Invalidates the results collected so far
152
     */
153
    final public function invalidate_results() {
154
        $this->results = null;
155
        $this->totalcount = null;
156
    }
157
 
158
    /**
159
     * Adds a required capability which all results will be checked against
160
     * @param string $capability
161
     * @param int|null $user
162
     */
163
    final public function require_capability($capability, $user = null) {
164
        if (!is_int($user)) {
165
            $user = null;
166
        }
167
        $this->requiredcapabilities[] = array(
168
            'capability' => $capability,
169
            'user' => $user
170
        );
171
    }
172
 
173
    /**
174
     * Executes the search
175
     *
176
     * @global moodle_database $DB
177
     * @return int The number of results
178
     */
179
    final public function search() {
180
        global $DB;
181
        if (!is_null($this->results)) {
182
            return $this->results;
183
        }
184
 
185
        $this->results = array();
186
        $this->totalcount = 0;
187
        $contextlevel = $this->get_itemcontextlevel();
188
        list($sql, $params) = $this->get_searchsql();
189
        // Get total number, to avoid some incorrect iterations.
190
        $countsql = preg_replace('/ORDER BY.*/', '', $sql);
191
        $totalcourses = $DB->count_records_sql("SELECT COUNT(*) FROM ($countsql) sel", $params);
192
        if ($totalcourses > 0) {
193
            // User to be checked is always the same (usually null, get it from first element).
194
            $firstcap = reset($this->requiredcapabilities);
195
            $userid = isset($firstcap['user']) ? $firstcap['user'] : null;
196
            // Extract caps to check, this saves us a bunch of iterations.
197
            $requiredcaps = array();
198
            foreach ($this->requiredcapabilities as $cap) {
199
                $requiredcaps[] = $cap['capability'];
200
            }
201
            // Iterate while we have records and haven't reached $this->maxresults.
202
            $resultset = $DB->get_recordset_sql($sql, $params);
203
            foreach ($resultset as $result) {
204
                context_helper::preload_from_record($result);
205
                $classname = context_helper::get_class_for_level($contextlevel);
206
                $context = $classname::instance($result->id);
207
                if (count($requiredcaps) > 0) {
208
                    if (!has_all_capabilities($requiredcaps, $context, $userid)) {
209
                        continue;
210
                    }
211
                }
212
                // Check if we are over the limit.
213
                if ($this->totalcount + 1 > $this->maxresults) {
214
                    $this->hasmoreresults = true;
215
                    break;
216
                }
217
                // If not, then continue.
218
                $this->totalcount++;
219
                $this->results[$result->id] = $result;
220
            }
221
            $resultset->close();
222
        }
223
 
224
        return $this->totalcount;
225
    }
226
 
227
    /**
228
     * Returns true if there are more search results.
229
     * @return bool
230
     */
231
    final public function has_more_results() {
232
        if ($this->results === null) {
233
            $this->search();
234
        }
235
        return $this->hasmoreresults;
236
    }
237
 
238
    /**
239
     * Returns an array containing the SQL for the search and the params
240
     * @return array
241
     */
242
    abstract protected function get_searchsql();
243
 
244
    /**
245
     * Gets the context level associated with this components items
246
     * @return CONTEXT_*
247
     */
248
    abstract protected function get_itemcontextlevel();
249
 
250
    /**
251
     * Formats the results
252
     */
253
    abstract protected function format_results();
254
 
255
    /**
256
     * Gets the string used to transfer the search string for this compontents requests
257
     * @return string
258
     */
259
    abstract public function get_varsearch();
260
}
261
 
262
/**
263
 * A course search component
264
 *
265
 * @package   core_backup
266
 * @copyright 2010 Sam Hemelryk
267
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
268
 */
269
class restore_course_search extends restore_search_base {
270
 
271
    /**
272
     * @var string
273
     */
274
    static $VAR_SEARCH = 'search';
275
 
276
    /**
277
     * The current course id.
278
     * @var int
279
     */
280
    protected $currentcourseid = null;
281
 
282
    /**
283
     * Determines if the current course is included in the results.
284
     * @var bool
285
     */
286
    protected $includecurrentcourse;
287
 
288
    /**
289
     * Constructor
290
     * @param array $config
291
     * @param int $currentcouseid The current course id so it can be ignored
292
     */
293
    public function __construct(array $config = array(), $currentcouseid = null) {
294
        parent::__construct($config);
295
        $this->setup_restrictions();
296
        $this->currentcourseid = $currentcouseid;
297
        $this->includecurrentcourse = false;
298
    }
299
 
300
    /**
301
     * Sets up any access restrictions for the courses to be displayed in the search.
302
     *
303
     * This will typically call $this->require_capability().
304
     */
305
    protected function setup_restrictions() {
306
        $this->require_capability('moodle/restore:restorecourse');
307
    }
308
 
309
    /**
310
     * Get the search SQL.
311
     * @global moodle_database $DB
312
     * @return array
313
     */
314
    protected function get_searchsql() {
315
        global $DB;
316
 
317
        $ctxselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
318
        $ctxjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
319
        $params = array(
320
            'contextlevel' => CONTEXT_COURSE,
321
            'fullnamesearch' => '%'.$this->get_search().'%',
322
            'shortnamesearch' => '%'.$this->get_search().'%'
323
        );
324
 
325
        $select     = " SELECT c.id, c.fullname, c.shortname, c.visible, c.sortorder ";
326
        $from       = " FROM {course} c ";
327
        $where      = " WHERE (".$DB->sql_like('c.fullname', ':fullnamesearch', false)." OR ".
328
            $DB->sql_like('c.shortname', ':shortnamesearch', false).")";
329
        $orderby    = " ORDER BY c.sortorder";
330
 
331
        if ($this->currentcourseid !== null && !$this->includecurrentcourse) {
332
            $where .= " AND c.id <> :currentcourseid";
333
            $params['currentcourseid'] = $this->currentcourseid;
334
        }
335
 
336
        return array($select.$ctxselect.$from.$ctxjoin.$where.$orderby, $params);
337
    }
338
 
339
    /**
340
     * Gets the context level for the search result items.
341
     * @return CONTEXT_|int
342
     */
343
    protected function get_itemcontextlevel() {
344
        return CONTEXT_COURSE;
345
    }
346
 
347
    /**
348
     * Formats results.
349
     */
350
    protected function format_results() {}
351
 
352
    /**
353
     * Returns the name the search variable should use
354
     * @return string
355
     */
356
    public function get_varsearch() {
357
        return self::$VAR_SEARCH;
358
    }
359
 
360
    /**
361
     * Returns true if the current course should be included in the results.
362
     */
363
    public function set_include_currentcourse() {
364
        $this->includecurrentcourse = true;
365
    }
366
 
367
    /**
368
     * Get the current course id
369
     *
370
     * @return int
371
     */
372
    public function get_current_course_id(): int {
373
        return $this->currentcourseid;
374
    }
375
}
376
 
377
/**
378
 * A category search component
379
 *
380
 * @package   core_backup
381
 * @copyright 2010 Sam Hemelryk
382
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
383
 */
384
class restore_category_search extends restore_search_base  {
385
 
386
    /**
387
     * The search variable to use.
388
     * @var string
389
     */
390
    static $VAR_SEARCH = 'catsearch';
391
 
392
    /**
393
     * Constructor
394
     * @param array $config
395
     */
396
    public function __construct(array $config = array()) {
397
        parent::__construct($config);
398
        $this->require_capability('moodle/course:create');
399
    }
400
    /**
401
     * Returns the search SQL.
402
     * @global moodle_database $DB
403
     * @return array
404
     */
405
    protected function get_searchsql() {
406
        global $DB;
407
 
408
        $ctxselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
409
        $ctxjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
410
        $params = array(
411
            'contextlevel' => CONTEXT_COURSECAT,
412
            'namesearch' => '%'.$this->get_search().'%',
413
        );
414
 
415
        $select     = " SELECT c.id, c.name, c.visible, c.sortorder, c.description, c.descriptionformat ";
416
        $from       = " FROM {course_categories} c ";
417
        $where      = " WHERE ".$DB->sql_like('c.name', ':namesearch', false);
418
        $orderby    = " ORDER BY c.sortorder";
419
 
420
        return array($select.$ctxselect.$from.$ctxjoin.$where.$orderby, $params);
421
    }
422
 
423
    /**
424
     * Returns the context level of the search results.
425
     * @return CONTEXT_COURSECAT
426
     */
427
    protected function get_itemcontextlevel() {
428
        return CONTEXT_COURSECAT;
429
    }
430
 
431
    /**
432
     * Formats the results.
433
     */
434
    protected function format_results() {}
435
 
436
    /**
437
     * Returns the name to use for the search variable.
438
     * @return string
439
     */
440
    public function get_varsearch() {
441
        return self::$VAR_SEARCH;
442
    }
443
}