See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 403]
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 /** 369 * A category search component 370 * 371 * @package core_backup 372 * @copyright 2010 Sam Hemelryk 373 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 374 */ 375 class restore_category_search extends restore_search_base { 376 377 /** 378 * The search variable to use. 379 * @var string 380 */ 381 static $VAR_SEARCH = 'catsearch'; 382 383 /** 384 * Constructor 385 * @param array $config 386 */ 387 public function __construct(array $config = array()) { 388 parent::__construct($config); 389 $this->require_capability('moodle/course:create'); 390 } 391 /** 392 * Returns the search SQL. 393 * @global moodle_database $DB 394 * @return array 395 */ 396 protected function get_searchsql() { 397 global $DB; 398 399 $ctxselect = ', ' . context_helper::get_preload_record_columns_sql('ctx'); 400 $ctxjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)"; 401 $params = array( 402 'contextlevel' => CONTEXT_COURSECAT, 403 'namesearch' => '%'.$this->get_search().'%', 404 ); 405 406 $select = " SELECT c.id, c.name, c.visible, c.sortorder, c.description, c.descriptionformat "; 407 $from = " FROM {course_categories} c "; 408 $where = " WHERE ".$DB->sql_like('c.name', ':namesearch', false); 409 $orderby = " ORDER BY c.sortorder"; 410 411 return array($select.$ctxselect.$from.$ctxjoin.$where.$orderby, $params); 412 } 413 414 /** 415 * Returns the context level of the search results. 416 * @return CONTEXT_COURSECAT 417 */ 418 protected function get_itemcontextlevel() { 419 return CONTEXT_COURSECAT; 420 } 421 422 /** 423 * Formats the results. 424 */ 425 protected function format_results() {} 426 427 /** 428 * Returns the name to use for the search variable. 429 * @return string 430 */ 431 public function get_varsearch() { 432 return self::$VAR_SEARCH; 433 } 434 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body