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