[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 * File containing the helper class. 19 * 20 * @package tool_uploadcourse 21 * @copyright 2013 Frédéric Massart 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 require_once($CFG->libdir . '/coursecatlib.php'); 27 require_once($CFG->dirroot . '/cache/lib.php'); 28 require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); 29 require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); 30 31 /** 32 * Class containing a set of helpers. 33 * 34 * @package tool_uploadcourse 35 * @copyright 2013 Frédéric Massart 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class tool_uploadcourse_helper { 39 40 /** 41 * Generate a shortname based on a template. 42 * 43 * @param array|object $data course data. 44 * @param string $templateshortname template of shortname. 45 * @return null|string shortname based on the template, or null when an error occured. 46 */ 47 public static function generate_shortname($data, $templateshortname) { 48 if (empty($templateshortname) && !is_numeric($templateshortname)) { 49 return null; 50 } 51 if (strpos($templateshortname, '%') === false) { 52 return $templateshortname; 53 } 54 55 $course = (object) $data; 56 $fullname = isset($course->fullname) ? $course->fullname : ''; 57 $idnumber = isset($course->idnumber) ? $course->idnumber : ''; 58 59 $callback = partial(array('tool_uploadcourse_helper', 'generate_shortname_callback'), $fullname, $idnumber); 60 $result = preg_replace_callback('/(?<!%)%([+~-])?(\d)*([fi])/', $callback, $templateshortname); 61 62 if (!is_null($result)) { 63 $result = clean_param($result, PARAM_TEXT); 64 } 65 66 if (empty($result) && !is_numeric($result)) { 67 $result = null; 68 } 69 70 return $result; 71 } 72 73 /** 74 * Callback used when generating a shortname based on a template. 75 * 76 * @param string $fullname full name. 77 * @param string $idnumber ID number. 78 * @param array $block result from preg_replace_callback. 79 * @return string 80 */ 81 public static function generate_shortname_callback($fullname, $idnumber, $block) { 82 switch ($block[3]) { 83 case 'f': 84 $repl = $fullname; 85 break; 86 case 'i': 87 $repl = $idnumber; 88 break; 89 default: 90 return $block[0]; 91 } 92 93 switch ($block[1]) { 94 case '+': 95 $repl = core_text::strtoupper($repl); 96 break; 97 case '-': 98 $repl = core_text::strtolower($repl); 99 break; 100 case '~': 101 $repl = core_text::strtotitle($repl); 102 break; 103 } 104 105 if (!empty($block[2])) { 106 $repl = core_text::substr($repl, 0, $block[2]); 107 } 108 109 return $repl; 110 } 111 112 /** 113 * Return the available course formats. 114 * 115 * @return array 116 */ 117 public static function get_course_formats() { 118 return array_keys(core_component::get_plugin_list('format')); 119 } 120 121 /** 122 * Extract enrolment data from passed data. 123 * 124 * Constructs an array of methods, and their options: 125 * array( 126 * 'method1' => array( 127 * 'option1' => value, 128 * 'option2' => value 129 * ), 130 * 'method2' => array( 131 * 'option1' => value, 132 * 'option2' => value 133 * ) 134 * ) 135 * 136 * @param array $data data to extract the enrolment data from. 137 * @return array 138 */ 139 public static function get_enrolment_data($data) { 140 $enrolmethods = array(); 141 $enroloptions = array(); 142 foreach ($data as $field => $value) { 143 144 // Enrolmnent data. 145 $matches = array(); 146 if (preg_match('/^enrolment_(\d+)(_(.+))?$/', $field, $matches)) { 147 $key = $matches[1]; 148 if (!isset($enroloptions[$key])) { 149 $enroloptions[$key] = array(); 150 } 151 if (empty($matches[3])) { 152 $enrolmethods[$key] = $value; 153 } else { 154 $enroloptions[$key][$matches[3]] = $value; 155 } 156 } 157 } 158 159 // Combining enrolment methods and their options in a single array. 160 $enrolmentdata = array(); 161 if (!empty($enrolmethods)) { 162 $enrolmentplugins = self::get_enrolment_plugins(); 163 foreach ($enrolmethods as $key => $method) { 164 if (!array_key_exists($method, $enrolmentplugins)) { 165 // Error! 166 continue; 167 } 168 $enrolmentdata[$enrolmethods[$key]] = $enroloptions[$key]; 169 } 170 } 171 return $enrolmentdata; 172 } 173 174 /** 175 * Return the enrolment plugins. 176 * 177 * The result is cached for faster execution. 178 * 179 * @return array 180 */ 181 public static function get_enrolment_plugins() { 182 $cache = cache::make('tool_uploadcourse', 'helper'); 183 if (($enrol = $cache->get('enrol')) === false) { 184 $enrol = enrol_get_plugins(false); 185 $cache->set('enrol', $enrol); 186 } 187 return $enrol; 188 } 189 190 /** 191 * Get the restore content tempdir. 192 * 193 * The tempdir is the sub directory in which the backup has been extracted. 194 * 195 * This caches the result for better performance, but $CFG->keeptempdirectoriesonbackup 196 * needs to be enabled, otherwise the cache is ignored. 197 * 198 * @param string $backupfile path to a backup file. 199 * @param string $shortname shortname of a course. 200 * @param array $errors will be populated with errors found. 201 * @return string|false false when the backup couldn't retrieved. 202 */ 203 public static function get_restore_content_dir($backupfile = null, $shortname = null, &$errors = array()) { 204 global $CFG, $DB, $USER; 205 206 $cachekey = null; 207 if (!empty($backupfile)) { 208 $backupfile = realpath($backupfile); 209 if (empty($backupfile) || !is_readable($backupfile)) { 210 $errors['cannotreadbackupfile'] = new lang_string('cannotreadbackupfile', 'tool_uploadcourse'); 211 return false; 212 } 213 $cachekey = 'backup_path:' . $backupfile; 214 } else if (!empty($shortname) || is_numeric($shortname)) { 215 $cachekey = 'backup_sn:' . $shortname; 216 } 217 218 if (empty($cachekey)) { 219 return false; 220 } 221 222 // If $CFG->keeptempdirectoriesonbackup is not set to true, any restore happening would 223 // automatically delete the backup directory... causing the cache to return an unexisting directory. 224 $usecache = !empty($CFG->keeptempdirectoriesonbackup); 225 if ($usecache) { 226 $cache = cache::make('tool_uploadcourse', 'helper'); 227 } 228 229 // If we don't use the cache, or if we do and not set, or the directory doesn't exist any more. 230 if (!$usecache || (($backupid = $cache->get($cachekey)) === false || !is_dir("$CFG->tempdir/backup/$backupid"))) { 231 232 // Use null instead of false because it would consider that the cache key has not been set. 233 $backupid = null; 234 235 if (!empty($backupfile)) { 236 // Extracting the backup file. 237 $packer = get_file_packer('application/vnd.moodle.backup'); 238 $backupid = restore_controller::get_tempdir_name(SITEID, $USER->id); 239 $path = "$CFG->tempdir/backup/$backupid/"; 240 $result = $packer->extract_to_pathname($backupfile, $path); 241 if (!$result) { 242 $errors['invalidbackupfile'] = new lang_string('invalidbackupfile', 'tool_uploadcourse'); 243 } 244 } else if (!empty($shortname) || is_numeric($shortname)) { 245 // Creating restore from an existing course. 246 $courseid = $DB->get_field('course', 'id', array('shortname' => $shortname), IGNORE_MISSING); 247 if (!empty($courseid)) { 248 $bc = new backup_controller(backup::TYPE_1COURSE, $courseid, backup::FORMAT_MOODLE, 249 backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id); 250 $bc->execute_plan(); 251 $backupid = $bc->get_backupid(); 252 $bc->destroy(); 253 } else { 254 $errors['coursetorestorefromdoesnotexist'] = 255 new lang_string('coursetorestorefromdoesnotexist', 'tool_uploadcourse'); 256 } 257 } 258 259 if ($usecache) { 260 $cache->set($cachekey, $backupid); 261 } 262 } 263 264 if ($backupid === null) { 265 $backupid = false; 266 } 267 return $backupid; 268 } 269 270 /** 271 * Return the role IDs. 272 * 273 * The result is cached for faster execution. 274 * 275 * @return array 276 */ 277 public static function get_role_ids() { 278 $cache = cache::make('tool_uploadcourse', 'helper'); 279 if (($roles = $cache->get('roles')) === false) { 280 $roles = array(); 281 $rolesraw = get_all_roles(); 282 foreach ($rolesraw as $role) { 283 $roles[$role->shortname] = $role->id; 284 } 285 $cache->set('roles', $roles); 286 } 287 return $roles; 288 } 289 290 /** 291 * Get the role renaming data from the passed data. 292 * 293 * @param array $data data to extract the names from. 294 * @param array $errors will be populated with errors found. 295 * @return array where the key is the role_<id>, the value is the new name. 296 */ 297 public static function get_role_names($data, &$errors = array()) { 298 $rolenames = array(); 299 $rolesids = self::get_role_ids(); 300 $invalidroles = array(); 301 foreach ($data as $field => $value) { 302 303 $matches = array(); 304 if (preg_match('/^role_(.+)?$/', $field, $matches)) { 305 if (!isset($rolesids[$matches[1]])) { 306 $invalidroles[] = $matches[1]; 307 continue; 308 } 309 $rolenames['role_' . $rolesids[$matches[1]]] = $value; 310 } 311 312 } 313 314 if (!empty($invalidroles)) { 315 $errors['invalidroles'] = new lang_string('invalidroles', 'tool_uploadcourse', implode(', ', $invalidroles)); 316 } 317 318 // Roles names. 319 return $rolenames; 320 } 321 322 /** 323 * Helper to increment an ID number. 324 * 325 * This first checks if the ID number is in use. 326 * 327 * @param string $idnumber ID number to increment. 328 * @return string new ID number. 329 */ 330 public static function increment_idnumber($idnumber) { 331 global $DB; 332 while ($DB->record_exists('course', array('idnumber' => $idnumber))) { 333 $matches = array(); 334 if (!preg_match('/(.*?)([0-9]+)$/', $idnumber, $matches)) { 335 $newidnumber = $idnumber . '_2'; 336 } else { 337 $newidnumber = $matches[1] . ((int) $matches[2] + 1); 338 } 339 $idnumber = $newidnumber; 340 } 341 return $idnumber; 342 } 343 344 /** 345 * Helper to increment a shortname. 346 * 347 * This considers that the shortname passed has to be incremented. 348 * 349 * @param string $shortname shortname to increment. 350 * @return string new shortname. 351 */ 352 public static function increment_shortname($shortname) { 353 global $DB; 354 do { 355 $matches = array(); 356 if (!preg_match('/(.*?)([0-9]+)$/', $shortname, $matches)) { 357 $newshortname = $shortname . '_2'; 358 } else { 359 $newshortname = $matches[1] . ($matches[2]+1); 360 } 361 $shortname = $newshortname; 362 } while ($DB->record_exists('course', array('shortname' => $shortname))); 363 return $shortname; 364 } 365 366 /** 367 * Resolve a category based on the data passed. 368 * 369 * Key accepted are: 370 * - category, which is supposed to be a category ID. 371 * - category_idnumber 372 * - category_path, array of categories from parent to child. 373 * 374 * @param array $data to resolve the category from. 375 * @param array $errors will be populated with errors found. 376 * @return int category ID. 377 */ 378 public static function resolve_category($data, &$errors = array()) { 379 $catid = null; 380 381 if (!empty($data['category'])) { 382 $category = coursecat::get((int) $data['category'], IGNORE_MISSING); 383 if (!empty($category) && !empty($category->id)) { 384 $catid = $category->id; 385 } else { 386 $errors['couldnotresolvecatgorybyid'] = 387 new lang_string('couldnotresolvecatgorybyid', 'tool_uploadcourse'); 388 } 389 } 390 391 if (empty($catid) && !empty($data['category_idnumber'])) { 392 $catid = self::resolve_category_by_idnumber($data['category_idnumber']); 393 if (empty($catid)) { 394 $errors['couldnotresolvecatgorybyidnumber'] = 395 new lang_string('couldnotresolvecatgorybyidnumber', 'tool_uploadcourse'); 396 } 397 } 398 if (empty($catid) && !empty($data['category_path'])) { 399 $catid = self::resolve_category_by_path(explode(' / ', $data['category_path'])); 400 if (empty($catid)) { 401 $errors['couldnotresolvecatgorybypath'] = 402 new lang_string('couldnotresolvecatgorybypath', 'tool_uploadcourse'); 403 } 404 } 405 406 return $catid; 407 } 408 409 /** 410 * Resolve a category by ID number. 411 * 412 * @param string $idnumber category ID number. 413 * @return int category ID. 414 */ 415 public static function resolve_category_by_idnumber($idnumber) { 416 global $DB; 417 $cache = cache::make('tool_uploadcourse', 'helper'); 418 $cachekey = 'cat_idn_' . $idnumber; 419 if (($id = $cache->get($cachekey)) === false) { 420 $params = array('idnumber' => $idnumber); 421 $id = $DB->get_field_select('course_categories', 'id', 'idnumber = :idnumber', $params, IGNORE_MISSING); 422 423 // Little hack to be able to differenciate between the cache not set and a category not found. 424 if ($id === false) { 425 $id = -1; 426 } 427 428 $cache->set($cachekey, $id); 429 } 430 431 // Little hack to be able to differenciate between the cache not set and a category not found. 432 if ($id == -1) { 433 $id = false; 434 } 435 436 return $id; 437 } 438 439 /** 440 * Resolve a category by path. 441 * 442 * @param array $path category names indexed from parent to children. 443 * @return int category ID. 444 */ 445 public static function resolve_category_by_path(array $path) { 446 global $DB; 447 $cache = cache::make('tool_uploadcourse', 'helper'); 448 $cachekey = 'cat_path_' . serialize($path); 449 if (($id = $cache->get($cachekey)) === false) { 450 $parent = 0; 451 $sql = 'name = :name AND parent = :parent'; 452 while ($name = array_shift($path)) { 453 $params = array('name' => $name, 'parent' => $parent); 454 if ($records = $DB->get_records_select('course_categories', $sql, $params, null, 'id, parent')) { 455 if (count($records) > 1) { 456 // Too many records with the same name! 457 $id = -1; 458 break; 459 } 460 $record = reset($records); 461 $id = $record->id; 462 $parent = $record->id; 463 } else { 464 // Not found. 465 $id = -1; 466 break; 467 } 468 } 469 $cache->set($cachekey, $id); 470 } 471 472 // We save -1 when the category has not been found to be able to know if the cache was set. 473 if ($id == -1) { 474 $id = false; 475 } 476 return $id; 477 } 478 479 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |