[ Index ] |
PHP Cross Reference of moodle-2.8 |
[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 * Manual enrolment plugin main library file. 19 * 20 * @package enrol_manual 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 class enrol_manual_plugin extends enrol_plugin { 28 29 protected $lasternoller = null; 30 protected $lasternollerinstanceid = 0; 31 32 public function roles_protected() { 33 // Users may tweak the roles later. 34 return false; 35 } 36 37 public function allow_enrol(stdClass $instance) { 38 // Users with enrol cap may unenrol other users manually manually. 39 return true; 40 } 41 42 public function allow_unenrol(stdClass $instance) { 43 // Users with unenrol cap may unenrol other users manually manually. 44 return true; 45 } 46 47 public function allow_manage(stdClass $instance) { 48 // Users with manage cap may tweak period and status. 49 return true; 50 } 51 52 /** 53 * Returns link to manual enrol UI if exists. 54 * Does the access control tests automatically. 55 * 56 * @param stdClass $instance 57 * @return moodle_url 58 */ 59 public function get_manual_enrol_link($instance) { 60 $name = $this->get_name(); 61 if ($instance->enrol !== $name) { 62 throw new coding_exception('invalid enrol instance!'); 63 } 64 65 if (!enrol_is_enabled($name)) { 66 return NULL; 67 } 68 69 $context = context_course::instance($instance->courseid, MUST_EXIST); 70 71 if (!has_capability('enrol/manual:enrol', $context)) { 72 // Note: manage capability not used here because it is used for editing 73 // of existing enrolments which is not possible here. 74 return NULL; 75 } 76 77 return new moodle_url('/enrol/manual/manage.php', array('enrolid'=>$instance->id, 'id'=>$instance->courseid)); 78 } 79 80 /** 81 * Returns enrolment instance manage link. 82 * 83 * By defaults looks for manage.php file and tests for manage capability. 84 * 85 * @param navigation_node $instancesnode 86 * @param stdClass $instance 87 * @return moodle_url; 88 */ 89 public function add_course_navigation($instancesnode, stdClass $instance) { 90 if ($instance->enrol !== 'manual') { 91 throw new coding_exception('Invalid enrol instance type!'); 92 } 93 94 $context = context_course::instance($instance->courseid); 95 if (has_capability('enrol/manual:config', $context)) { 96 $managelink = new moodle_url('/enrol/manual/edit.php', array('courseid'=>$instance->courseid)); 97 $instancesnode->add($this->get_instance_name($instance), $managelink, navigation_node::TYPE_SETTING); 98 } 99 } 100 101 /** 102 * Returns edit icons for the page with list of instances. 103 * @param stdClass $instance 104 * @return array 105 */ 106 public function get_action_icons(stdClass $instance) { 107 global $OUTPUT; 108 109 if ($instance->enrol !== 'manual') { 110 throw new coding_exception('invalid enrol instance!'); 111 } 112 $context = context_course::instance($instance->courseid); 113 114 $icons = array(); 115 116 if (has_capability('enrol/manual:enrol', $context) or has_capability('enrol/manual:unenrol', $context)) { 117 $managelink = new moodle_url("/enrol/manual/manage.php", array('enrolid'=>$instance->id)); 118 $icons[] = $OUTPUT->action_icon($managelink, new pix_icon('t/enrolusers', get_string('enrolusers', 'enrol_manual'), 'core', array('class'=>'iconsmall'))); 119 } 120 if (has_capability('enrol/manual:config', $context)) { 121 $editlink = new moodle_url("/enrol/manual/edit.php", array('courseid'=>$instance->courseid)); 122 $icons[] = $OUTPUT->action_icon($editlink, new pix_icon('t/edit', get_string('edit'), 'core', 123 array('class' => 'iconsmall'))); 124 } 125 126 return $icons; 127 } 128 129 /** 130 * Returns link to page which may be used to add new instance of enrolment plugin in course. 131 * @param int $courseid 132 * @return moodle_url page url 133 */ 134 public function get_newinstance_link($courseid) { 135 global $DB; 136 137 $context = context_course::instance($courseid, MUST_EXIST); 138 139 if (!has_capability('moodle/course:enrolconfig', $context) or !has_capability('enrol/manual:config', $context)) { 140 return NULL; 141 } 142 143 if ($DB->record_exists('enrol', array('courseid'=>$courseid, 'enrol'=>'manual'))) { 144 return NULL; 145 } 146 147 return new moodle_url('/enrol/manual/edit.php', array('courseid'=>$courseid)); 148 } 149 150 /** 151 * Add new instance of enrol plugin with default settings. 152 * @param stdClass $course 153 * @return int id of new instance, null if can not be created 154 */ 155 public function add_default_instance($course) { 156 $expirynotify = $this->get_config('expirynotify', 0); 157 if ($expirynotify == 2) { 158 $expirynotify = 1; 159 $notifyall = 1; 160 } else { 161 $notifyall = 0; 162 } 163 $fields = array( 164 'status' => $this->get_config('status'), 165 'roleid' => $this->get_config('roleid', 0), 166 'enrolperiod' => $this->get_config('enrolperiod', 0), 167 'expirynotify' => $expirynotify, 168 'notifyall' => $notifyall, 169 'expirythreshold' => $this->get_config('expirythreshold', 86400), 170 ); 171 return $this->add_instance($course, $fields); 172 } 173 174 /** 175 * Add new instance of enrol plugin. 176 * @param stdClass $course 177 * @param array instance fields 178 * @return int id of new instance, null if can not be created 179 */ 180 public function add_instance($course, array $fields = NULL) { 181 global $DB; 182 183 if ($DB->record_exists('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'))) { 184 // only one instance allowed, sorry 185 return NULL; 186 } 187 188 return parent::add_instance($course, $fields); 189 } 190 191 /** 192 * Returns a button to manually enrol users through the manual enrolment plugin. 193 * 194 * By default the first manual enrolment plugin instance available in the course is used. 195 * If no manual enrolment instances exist within the course then false is returned. 196 * 197 * This function also adds a quickenrolment JS ui to the page so that users can be enrolled 198 * via AJAX. 199 * 200 * @param course_enrolment_manager $manager 201 * @return enrol_user_button 202 */ 203 public function get_manual_enrol_button(course_enrolment_manager $manager) { 204 global $CFG; 205 require_once($CFG->dirroot.'/cohort/lib.php'); 206 207 $instance = null; 208 $instances = array(); 209 foreach ($manager->get_enrolment_instances() as $tempinstance) { 210 if ($tempinstance->enrol == 'manual') { 211 if ($instance === null) { 212 $instance = $tempinstance; 213 } 214 $instances[] = array('id' => $tempinstance->id, 'name' => $this->get_instance_name($tempinstance)); 215 } 216 } 217 if (empty($instance)) { 218 return false; 219 } 220 221 if (!$manuallink = $this->get_manual_enrol_link($instance)) { 222 return false; 223 } 224 225 $button = new enrol_user_button($manuallink, get_string('enrolusers', 'enrol_manual'), 'get'); 226 $button->class .= ' enrol_manual_plugin'; 227 228 $startdate = $manager->get_course()->startdate; 229 $startdateoptions = array(); 230 $timeformat = get_string('strftimedatefullshort'); 231 if ($startdate > 0) { 232 $startdateoptions[2] = get_string('coursestart') . ' (' . userdate($startdate, $timeformat) . ')'; 233 } 234 $today = time(); 235 $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); 236 $startdateoptions[3] = get_string('today') . ' (' . userdate($today, $timeformat) . ')' ; 237 $defaultduration = $instance->enrolperiod > 0 ? $instance->enrolperiod / 86400 : ''; 238 239 $modules = array('moodle-enrol_manual-quickenrolment', 'moodle-enrol_manual-quickenrolment-skin'); 240 $arguments = array( 241 'instances' => $instances, 242 'courseid' => $instance->courseid, 243 'ajaxurl' => '/enrol/manual/ajax.php', 244 'url' => $manager->get_moodlepage()->url->out(false), 245 'optionsStartDate' => $startdateoptions, 246 'defaultRole' => $instance->roleid, 247 'defaultDuration' => $defaultduration, 248 'disableGradeHistory' => $CFG->disablegradehistory, 249 'recoverGradesDefault'=> '', 250 'cohortsAvailable' => cohort_get_available_cohorts($manager->get_context(), COHORT_COUNT_MEMBERS, 0, 1) ? true : false 251 ); 252 253 if ($CFG->recovergradesdefault) { 254 $arguments['recoverGradesDefault'] = ' checked="checked"'; 255 } 256 257 $function = 'M.enrol_manual.quickenrolment.init'; 258 $button->require_yui_module($modules, $function, array($arguments)); 259 $button->strings_for_js(array( 260 'ajaxoneuserfound', 261 'ajaxxusersfound', 262 'ajaxnext25', 263 'enrol', 264 'enrolmentoptions', 265 'enrolusers', 266 'errajaxfailedenrol', 267 'errajaxsearch', 268 'none', 269 'usersearch', 270 'unlimitedduration', 271 'startdatetoday', 272 'durationdays', 273 'enrolperiod', 274 'finishenrollingusers', 275 'recovergrades'), 'enrol'); 276 $button->strings_for_js(array('browseusers', 'browsecohorts'), 'enrol_manual'); 277 $button->strings_for_js('assignroles', 'role'); 278 $button->strings_for_js('startingfrom', 'moodle'); 279 280 return $button; 281 } 282 283 /** 284 * Enrol cron support. 285 * @return void 286 */ 287 public function cron() { 288 $trace = new text_progress_trace(); 289 $this->sync($trace, null); 290 $this->send_expiry_notifications($trace); 291 } 292 293 /** 294 * Sync all meta course links. 295 * 296 * @param progress_trace $trace 297 * @param int $courseid one course, empty mean all 298 * @return int 0 means ok, 1 means error, 2 means plugin disabled 299 */ 300 public function sync(progress_trace $trace, $courseid = null) { 301 global $DB; 302 303 if (!enrol_is_enabled('manual')) { 304 $trace->finished(); 305 return 2; 306 } 307 308 // Unfortunately this may take a long time, execution can be interrupted safely here. 309 core_php_time_limit::raise(); 310 raise_memory_limit(MEMORY_HUGE); 311 312 $trace->output('Verifying manual enrolment expiration...'); 313 314 $params = array('now'=>time(), 'useractive'=>ENROL_USER_ACTIVE, 'courselevel'=>CONTEXT_COURSE); 315 $coursesql = ""; 316 if ($courseid) { 317 $coursesql = "AND e.courseid = :courseid"; 318 $params['courseid'] = $courseid; 319 } 320 321 // Deal with expired accounts. 322 $action = $this->get_config('expiredaction', ENROL_EXT_REMOVED_KEEP); 323 324 if ($action == ENROL_EXT_REMOVED_UNENROL) { 325 $instances = array(); 326 $sql = "SELECT ue.*, e.courseid, c.id AS contextid 327 FROM {user_enrolments} ue 328 JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual') 329 JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel) 330 WHERE ue.timeend > 0 AND ue.timeend < :now 331 $coursesql"; 332 $rs = $DB->get_recordset_sql($sql, $params); 333 foreach ($rs as $ue) { 334 if (empty($instances[$ue->enrolid])) { 335 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 336 } 337 $instance = $instances[$ue->enrolid]; 338 // Always remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here. 339 role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true); 340 $this->unenrol_user($instance, $ue->userid); 341 $trace->output("unenrolling expired user $ue->userid from course $instance->courseid", 1); 342 } 343 $rs->close(); 344 unset($instances); 345 346 } else if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES or $action == ENROL_EXT_REMOVED_SUSPEND) { 347 $instances = array(); 348 $sql = "SELECT ue.*, e.courseid, c.id AS contextid 349 FROM {user_enrolments} ue 350 JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual') 351 JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel) 352 WHERE ue.timeend > 0 AND ue.timeend < :now 353 AND ue.status = :useractive 354 $coursesql"; 355 $rs = $DB->get_recordset_sql($sql, $params); 356 foreach ($rs as $ue) { 357 if (empty($instances[$ue->enrolid])) { 358 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 359 } 360 $instance = $instances[$ue->enrolid]; 361 if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) { 362 // Remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here. 363 role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true); 364 $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); 365 $trace->output("suspending expired user $ue->userid in course $instance->courseid, roles unassigned", 1); 366 } else { 367 $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); 368 $trace->output("suspending expired user $ue->userid in course $instance->courseid, roles kept", 1); 369 } 370 } 371 $rs->close(); 372 unset($instances); 373 374 } else { 375 // ENROL_EXT_REMOVED_KEEP means no changes. 376 } 377 378 $trace->output('...manual enrolment updates finished.'); 379 $trace->finished(); 380 381 return 0; 382 } 383 384 /** 385 * Returns the user who is responsible for manual enrolments in given instance. 386 * 387 * Usually it is the first editing teacher - the person with "highest authority" 388 * as defined by sort_by_roleassignment_authority() having 'enrol/manual:manage' 389 * capability. 390 * 391 * @param int $instanceid enrolment instance id 392 * @return stdClass user record 393 */ 394 protected function get_enroller($instanceid) { 395 global $DB; 396 397 if ($this->lasternollerinstanceid == $instanceid and $this->lasternoller) { 398 return $this->lasternoller; 399 } 400 401 $instance = $DB->get_record('enrol', array('id'=>$instanceid, 'enrol'=>$this->get_name()), '*', MUST_EXIST); 402 $context = context_course::instance($instance->courseid); 403 404 if ($users = get_enrolled_users($context, 'enrol/manual:manage')) { 405 $users = sort_by_roleassignment_authority($users, $context); 406 $this->lasternoller = reset($users); 407 unset($users); 408 } else { 409 $this->lasternoller = parent::get_enroller($instanceid); 410 } 411 412 $this->lasternollerinstanceid = $instanceid; 413 414 return $this->lasternoller; 415 } 416 417 /** 418 * Gets an array of the user enrolment actions. 419 * 420 * @param course_enrolment_manager $manager 421 * @param stdClass $ue A user enrolment object 422 * @return array An array of user_enrolment_actions 423 */ 424 public function get_user_enrolment_actions(course_enrolment_manager $manager, $ue) { 425 $actions = array(); 426 $context = $manager->get_context(); 427 $instance = $ue->enrolmentinstance; 428 $params = $manager->get_moodlepage()->url->params(); 429 $params['ue'] = $ue->id; 430 if ($this->allow_unenrol_user($instance, $ue) && has_capability("enrol/manual:unenrol", $context)) { 431 $url = new moodle_url('/enrol/unenroluser.php', $params); 432 $actions[] = new user_enrolment_action(new pix_icon('t/delete', ''), get_string('unenrol', 'enrol'), $url, array('class'=>'unenrollink', 'rel'=>$ue->id)); 433 } 434 if ($this->allow_manage($instance) && has_capability("enrol/manual:manage", $context)) { 435 $url = new moodle_url('/enrol/editenrolment.php', $params); 436 $actions[] = new user_enrolment_action(new pix_icon('t/edit', ''), get_string('edit'), $url, array('class'=>'editenrollink', 'rel'=>$ue->id)); 437 } 438 return $actions; 439 } 440 441 /** 442 * The manual plugin has several bulk operations that can be performed. 443 * @param course_enrolment_manager $manager 444 * @return array 445 */ 446 public function get_bulk_operations(course_enrolment_manager $manager) { 447 global $CFG; 448 require_once($CFG->dirroot.'/enrol/manual/locallib.php'); 449 $context = $manager->get_context(); 450 $bulkoperations = array(); 451 if (has_capability("enrol/manual:manage", $context)) { 452 $bulkoperations['editselectedusers'] = new enrol_manual_editselectedusers_operation($manager, $this); 453 } 454 if (has_capability("enrol/manual:unenrol", $context)) { 455 $bulkoperations['deleteselectedusers'] = new enrol_manual_deleteselectedusers_operation($manager, $this); 456 } 457 return $bulkoperations; 458 } 459 460 /** 461 * Restore instance and map settings. 462 * 463 * @param restore_enrolments_structure_step $step 464 * @param stdClass $data 465 * @param stdClass $course 466 * @param int $oldid 467 */ 468 public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) { 469 global $DB; 470 // There is only I manual enrol instance allowed per course. 471 if ($instances = $DB->get_records('enrol', array('courseid'=>$data->courseid, 'enrol'=>'manual'), 'id')) { 472 $instance = reset($instances); 473 $instanceid = $instance->id; 474 } else { 475 $instanceid = $this->add_instance($course, (array)$data); 476 } 477 $step->set_mapping('enrol', $oldid, $instanceid); 478 } 479 480 /** 481 * Restore user enrolment. 482 * 483 * @param restore_enrolments_structure_step $step 484 * @param stdClass $data 485 * @param stdClass $instance 486 * @param int $oldinstancestatus 487 * @param int $userid 488 */ 489 public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) { 490 global $DB; 491 492 // Note: this is a bit tricky because other types may be converted to manual enrolments, 493 // and manual is restricted to one enrolment per user. 494 495 $ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid)); 496 $enrol = false; 497 if ($ue and $ue->status == ENROL_USER_ACTIVE) { 498 // We do not want to restrict current active enrolments, let's kind of merge the times only. 499 // This prevents some teacher lockouts too. 500 if ($data->status == ENROL_USER_ACTIVE) { 501 if ($data->timestart > $ue->timestart) { 502 $data->timestart = $ue->timestart; 503 $enrol = true; 504 } 505 506 if ($data->timeend == 0) { 507 if ($ue->timeend != 0) { 508 $enrol = true; 509 } 510 } else if ($ue->timeend == 0) { 511 $data->timeend = 0; 512 } else if ($data->timeend < $ue->timeend) { 513 $data->timeend = $ue->timeend; 514 $enrol = true; 515 } 516 } 517 } else { 518 if ($instance->status == ENROL_INSTANCE_ENABLED and $oldinstancestatus != ENROL_INSTANCE_ENABLED) { 519 // Make sure that user enrolments are not activated accidentally, 520 // we do it only here because it is not expected that enrolments are migrated to other plugins. 521 $data->status = ENROL_USER_SUSPENDED; 522 } 523 $enrol = true; 524 } 525 526 if ($enrol) { 527 $this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, $data->status); 528 } 529 } 530 531 /** 532 * Restore role assignment. 533 * 534 * @param stdClass $instance 535 * @param int $roleid 536 * @param int $userid 537 * @param int $contextid 538 */ 539 public function restore_role_assignment($instance, $roleid, $userid, $contextid) { 540 // This is necessary only because we may migrate other types to this instance, 541 // we do not use component in manual or self enrol. 542 role_assign($roleid, $userid, $contextid, '', 0); 543 } 544 545 /** 546 * Restore user group membership. 547 * @param stdClass $instance 548 * @param int $groupid 549 * @param int $userid 550 */ 551 public function restore_group_member($instance, $groupid, $userid) { 552 global $CFG; 553 require_once("$CFG->dirroot/group/lib.php"); 554 555 // This might be called when forcing restore as manual enrolments. 556 557 groups_add_member($groupid, $userid); 558 } 559 560 /** 561 * Is it possible to delete enrol instance via standard UI? 562 * 563 * @param object $instance 564 * @return bool 565 */ 566 public function can_delete_instance($instance) { 567 $context = context_course::instance($instance->courseid); 568 return has_capability('enrol/manual:config', $context); 569 } 570 571 /** 572 * Is it possible to hide/show enrol instance via standard UI? 573 * 574 * @param stdClass $instance 575 * @return bool 576 */ 577 public function can_hide_show_instance($instance) { 578 $context = context_course::instance($instance->courseid); 579 return has_capability('enrol/manual:config', $context); 580 } 581 582 /** 583 * Enrol all not enrolled cohort members into course via enrol instance. 584 * 585 * @param stdClass $instance 586 * @param int $cohortid 587 * @param int $roleid optional role id 588 * @param int $timestart 0 means unknown 589 * @param int $timeend 0 means forever 590 * @param int $status default to ENROL_USER_ACTIVE for new enrolments, no change by default in updates 591 * @param bool $recovergrades restore grade history 592 */ 593 public function enrol_cohort(stdClass $instance, $cohortid, $roleid = null, $timestart = 0, $timeend = 0, $status = null, $recovergrades = null) { 594 global $DB; 595 $context = context_course::instance($instance->courseid); 596 list($esql, $params) = get_enrolled_sql($context); 597 $sql = "SELECT cm.userid FROM {cohort_members} cm LEFT JOIN ($esql) u ON u.id = cm.userid ". 598 "WHERE cm.cohortid = :cohortid AND u.id IS NULL"; 599 $params['cohortid'] = $cohortid; 600 $members = $DB->get_fieldset_sql($sql, $params); 601 foreach ($members as $userid) { 602 $this->enrol_user($instance, $userid, $roleid, $timestart, $timeend, $status, $recovergrades); 603 } 604 } 605 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |