MDL-35064 improve enrol test comments
[moodle.git] / enrol / manual / locallib.php
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/>.
17 /**
18  * Auxiliary manual user enrolment lib, the main purpose is to lower memory requirements...
19  *
20  * @package    enrol
21  * @subpackage manual
22  * @copyright  2010 Petr Skoda {@link http://skodak.org}
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 require_once($CFG->dirroot . '/user/selector/lib.php');
29 require_once($CFG->dirroot . '/enrol/locallib.php');
32 /**
33  * Enrol candidates
34  */
35 class enrol_manual_potential_participant extends user_selector_base {
36     protected $enrolid;
38     public function __construct($name, $options) {
39         $this->enrolid  = $options['enrolid'];
40         parent::__construct($name, $options);
41     }
43     /**
44      * Candidate users
45      * @param <type> $search
46      * @return array
47      */
48     public function find_users($search) {
49         global $DB;
50         //by default wherecondition retrieves all users except the deleted, not confirmed and guest
51         list($wherecondition, $params) = $this->search_sql($search, 'u');
52         $params['enrolid'] = $this->enrolid;
54         $fields      = 'SELECT ' . $this->required_fields_sql('u');
55         $countfields = 'SELECT COUNT(1)';
57         $sql = " FROM {user} u
58             LEFT JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)
59                 WHERE $wherecondition
60                       AND ue.id IS NULL";
61         $order = ' ORDER BY u.lastname ASC, u.firstname ASC';
63         if (!$this->is_validating()) {
64             $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
65             if ($potentialmemberscount > 100) {
66                 return $this->too_many_results($search, $potentialmemberscount);
67             }
68         }
70         $availableusers = $DB->get_records_sql($fields . $sql . $order, $params);
72         if (empty($availableusers)) {
73             return array();
74         }
77         if ($search) {
78             $groupname = get_string('enrolcandidatesmatching', 'enrol', $search);
79         } else {
80             $groupname = get_string('enrolcandidates', 'enrol');
81         }
83         return array($groupname => $availableusers);
84     }
86     protected function get_options() {
87         $options = parent::get_options();
88         $options['enrolid'] = $this->enrolid;
89         $options['file']    = 'enrol/manual/locallib.php';
90         return $options;
91     }
92 }
94 /**
95  * Enroled users
96  */
97 class enrol_manual_current_participant extends user_selector_base {
98     protected $courseid;
99     protected $enrolid;
101     public function __construct($name, $options) {
102         $this->enrolid  = $options['enrolid'];
103         parent::__construct($name, $options);
104     }
106     /**
107      * Candidate users
108      * @param <type> $search
109      * @return array
110      */
111     public function find_users($search) {
112         global $DB;
113         //by default wherecondition retrieves all users except the deleted, not confirmed and guest
114         list($wherecondition, $params) = $this->search_sql($search, 'u');
115         $params['enrolid'] = $this->enrolid;
117         $fields      = 'SELECT ' . $this->required_fields_sql('u');
118         $countfields = 'SELECT COUNT(1)';
120         $sql = " FROM {user} u
121                  JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)
122                 WHERE $wherecondition";
124         $order = ' ORDER BY u.lastname ASC, u.firstname ASC';
126         if (!$this->is_validating()) {
127             $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
128             if ($potentialmemberscount > 100) {
129                 return $this->too_many_results($search, $potentialmemberscount);
130             }
131         }
133         $availableusers = $DB->get_records_sql($fields . $sql . $order, $params);
135         if (empty($availableusers)) {
136             return array();
137         }
140         if ($search) {
141             $groupname = get_string('enrolledusersmatching', 'enrol', $search);
142         } else {
143             $groupname = get_string('enrolledusers', 'enrol');
144         }
146         return array($groupname => $availableusers);
147     }
149     protected function get_options() {
150         $options = parent::get_options();
151         $options['enrolid'] = $this->enrolid;
152         $options['file']    = 'enrol/manual/locallib.php';
153         return $options;
154     }
157 /**
158  * A bulk operation for the manual enrolment plugin to edit selected users.
159  *
160  * @copyright 2011 Sam Hemelryk
161  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
162  */
163 class enrol_manual_editselectedusers_operation extends enrol_bulk_enrolment_operation {
165     /**
166      * Returns the title to display for this bulk operation.
167      *
168      * @return string
169      */
170     public function get_title() {
171         return get_string('editselectedusers', 'enrol_manual');
172     }
174     /**
175      * Returns the identifier for this bulk operation. This is the key used when the plugin
176      * returns an array containing all of the bulk operations it supports.
177      */
178     public function get_identifier() {
179         return 'editselectedusers';
180     }
182     /**
183      * Processes the bulk operation request for the given userids with the provided properties.
184      *
185      * @global moodle_database $DB
186      * @param course_enrolment_manager $manager
187      * @param array $userids
188      * @param stdClass $properties The data returned by the form.
189      */
190     public function process(course_enrolment_manager $manager, array $users, stdClass $properties) {
191         global $DB, $USER;
193         if (!has_capability("enrol/manual:manage", $manager->get_context())) {
194             return false;
195         }
197         // Get all of the user enrolment id's
198         $ueids = array();
199         $instances = array();
200         foreach ($users as $user) {
201             foreach ($user->enrolments as $enrolment) {
202                 $ueids[] = $enrolment->id;
203                 if (!array_key_exists($enrolment->id, $instances)) {
204                     $instances[$enrolment->id] = $enrolment;
205                 }
206             }
207         }
209         // Check that each instance is manageable by the current user.
210         foreach ($instances as $instance) {
211             if (!$this->plugin->allow_manage($instance)) {
212                 return false;
213             }
214         }
216         // Collect the known properties.
217         $status = $properties->status;
218         $timestart = $properties->timestart;
219         $timeend = $properties->timeend;
221         list($ueidsql, $params) = $DB->get_in_or_equal($ueids, SQL_PARAMS_NAMED);
223         $updatesql = array();
224         if ($status == ENROL_USER_ACTIVE || $status == ENROL_USER_SUSPENDED) {
225             $updatesql[] = 'status = :status';
226             $params['status'] = (int)$status;
227         }
228         if (!empty($timestart)) {
229             $updatesql[] = 'timestart = :timestart';
230             $params['timestart'] = (int)$timestart;
231         }
232         if (!empty($timeend)) {
233             $updatesql[] = 'timeend = :timeend';
234             $params['timeend'] = (int)$timeend;
235         }
236         if (empty($updatesql)) {
237             return true;
238         }
240         // Update the modifierid
241         $updatesql[] = 'modifierid = :modifierid';
242         $params['modifierid'] = (int)$USER->id;
244         // Update the time modified
245         $updatesql[] = 'timemodified = :timemodified';
246         $params['timemodified'] = time();
248         // Build the SQL statement
249         $updatesql = join(', ', $updatesql);
250         $sql = "UPDATE {user_enrolments}
251                    SET $updatesql
252                  WHERE id $ueidsql";
254         if ($DB->execute($sql, $params)) {
255             foreach ($users as $user) {
256                 foreach ($user->enrolments as $enrolment) {
257                     $enrolment->courseid  = $enrolment->enrolmentinstance->courseid;
258                     $enrolment->enrol     = 'manual';
259                     events_trigger('user_enrol_modified', $enrolment);
260                 }
261             }
262             return true;
263         }
265         return false;
266     }
268     /**
269      * Returns a enrol_bulk_enrolment_operation extension form to be used
270      * in collecting required information for this operation to be processed.
271      *
272      * @param string|moodle_url|null $defaultaction
273      * @param mixed $defaultcustomdata
274      * @return enrol_manual_editselectedusers_form
275      */
276     public function get_form($defaultaction = null, $defaultcustomdata = null) {
277         global $CFG;
278         require_once($CFG->dirroot.'/enrol/manual/bulkchangeforms.php');
279         return new enrol_manual_editselectedusers_form($defaultaction, $defaultcustomdata);
280     }
284 /**
285  * A bulk operation for the manual enrolment plugin to delete selected users enrolments.
286  *
287  * @copyright 2011 Sam Hemelryk
288  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
289  */
290 class enrol_manual_deleteselectedusers_operation extends enrol_bulk_enrolment_operation {
292     /**
293      * Returns the title to display for this bulk operation.
294      *
295      * @return string
296      */
297     public function get_identifier() {
298         return 'deleteselectedusers';
299     }
301     /**
302      * Returns the identifier for this bulk operation. This is the key used when the plugin
303      * returns an array containing all of the bulk operations it supports.
304      *
305      * @return string
306      */
307     public function get_title() {
308         return get_string('deleteselectedusers', 'enrol_manual');
309     }
311     /**
312      * Returns a enrol_bulk_enrolment_operation extension form to be used
313      * in collecting required information for this operation to be processed.
314      *
315      * @param string|moodle_url|null $defaultaction
316      * @param mixed $defaultcustomdata
317      * @return enrol_manual_editselectedusers_form
318      */
319     public function get_form($defaultaction = null, $defaultcustomdata = null) {
320         global $CFG;
321         require_once($CFG->dirroot.'/enrol/manual/bulkchangeforms.php');
322         if (!array($defaultcustomdata)) {
323             $defaultcustomdata = array();
324         }
325         $defaultcustomdata['title'] = $this->get_title();
326         $defaultcustomdata['message'] = get_string('confirmbulkdeleteenrolment', 'enrol_manual');
327         $defaultcustomdata['button'] = get_string('unenrolusers', 'enrol_manual');
328         return new enrol_manual_deleteselectedusers_form($defaultaction, $defaultcustomdata);
329     }
331     /**
332      * Processes the bulk operation request for the given userids with the provided properties.
333      *
334      * @global moodle_database $DB
335      * @param course_enrolment_manager $manager
336      * @param array $userids
337      * @param stdClass $properties The data returned by the form.
338      */
339     public function process(course_enrolment_manager $manager, array $users, stdClass $properties) {
340         global $DB;
342         if (!has_capability("enrol/manual:unenrol", $manager->get_context())) {
343             return false;
344         }
345         foreach ($users as $user) {
346             foreach ($user->enrolments as $enrolment) {
347                 $plugin = $enrolment->enrolmentplugin;
348                 $instance = $enrolment->enrolmentinstance;
349                 if ($plugin->allow_unenrol_user($instance, $enrolment)) {
350                     $plugin->unenrol_user($instance, $user->id);
351                 }
352             }
353         }
354         return true;
355     }
359 /**
360  * Migrates all enrolments of the given plugin to enrol_manual plugin,
361  * this is used for example during plugin uninstallation.
362  *
363  * NOTE: this function does not trigger role and enrolment related events.
364  *
365  * @param string $enrol
366  */
367 function enrol_manual_migrate_plugin_enrolments($enrol) {
368     global $DB;
370     if ($enrol === 'manual') {
371         // We can not migrate to self.
372         return;
373     }
375     $manualplugin = enrol_get_plugin('manual');
377     $params = array('enrol'=>$enrol);
378     $sql = "SELECT e.id, e.courseid, e.status, MIN(me.id) AS mid, COUNT(ue.id) AS cu
379               FROM {enrol} e
380               JOIN {user_enrolments} ue ON (ue.enrolid = e.id)
381               JOIN {course} c ON (c.id = e.courseid)
382          LEFT JOIN {enrol} me ON (me.courseid = e.courseid AND me.enrol='manual')
383              WHERE e.enrol = :enrol
384           GROUP BY e.id, e.courseid, e.status
385           ORDER BY e.id";
386     $rs = $DB->get_recordset_sql($sql, $params);
388     foreach($rs as $e) {
389         $minstance = false;
390         if (!$e->mid) {
391             // Manual instance does not exist yet, add a new one.
392             $course = $DB->get_record('course', array('id'=>$e->courseid), '*', MUST_EXIST);
393             if ($minstance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'))) {
394                 // Already created by previous iteration.
395                 $e->mid = $minstance->id;
396             } else if ($e->mid = $manualplugin->add_default_instance($course)) {
397                 $minstance = $DB->get_record('enrol', array('id'=>$e->mid));
398                 if ($e->status != ENROL_INSTANCE_ENABLED) {
399                     $DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$e->mid));
400                     $minstance->status = ENROL_INSTANCE_DISABLED;
401                 }
402             }
403         } else {
404             $minstance = $DB->get_record('enrol', array('id'=>$e->mid));
405         }
407         if (!$minstance) {
408             // This should never happen unless adding of default instance fails unexpectedly.
409             continue;
410         }
412         // First delete potential role duplicates.
413         $params = array('id'=>$e->id, 'component'=>'enrol_'.$enrol, 'empty'=>$DB->sql_empty());
414         $sql = "SELECT ra.id
415                   FROM {role_assignments} ra
416                   JOIN {role_assignments} mra ON (mra.contextid = ra.contextid AND mra.userid = ra.userid AND mra.roleid = ra.roleid AND mra.component = :empty AND mra.itemid = 0)
417                  WHERE ra.component = :component AND ra.itemid = :id";
418         $ras = $DB->get_records_sql($sql, $params);
419         $ras = array_keys($ras);
420         $DB->delete_records_list('role_assignments', 'id', $ras);
421         unset($ras);
423         // Migrate roles.
424         $sql = "UPDATE {role_assignments}
425                    SET itemid = 0, component = :empty
426                  WHERE itemid = :id AND component = :component";
427         $params = array('empty'=>$DB->sql_empty(), 'id'=>$e->id, 'component'=>'enrol_'.$enrol);
428         $DB->execute($sql, $params);
430         // Delete potential enrol duplicates.
431         $params = array('id'=>$e->id, 'mid'=>$e->mid);
432         $sql = "SELECT ue.id
433                   FROM {user_enrolments} ue
434                   JOIN {user_enrolments} mue ON (mue.userid = ue.userid AND mue.enrolid = :mid)
435                  WHERE ue.enrolid = :id";
436         $ues = $DB->get_records_sql($sql, $params);
437         $ues = array_keys($ues);
438         $DB->delete_records_list('user_enrolments', 'id', $ues);
439         unset($ues);
441         // Migrate to manual enrol instance.
442         $params = array('id'=>$e->id, 'mid'=>$e->mid);
443         if ($e->status != ENROL_INSTANCE_ENABLED and $minstance->status == ENROL_INSTANCE_ENABLED) {
444             $status = ", status = :disabled";
445             $params['disabled'] = ENROL_USER_SUSPENDED;
446         } else {
447             $status = "";
448         }
449         $sql = "UPDATE {user_enrolments}
450                    SET enrolid = :mid $status
451                  WHERE enrolid = :id";
452         $DB->execute($sql, $params);
453     }
454     $rs->close();