[ 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 * Meta course enrolment plugin. 19 * 20 * @package enrol_meta 21 * @copyright 2010 Petr Skoda {@link http://skodak.org} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 /** 28 * ENROL_META_CREATE_GROUP constant for automatically creating a group for a meta course. 29 */ 30 define('ENROL_META_CREATE_GROUP', -1); 31 32 /** 33 * Meta course enrolment plugin. 34 * @author Petr Skoda 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class enrol_meta_plugin extends enrol_plugin { 38 39 /** 40 * Returns localised name of enrol instance 41 * 42 * @param stdClass $instance (null is accepted too) 43 * @return string 44 */ 45 public function get_instance_name($instance) { 46 global $DB; 47 48 if (empty($instance)) { 49 $enrol = $this->get_name(); 50 return get_string('pluginname', 'enrol_'.$enrol); 51 } else if (empty($instance->name)) { 52 $enrol = $this->get_name(); 53 $course = $DB->get_record('course', array('id'=>$instance->customint1)); 54 if ($course) { 55 $coursename = format_string(get_course_display_name_for_list($course)); 56 } else { 57 // Use course id, if course is deleted. 58 $coursename = $instance->customint1; 59 } 60 return get_string('pluginname', 'enrol_' . $enrol) . ' (' . $coursename . ')'; 61 } else { 62 return format_string($instance->name); 63 } 64 } 65 66 /** 67 * Returns true if we can add a new instance to this course. 68 * 69 * @param int $courseid 70 * @return boolean 71 */ 72 public function can_add_instance($courseid) { 73 $context = context_course::instance($courseid, MUST_EXIST); 74 if (!has_capability('moodle/course:enrolconfig', $context) or !has_capability('enrol/meta:config', $context)) { 75 return false; 76 } 77 // Multiple instances supported - multiple parent courses linked. 78 return true; 79 } 80 81 /** 82 * Does this plugin allow manual unenrolment of a specific user? 83 * Yes, but only if user suspended... 84 * 85 * @param stdClass $instance course enrol instance 86 * @param stdClass $ue record from user_enrolments table 87 * 88 * @return bool - true means user with 'enrol/xxx:unenrol' may unenrol this user, false means nobody may touch this user enrolment 89 */ 90 public function allow_unenrol_user(stdClass $instance, stdClass $ue) { 91 if ($ue->status == ENROL_USER_SUSPENDED) { 92 return true; 93 } 94 95 return false; 96 } 97 98 /** 99 * Gets an array of the user enrolment actions 100 * 101 * @param course_enrolment_manager $manager 102 * @param stdClass $ue A user enrolment object 103 * @return array An array of user_enrolment_actions 104 */ 105 public function get_user_enrolment_actions(course_enrolment_manager $manager, $ue) { 106 $actions = array(); 107 $context = $manager->get_context(); 108 $instance = $ue->enrolmentinstance; 109 $params = $manager->get_moodlepage()->url->params(); 110 $params['ue'] = $ue->id; 111 if ($this->allow_unenrol_user($instance, $ue) && has_capability('enrol/meta:unenrol', $context)) { 112 $url = new moodle_url('/enrol/unenroluser.php', $params); 113 $actions[] = new user_enrolment_action(new pix_icon('t/delete', ''), get_string('unenrol', 'enrol'), $url, array('class'=>'unenrollink', 'rel'=>$ue->id)); 114 } 115 return $actions; 116 } 117 118 /** 119 * Called after updating/inserting course. 120 * 121 * @param bool $inserted true if course just inserted 122 * @param stdClass $course 123 * @param stdClass $data form data 124 * @return void 125 */ 126 public function course_updated($inserted, $course, $data) { 127 // Meta sync updates are slow, if enrolments get out of sync teacher will have to wait till next cron. 128 // We should probably add some sync button to the course enrol methods overview page. 129 } 130 131 /** 132 * Add new instance of enrol plugin. 133 * @param object $course 134 * @param array $fields instance fields 135 * @return int id of last instance, null if can not be created 136 */ 137 public function add_instance($course, array $fields = null) { 138 global $CFG; 139 140 require_once("$CFG->dirroot/enrol/meta/locallib.php"); 141 142 // Support creating multiple at once. 143 if (is_array($fields['customint1'])) { 144 $courses = array_unique($fields['customint1']); 145 } else { 146 $courses = array($fields['customint1']); 147 } 148 foreach ($courses as $courseid) { 149 if (!empty($fields['customint2']) && $fields['customint2'] == ENROL_META_CREATE_GROUP) { 150 $context = context_course::instance($course->id); 151 require_capability('moodle/course:managegroups', $context); 152 $groupid = enrol_meta_create_new_group($course->id, $courseid); 153 $fields['customint2'] = $groupid; 154 } 155 156 $fields['customint1'] = $courseid; 157 $result = parent::add_instance($course, $fields); 158 } 159 160 enrol_meta_sync($course->id); 161 162 return $result; 163 } 164 165 /** 166 * Update instance of enrol plugin. 167 * @param stdClass $instance 168 * @param stdClass $data modified instance fields 169 * @return boolean 170 */ 171 public function update_instance($instance, $data) { 172 global $CFG; 173 174 require_once("$CFG->dirroot/enrol/meta/locallib.php"); 175 176 if (!empty($data->customint2) && $data->customint2 == ENROL_META_CREATE_GROUP) { 177 $context = context_course::instance($instance->courseid); 178 require_capability('moodle/course:managegroups', $context); 179 $groupid = enrol_meta_create_new_group($instance->courseid, $data->customint1); 180 $data->customint2 = $groupid; 181 } 182 183 $result = parent::update_instance($instance, $data); 184 185 enrol_meta_sync($instance->courseid); 186 187 return $result; 188 } 189 190 /** 191 * Update instance status 192 * 193 * @param stdClass $instance 194 * @param int $newstatus ENROL_INSTANCE_ENABLED, ENROL_INSTANCE_DISABLED 195 * @return void 196 */ 197 public function update_status($instance, $newstatus) { 198 global $CFG; 199 200 parent::update_status($instance, $newstatus); 201 202 require_once("$CFG->dirroot/enrol/meta/locallib.php"); 203 enrol_meta_sync($instance->courseid); 204 } 205 206 /** 207 * Called for all enabled enrol plugins that returned true from is_cron_required(). 208 * @return void 209 */ 210 public function cron() { 211 global $CFG; 212 213 require_once("$CFG->dirroot/enrol/meta/locallib.php"); 214 enrol_meta_sync(); 215 } 216 217 /** 218 * Is it possible to delete enrol instance via standard UI? 219 * 220 * @param stdClass $instance 221 * @return bool 222 */ 223 public function can_delete_instance($instance) { 224 $context = context_course::instance($instance->courseid); 225 return has_capability('enrol/meta:config', $context); 226 } 227 228 /** 229 * Is it possible to hide/show enrol instance via standard UI? 230 * 231 * @param stdClass $instance 232 * @return bool 233 */ 234 public function can_hide_show_instance($instance) { 235 $context = context_course::instance($instance->courseid); 236 return has_capability('enrol/meta:config', $context); 237 } 238 239 /** 240 * We are a good plugin and don't invent our own UI/validation code path. 241 * 242 * @return boolean 243 */ 244 public function use_standard_editing_ui() { 245 return true; 246 } 247 248 /** 249 * Return an array of valid options for the courses. 250 * 251 * @param stdClass $instance 252 * @param context $coursecontext 253 * @return array 254 */ 255 protected function get_course_options($instance, $coursecontext) { 256 global $DB; 257 258 if ($instance->id) { 259 $where = 'WHERE c.id = :courseid'; 260 $params = array('courseid' => $instance->customint1); 261 $existing = array(); 262 } else { 263 $where = ''; 264 $params = array(); 265 $instanceparams = array('enrol' => 'meta', 'courseid' => $instance->courseid); 266 $existing = $DB->get_records('enrol', $instanceparams, '', 'customint1, id'); 267 } 268 269 // TODO: this has to be done via ajax or else it will fail very badly on large sites! 270 $courses = array(); 271 $select = ', ' . context_helper::get_preload_record_columns_sql('ctx'); 272 $join = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)"; 273 274 $sortorder = 'c.' . $this->get_config('coursesort', 'sortorder') . ' ASC'; 275 276 $sql = "SELECT c.id, c.fullname, c.shortname, c.visible $select FROM {course} c $join $where ORDER BY $sortorder"; 277 $rs = $DB->get_recordset_sql($sql, array('contextlevel' => CONTEXT_COURSE) + $params); 278 foreach ($rs as $c) { 279 if ($c->id == SITEID or $c->id == $instance->courseid or isset($existing[$c->id])) { 280 continue; 281 } 282 context_helper::preload_from_record($c); 283 $coursecontext = context_course::instance($c->id); 284 if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) { 285 continue; 286 } 287 if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) { 288 continue; 289 } 290 $courses[$c->id] = $coursecontext->get_context_name(false); 291 } 292 $rs->close(); 293 return $courses; 294 } 295 296 /** 297 * Return an array of valid options for the groups. 298 * 299 * @param context $coursecontext 300 * @return array 301 */ 302 protected function get_group_options($coursecontext) { 303 $groups = array(0 => get_string('none')); 304 $courseid = $coursecontext->instanceid; 305 if (has_capability('moodle/course:managegroups', $coursecontext)) { 306 $groups[ENROL_META_CREATE_GROUP] = get_string('creategroup', 'enrol_meta'); 307 } 308 foreach (groups_get_all_groups($courseid) as $group) { 309 $groups[$group->id] = format_string($group->name, true, array('context' => $coursecontext)); 310 } 311 return $groups; 312 } 313 314 /** 315 * Add elements to the edit instance form. 316 * 317 * @param stdClass $instance 318 * @param MoodleQuickForm $mform 319 * @param context $coursecontext 320 * @return bool 321 */ 322 public function edit_instance_form($instance, MoodleQuickForm $mform, $coursecontext) { 323 global $DB; 324 325 $groups = $this->get_group_options($coursecontext); 326 $existing = $DB->get_records('enrol', array('enrol' => 'meta', 'courseid' => $coursecontext->instanceid), '', 'customint1, id'); 327 328 $excludelist = array($coursecontext->instanceid); 329 foreach ($existing as $existinginstance) { 330 $excludelist[] = $existinginstance->customint1; 331 } 332 333 $options = array( 334 'requiredcapabilities' => array('enrol/meta:selectaslinked'), 335 'multiple' => true, 336 'exclude' => $excludelist 337 ); 338 $mform->addElement('course', 'customint1', get_string('linkedcourse', 'enrol_meta'), $options); 339 $mform->addRule('customint1', get_string('required'), 'required', null, 'client'); 340 if (!empty($instance->id)) { 341 $mform->freeze('customint1'); 342 } 343 344 $mform->addElement('select', 'customint2', get_string('addgroup', 'enrol_meta'), $groups); 345 } 346 347 /** 348 * Perform custom validation of the data used to edit the instance. 349 * 350 * @param array $data array of ("fieldname"=>value) of submitted data 351 * @param array $files array of uploaded files "element_name"=>tmp_file_path 352 * @param object $instance The instance loaded from the DB 353 * @param context $context The context of the instance we are editing 354 * @return array of "element_name"=>"error_description" if there are errors, 355 * or an empty array if everything is OK. 356 * @return void 357 */ 358 public function edit_instance_validation($data, $files, $instance, $context) { 359 global $DB; 360 $errors = array(); 361 $thiscourseid = $context->instanceid; 362 $c = false; 363 364 if (!empty($data['customint1'])) { 365 foreach ($data['customint1'] as $courseid) { 366 $c = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); 367 $coursecontext = context_course::instance($c->id); 368 $existing = $DB->get_records('enrol', array('enrol' => 'meta', 'courseid' => $thiscourseid), '', 'customint1, id'); 369 if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) { 370 $errors['customint1'] = get_string('error'); 371 } else if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) { 372 $errors['customint1'] = get_string('error'); 373 } else if ($c->id == SITEID or $c->id == $thiscourseid or isset($existing[$c->id])) { 374 $errors['customint1'] = get_string('error'); 375 } 376 } 377 } else { 378 $errors['customint1'] = get_string('required'); 379 } 380 381 $validgroups = array_keys($this->get_group_options($context)); 382 383 $tovalidate = array( 384 'customint2' => $validgroups 385 ); 386 $typeerrors = $this->validate_param_types($data, $tovalidate); 387 $errors = array_merge($errors, $typeerrors); 388 389 return $errors; 390 } 391 392 393 /** 394 * Restore instance and map settings. 395 * 396 * @param restore_enrolments_structure_step $step 397 * @param stdClass $data 398 * @param stdClass $course 399 * @param int $oldid 400 */ 401 public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) { 402 global $DB, $CFG; 403 404 if (!$step->get_task()->is_samesite()) { 405 // No meta restore from other sites. 406 $step->set_mapping('enrol', $oldid, 0); 407 return; 408 } 409 410 if (!empty($data->customint2)) { 411 $data->customint2 = $step->get_mappingid('group', $data->customint2); 412 } 413 414 if ($DB->record_exists('course', array('id' => $data->customint1))) { 415 $instance = $DB->get_record('enrol', array('roleid' => $data->roleid, 'customint1' => $data->customint1, 416 'courseid' => $course->id, 'enrol' => $this->get_name())); 417 if ($instance) { 418 $instanceid = $instance->id; 419 } else { 420 $instanceid = $this->add_instance($course, (array)$data); 421 } 422 $step->set_mapping('enrol', $oldid, $instanceid); 423 424 require_once("$CFG->dirroot/enrol/meta/locallib.php"); 425 enrol_meta_sync($data->customint1); 426 427 } else { 428 $step->set_mapping('enrol', $oldid, 0); 429 } 430 } 431 432 /** 433 * Restore user enrolment. 434 * 435 * @param restore_enrolments_structure_step $step 436 * @param stdClass $data 437 * @param stdClass $instance 438 * @param int $userid 439 * @param int $oldinstancestatus 440 */ 441 public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) { 442 global $DB; 443 444 if ($this->get_config('unenrolaction') != ENROL_EXT_REMOVED_SUSPENDNOROLES) { 445 // Enrolments were already synchronised in restore_instance(), we do not want any suspended leftovers. 446 return; 447 } 448 449 // ENROL_EXT_REMOVED_SUSPENDNOROLES means all previous enrolments are restored 450 // but without roles and suspended. 451 452 if (!$DB->record_exists('user_enrolments', array('enrolid' => $instance->id, 'userid' => $userid))) { 453 $this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, ENROL_USER_SUSPENDED); 454 if ($instance->customint2) { 455 groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->id); 456 } 457 } 458 } 459 460 /** 461 * Restore user group membership. 462 * @param stdClass $instance 463 * @param int $groupid 464 * @param int $userid 465 */ 466 public function restore_group_member($instance, $groupid, $userid) { 467 // Nothing to do here, the group members are added in $this->restore_group_restored(). 468 return; 469 } 470 471 }
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 |