on-demand release 4.5dev+
[moodle.git] / backup / util / ui / restore_ui_components.php
blob9b165d3be307e2b31946189ae562671d1b2cba23
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.
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/>.
17 /**
18 * This file contains components used by the restore UI
20 * @package core_backup
21 * @copyright 2010 Sam Hemelryk
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 /**
26 * A base class that can be used to build a specific search upon
28 * @package core_backup
29 * @copyright 2010 Sam Hemelryk
30 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 abstract class restore_search_base implements renderable {
34 /**
35 * The default values for this components params
37 const DEFAULT_SEARCH = '';
39 /**
40 * The param used to convey the current search string
41 * @var string
43 static $VAR_SEARCH = 'search';
45 /**
46 * The current search string
47 * @var string|null
49 private $search = null;
50 /**
51 * The URL for this page including required params to return to it
52 * @var moodle_url
54 private $url = null;
55 /**
56 * The results of the search
57 * @var array|null
59 private $results = null;
60 /**
61 * The total number of results available
62 * @var int
64 private $totalcount = null;
65 /**
66 * Array of capabilities required for each item in the search
67 * @var array
69 private $requiredcapabilities = array();
70 /**
71 * Max number of courses to return in a search.
72 * @var int
74 private $maxresults = null;
75 /**
76 * Indicates if we have more than maxresults found.
77 * @var boolean
79 private $hasmoreresults = false;
81 /**
82 * Constructor
83 * @param array $config Config options
85 public function __construct(array $config = array()) {
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');
91 foreach ($config as $name => $value) {
92 $method = 'set_'.$name;
93 if (method_exists($this, $method)) {
94 $this->$method($value);
99 /**
100 * The URL for this search
101 * @global moodle_page $PAGE
102 * @return moodle_url The URL for this page
104 final public function get_url() {
105 global $PAGE;
106 $params = array(
107 $this->get_varsearch() => $this->get_search()
109 return ($this->url !== null) ? new moodle_url($this->url, $params) : new moodle_url($PAGE->url, $params);
113 * The current search string
114 * @return string
116 final public function get_search() {
117 return ($this->search !== null) ? $this->search : self::DEFAULT_SEARCH;
121 * The total number of results
122 * @return int
124 final public function get_count() {
125 if ($this->totalcount === null) {
126 $this->search();
128 return $this->totalcount;
132 * Returns an array of results from the search
133 * @return array
135 final public function get_results() {
136 if ($this->results === null) {
137 $this->search();
139 return $this->results;
143 * Sets the page URL
144 * @param moodle_url $url
146 final public function set_url(moodle_url $url) {
147 $this->url = $url;
151 * Invalidates the results collected so far
153 final public function invalidate_results() {
154 $this->results = null;
155 $this->totalcount = null;
159 * Adds a required capability which all results will be checked against
160 * @param string $capability
161 * @param int|null $user
163 final public function require_capability($capability, $user = null) {
164 if (!is_int($user)) {
165 $user = null;
167 $this->requiredcapabilities[] = array(
168 'capability' => $capability,
169 'user' => $user
174 * Executes the search
176 * @global moodle_database $DB
177 * @return int The number of results
179 final public function search() {
180 global $DB;
181 if (!is_null($this->results)) {
182 return $this->results;
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'];
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;
212 // Check if we are over the limit.
213 if ($this->totalcount + 1 > $this->maxresults) {
214 $this->hasmoreresults = true;
215 break;
217 // If not, then continue.
218 $this->totalcount++;
219 $this->results[$result->id] = $result;
221 $resultset->close();
224 return $this->totalcount;
228 * Returns true if there are more search results.
229 * @return bool
231 final public function has_more_results() {
232 if ($this->results === null) {
233 $this->search();
235 return $this->hasmoreresults;
239 * Returns an array containing the SQL for the search and the params
240 * @return array
242 abstract protected function get_searchsql();
245 * Gets the context level associated with this components items
246 * @return CONTEXT_*
248 abstract protected function get_itemcontextlevel();
251 * Formats the results
253 abstract protected function format_results();
256 * Gets the string used to transfer the search string for this compontents requests
257 * @return string
259 abstract public function get_varsearch();
263 * A course search component
265 * @package core_backup
266 * @copyright 2010 Sam Hemelryk
267 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
269 class restore_course_search extends restore_search_base {
272 * @var string
274 static $VAR_SEARCH = 'search';
277 * The current course id.
278 * @var int
280 protected $currentcourseid = null;
283 * Determines if the current course is included in the results.
284 * @var bool
286 protected $includecurrentcourse;
289 * Constructor
290 * @param array $config
291 * @param int $currentcouseid The current course id so it can be ignored
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;
301 * Sets up any access restrictions for the courses to be displayed in the search.
303 * This will typically call $this->require_capability().
305 protected function setup_restrictions() {
306 $this->require_capability('moodle/restore:restorecourse');
310 * Get the search SQL.
311 * @global moodle_database $DB
312 * @return array
314 protected function get_searchsql() {
315 global $DB;
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().'%'
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";
331 if ($this->currentcourseid !== null && !$this->includecurrentcourse) {
332 $where .= " AND c.id <> :currentcourseid";
333 $params['currentcourseid'] = $this->currentcourseid;
336 return array($select.$ctxselect.$from.$ctxjoin.$where.$orderby, $params);
340 * Gets the context level for the search result items.
341 * @return CONTEXT_|int
343 protected function get_itemcontextlevel() {
344 return CONTEXT_COURSE;
348 * Formats results.
350 protected function format_results() {}
353 * Returns the name the search variable should use
354 * @return string
356 public function get_varsearch() {
357 return self::$VAR_SEARCH;
361 * Returns true if the current course should be included in the results.
363 public function set_include_currentcourse() {
364 $this->includecurrentcourse = true;
368 * Get the current course id
370 * @return int
372 public function get_current_course_id(): int {
373 return $this->currentcourseid;
378 * A category search component
380 * @package core_backup
381 * @copyright 2010 Sam Hemelryk
382 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
384 class restore_category_search extends restore_search_base {
387 * The search variable to use.
388 * @var string
390 static $VAR_SEARCH = 'catsearch';
393 * Constructor
394 * @param array $config
396 public function __construct(array $config = array()) {
397 parent::__construct($config);
398 $this->require_capability('moodle/course:create');
401 * Returns the search SQL.
402 * @global moodle_database $DB
403 * @return array
405 protected function get_searchsql() {
406 global $DB;
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().'%',
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";
420 return array($select.$ctxselect.$from.$ctxjoin.$where.$orderby, $params);
424 * Returns the context level of the search results.
425 * @return CONTEXT_COURSECAT
427 protected function get_itemcontextlevel() {
428 return CONTEXT_COURSECAT;
432 * Formats the results.
434 protected function format_results() {}
437 * Returns the name to use for the search variable.
438 * @return string
440 public function get_varsearch() {
441 return self::$VAR_SEARCH;