Commit | Line | Data |
---|---|---|
e9b66095 | 1 | <?php |
e9b66095 | 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 | ||
4615817d | 17 | |
e9b66095 | 18 | /** |
df997f84 | 19 | * External course participation api. |
e9b66095 | 20 | * |
df997f84 PS |
21 | * This api is mostly read only, the actual enrol and unenrol |
22 | * support is in each enrol plugin. | |
23 | * | |
4615817d JM |
24 | * @package core_enrol |
25 | * @category external | |
26 | * @copyright 2010 Jerome Mouneyrac | |
e9b66095 | 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
28 | */ | |
29 | ||
97795859 | 30 | defined('MOODLE_INTERNAL') || die(); |
df997f84 | 31 | |
e9b66095 | 32 | require_once("$CFG->libdir/externallib.php"); |
33 | ||
5d1017e1 | 34 | /** |
4615817d JM |
35 | * Enrol external functions |
36 | * | |
37 | * @package core_enrol | |
38 | * @category external | |
39 | * @copyright 2011 Jerome Mouneyrac | |
40 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
41 | * @since Moodle 2.2 | |
5d1017e1 JM |
42 | */ |
43 | class core_enrol_external extends external_api { | |
44 | ||
b6b6c7ac PC |
45 | /** |
46 | * Returns description of method parameters | |
47 | * | |
48 | * @return external_function_parameters | |
49 | * @since Moodle 2.4 | |
50 | */ | |
51 | public static function get_enrolled_users_with_capability_parameters() { | |
52 | return new external_function_parameters( | |
53 | array ( | |
54 | 'coursecapabilities' => new external_multiple_structure( | |
55 | new external_single_structure( | |
56 | array ( | |
57 | 'courseid' => new external_value(PARAM_INT, 'Course ID number in the Moodle course table'), | |
58 | 'capabilities' => new external_multiple_structure( | |
59 | new external_value(PARAM_CAPABILITY, 'Capability name, such as mod/forum:viewdiscussion')), | |
60 | ) | |
61 | ) | |
62 | , 'course id and associated capability name'), | |
63 | 'options' => new external_multiple_structure( | |
64 | new external_single_structure( | |
65 | array( | |
66 | 'name' => new external_value(PARAM_ALPHANUMEXT, 'option name'), | |
67 | 'value' => new external_value(PARAM_RAW, 'option value') | |
68 | ) | |
69 | ), 'Option names: | |
70 | * groupid (integer) return only users in this group id. Requires \'moodle/site:accessallgroups\' . | |
71 | * onlyactive (integer) only users with active enrolments. Requires \'moodle/course:enrolreview\' . | |
72 | * userfields (\'string, string, ...\') return only the values of these user fields. | |
73 | * limitfrom (integer) sql limit from. | |
74 | * limitnumber (integer) max number of users per course and capability.', VALUE_DEFAULT, array()) | |
75 | ) | |
76 | ); | |
77 | } | |
78 | ||
79 | /** | |
80 | * Return users that have the capabilities for each course specified. For each course and capability specified, | |
21d3bfb3 | 81 | * a list of the users that are enrolled in the course and have that capability are returned. |
b6b6c7ac PC |
82 | * |
83 | * @param array $coursecapabilities array of course ids and associated capability names {courseid, {capabilities}} | |
84 | * @return array An array of arrays describing users for each associated courseid and capability | |
85 | * @since Moodle 2.4 | |
86 | */ | |
87 | public static function get_enrolled_users_with_capability($coursecapabilities, $options) { | |
88 | global $CFG, $DB; | |
93b47710 MN |
89 | |
90 | require_once($CFG->dirroot . '/course/lib.php'); | |
b6b6c7ac PC |
91 | require_once($CFG->dirroot . "/user/lib.php"); |
92 | ||
93 | if (empty($coursecapabilities)) { | |
94 | throw new invalid_parameter_exception('Parameter can not be empty'); | |
95 | } | |
96 | $params = self::validate_parameters(self::get_enrolled_users_with_capability_parameters(), | |
97 | array ('coursecapabilities' => $coursecapabilities, 'options'=>$options)); | |
98 | $result = array(); | |
99 | $userlist = array(); | |
100 | $groupid = 0; | |
101 | $onlyactive = false; | |
102 | $userfields = array(); | |
103 | $limitfrom = 0; | |
104 | $limitnumber = 0; | |
105 | foreach ($params['options'] as $option) { | |
106 | switch ($option['name']) { | |
107 | case 'groupid': | |
108 | $groupid = (int)$option['value']; | |
109 | break; | |
110 | case 'onlyactive': | |
111 | $onlyactive = !empty($option['value']); | |
112 | break; | |
113 | case 'userfields': | |
114 | $thefields = explode(',', $option['value']); | |
115 | foreach ($thefields as $f) { | |
116 | $userfields[] = clean_param($f, PARAM_ALPHANUMEXT); | |
117 | } | |
578a39b8 | 118 | break; |
b6b6c7ac PC |
119 | case 'limitfrom' : |
120 | $limitfrom = clean_param($option['value'], PARAM_INT); | |
121 | break; | |
122 | case 'limitnumber' : | |
123 | $limitnumber = clean_param($option['value'], PARAM_INT); | |
124 | break; | |
125 | } | |
126 | } | |
127 | ||
128 | foreach ($params['coursecapabilities'] as $coursecapability) { | |
129 | $courseid = $coursecapability['courseid']; | |
74df2951 | 130 | $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST); |
b6b6c7ac PC |
131 | $coursecontext = context_course::instance($courseid); |
132 | if (!$coursecontext) { | |
133 | throw new moodle_exception('cannotfindcourse', 'error', '', null, | |
134 | 'The course id ' . $courseid . ' doesn\'t exist.'); | |
135 | } | |
136 | if ($courseid == SITEID) { | |
137 | $context = context_system::instance(); | |
138 | } else { | |
139 | $context = $coursecontext; | |
140 | } | |
141 | try { | |
142 | self::validate_context($context); | |
143 | } catch (Exception $e) { | |
144 | $exceptionparam = new stdClass(); | |
145 | $exceptionparam->message = $e->getMessage(); | |
146 | $exceptionparam->courseid = $params['courseid']; | |
147 | throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); | |
148 | } | |
149 | ||
93b47710 MN |
150 | course_require_view_participants($context); |
151 | ||
b6b6c7ac PC |
152 | // The accessallgroups capability is needed to use this option. |
153 | if (!empty($groupid) && groups_is_member($groupid)) { | |
154 | require_capability('moodle/site:accessallgroups', $coursecontext); | |
155 | } | |
156 | // The course:enrolereview capability is needed to use this option. | |
157 | if ($onlyactive) { | |
158 | require_capability('moodle/course:enrolreview', $coursecontext); | |
159 | } | |
160 | ||
161 | // To see the permissions of others role:review capability is required. | |
162 | require_capability('moodle/role:review', $coursecontext); | |
163 | foreach ($coursecapability['capabilities'] as $capability) { | |
164 | $courseusers['courseid'] = $courseid; | |
165 | $courseusers['capability'] = $capability; | |
166 | ||
167 | list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext, $capability, $groupid, $onlyactive); | |
1f87a7f6 | 168 | $enrolledparams['courseid'] = $courseid; |
b6b6c7ac | 169 | |
1f87a7f6 JL |
170 | $sql = "SELECT u.*, COALESCE(ul.timeaccess, 0) AS lastcourseaccess |
171 | FROM {user} u | |
172 | LEFT JOIN {user_lastaccess} ul ON (ul.userid = u.id AND ul.courseid = :courseid) | |
173 | WHERE u.id IN ($enrolledsql) | |
174 | ORDER BY u.id ASC"; | |
b6b6c7ac PC |
175 | |
176 | $enrolledusers = $DB->get_recordset_sql($sql, $enrolledparams, $limitfrom, $limitnumber); | |
177 | $users = array(); | |
178 | foreach ($enrolledusers as $courseuser) { | |
179 | if ($userdetails = user_get_user_details($courseuser, $course, $userfields)) { | |
180 | $users[] = $userdetails; | |
181 | } | |
182 | } | |
183 | $enrolledusers->close(); | |
184 | $courseusers['users'] = $users; | |
185 | $result[] = $courseusers; | |
186 | } | |
187 | } | |
188 | return $result; | |
189 | } | |
190 | ||
191 | /** | |
192 | * Returns description of method result value | |
193 | * | |
194 | * @return external_multiple_structure | |
195 | * @since Moodle 2.4 | |
196 | */ | |
197 | public static function get_enrolled_users_with_capability_returns() { | |
198 | return new external_multiple_structure( new external_single_structure ( | |
199 | array ( | |
200 | 'courseid' => new external_value(PARAM_INT, 'Course ID number in the Moodle course table'), | |
201 | 'capability' => new external_value(PARAM_CAPABILITY, 'Capability name'), | |
202 | 'users' => new external_multiple_structure( | |
203 | new external_single_structure( | |
204 | array( | |
fb5ce7d3 | 205 | 'id' => new external_value(PARAM_INT, 'ID of the user'), |
b6b6c7ac PC |
206 | 'username' => new external_value(PARAM_RAW, 'Username', VALUE_OPTIONAL), |
207 | 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL), | |
208 | 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), | |
209 | 'fullname' => new external_value(PARAM_NOTAGS, 'The fullname of the user'), | |
210 | 'email' => new external_value(PARAM_TEXT, 'Email address', VALUE_OPTIONAL), | |
211 | 'address' => new external_value(PARAM_MULTILANG, 'Postal address', VALUE_OPTIONAL), | |
212 | 'phone1' => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL), | |
213 | 'phone2' => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL), | |
214 | 'icq' => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL), | |
215 | 'skype' => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL), | |
216 | 'yahoo' => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL), | |
217 | 'aim' => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL), | |
218 | 'msn' => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL), | |
219 | 'department' => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL), | |
220 | 'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL), | |
221 | 'interests' => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL), | |
222 | 'firstaccess' => new external_value(PARAM_INT, 'first access to the site (0 if never)', VALUE_OPTIONAL), | |
223 | 'lastaccess' => new external_value(PARAM_INT, 'last access to the site (0 if never)', VALUE_OPTIONAL), | |
1f87a7f6 | 224 | 'lastcourseaccess' => new external_value(PARAM_INT, 'last access to the course (0 if never)', VALUE_OPTIONAL), |
b6b6c7ac PC |
225 | 'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL), |
226 | 'descriptionformat' => new external_value(PARAM_INT, 'User profile description format', VALUE_OPTIONAL), | |
227 | 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), | |
228 | 'url' => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL), | |
229 | 'country' => new external_value(PARAM_ALPHA, 'Country code of the user, such as AU or CZ', VALUE_OPTIONAL), | |
230 | 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small', VALUE_OPTIONAL), | |
231 | 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big', VALUE_OPTIONAL), | |
232 | 'customfields' => new external_multiple_structure( | |
233 | new external_single_structure( | |
234 | array( | |
235 | 'type' => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field'), | |
236 | 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), | |
237 | 'name' => new external_value(PARAM_RAW, 'The name of the custom field'), | |
238 | 'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field'), | |
239 | ) | |
240 | ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL), | |
241 | 'groups' => new external_multiple_structure( | |
242 | new external_single_structure( | |
243 | array( | |
244 | 'id' => new external_value(PARAM_INT, 'group id'), | |
245 | 'name' => new external_value(PARAM_RAW, 'group name'), | |
246 | 'description' => new external_value(PARAM_RAW, 'group description'), | |
247 | ) | |
248 | ), 'user groups', VALUE_OPTIONAL), | |
249 | 'roles' => new external_multiple_structure( | |
250 | new external_single_structure( | |
251 | array( | |
252 | 'roleid' => new external_value(PARAM_INT, 'role id'), | |
253 | 'name' => new external_value(PARAM_RAW, 'role name'), | |
254 | 'shortname' => new external_value(PARAM_ALPHANUMEXT, 'role shortname'), | |
255 | 'sortorder' => new external_value(PARAM_INT, 'role sortorder') | |
256 | ) | |
257 | ), 'user roles', VALUE_OPTIONAL), | |
258 | 'preferences' => new external_multiple_structure( | |
259 | new external_single_structure( | |
260 | array( | |
abdb8f59 | 261 | 'name' => new external_value(PARAM_RAW, 'The name of the preferences'), |
b6b6c7ac PC |
262 | 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), |
263 | ) | |
264 | ), 'User preferences', VALUE_OPTIONAL), | |
265 | 'enrolledcourses' => new external_multiple_structure( | |
266 | new external_single_structure( | |
267 | array( | |
268 | 'id' => new external_value(PARAM_INT, 'Id of the course'), | |
269 | 'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'), | |
270 | 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course') | |
271 | ) | |
272 | ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL) | |
273 | ) | |
274 | ), 'List of users that are enrolled in the course and have the specified capability'), | |
275 | ) | |
276 | ) | |
277 | ); | |
278 | } | |
279 | ||
5d1017e1 JM |
280 | /** |
281 | * Returns description of method parameters | |
4615817d | 282 | * |
5d1017e1 JM |
283 | * @return external_function_parameters |
284 | */ | |
285 | public static function get_users_courses_parameters() { | |
286 | return new external_function_parameters( | |
287 | array( | |
288 | 'userid' => new external_value(PARAM_INT, 'user id'), | |
7d4c3458 MJ |
289 | 'returnusercount' => new external_value(PARAM_BOOL, |
290 | 'Include count of enrolled users for each course? This can add several seconds to the response time' | |
291 | . ' if a user is on several large courses, so set this to false if the value will not be used to' | |
292 | . ' improve performance.', | |
293 | VALUE_DEFAULT, true), | |
5d1017e1 JM |
294 | ) |
295 | ); | |
296 | } | |
297 | ||
298 | /** | |
299 | * Get list of courses user is enrolled in (only active enrolments are returned). | |
5d1017e1 JM |
300 | * Please note the current user must be able to access the course, otherwise the course is not included. |
301 | * | |
302 | * @param int $userid | |
7d4c3458 | 303 | * @param bool $returnusercount |
5d1017e1 JM |
304 | * @return array of courses |
305 | */ | |
7d4c3458 | 306 | public static function get_users_courses($userid, $returnusercount = true) { |
93b47710 MN |
307 | global $CFG, $USER, $DB; |
308 | ||
309 | require_once($CFG->dirroot . '/course/lib.php'); | |
b36ee81e | 310 | require_once($CFG->libdir . '/completionlib.php'); |
5d1017e1 JM |
311 | |
312 | // Do basic automatic PARAM checks on incoming data, using params description | |
313 | // If any problems are found then exceptions are thrown with helpful error messages | |
7d4c3458 MJ |
314 | $params = self::validate_parameters(self::get_users_courses_parameters(), |
315 | ['userid' => $userid, 'returnusercount' => $returnusercount]); | |
8e7b8cf0 | 316 | $userid = $params['userid']; |
7d4c3458 | 317 | $returnusercount = $params['returnusercount']; |
5d1017e1 | 318 | |
8e7b8cf0 | 319 | $courses = enrol_get_users_courses($userid, true, '*'); |
5d1017e1 JM |
320 | $result = array(); |
321 | ||
b36ee81e JL |
322 | // Get user data including last access to courses. |
323 | $user = get_complete_user_data('id', $userid); | |
8e7b8cf0 JL |
324 | $sameuser = $USER->id == $userid; |
325 | ||
326 | // Retrieve favourited courses (starred). | |
327 | $favouritecourseids = array(); | |
328 | if ($sameuser) { | |
329 | $ufservice = \core_favourites\service_factory::get_service_for_user_context(\context_user::instance($userid)); | |
330 | $favourites = $ufservice->find_favourites_by_type('core_course', 'courses'); | |
331 | ||
332 | if ($favourites) { | |
333 | $favouritecourseids = array_flip(array_map( | |
334 | function($favourite) { | |
335 | return $favourite->itemid; | |
336 | }, $favourites)); | |
337 | } | |
338 | } | |
b36ee81e | 339 | |
5d1017e1 | 340 | foreach ($courses as $course) { |
55bcef29 | 341 | $context = context_course::instance($course->id, IGNORE_MISSING); |
5d1017e1 JM |
342 | try { |
343 | self::validate_context($context); | |
344 | } catch (Exception $e) { | |
345 | // current user can not access this course, sorry we can not disclose who is enrolled in this course! | |
346 | continue; | |
347 | } | |
ad7612f5 | 348 | |
b36ee81e | 349 | if (!$sameuser and !course_can_view_participants($context)) { |
5d1017e1 JM |
350 | // we need capability to view participants |
351 | continue; | |
352 | } | |
353 | ||
7d4c3458 MJ |
354 | if ($returnusercount) { |
355 | list($enrolledsqlselect, $enrolledparams) = get_enrolled_sql($context); | |
356 | $enrolledsql = "SELECT COUNT('x') FROM ($enrolledsqlselect) enrolleduserids"; | |
357 | $enrolledusercount = $DB->count_records_sql($enrolledsql, $enrolledparams); | |
358 | } | |
ad7612f5 | 359 | |
b36ee81e | 360 | $displayname = external_format_string(get_course_display_name_for_list($course), $context->id); |
170717e2 | 361 | list($course->summary, $course->summaryformat) = |
1d3e9546 | 362 | external_format_text($course->summary, $course->summaryformat, $context->id, 'course', 'summary', null); |
d889b587 JL |
363 | $course->fullname = external_format_string($course->fullname, $context->id); |
364 | $course->shortname = external_format_string($course->shortname, $context->id); | |
170717e2 | 365 | |
80ece084 | 366 | $progress = null; |
b36ee81e | 367 | $completed = null; |
8e7b8cf0 | 368 | $completionhascriteria = false; |
dfcf8342 | 369 | $completionusertracked = false; |
b36ee81e JL |
370 | |
371 | // Return only private information if the user should be able to see it. | |
372 | if ($sameuser || completion_can_view_data($userid, $course)) { | |
373 | if ($course->enablecompletion) { | |
374 | $completion = new completion_info($course); | |
375 | $completed = $completion->is_course_complete($userid); | |
8e7b8cf0 | 376 | $completionhascriteria = $completion->has_criteria(); |
dfcf8342 | 377 | $completionusertracked = $completion->is_tracked_user($userid); |
b36ee81e JL |
378 | $progress = \core_completion\progress::get_course_progress_percentage($course, $userid); |
379 | } | |
380 | } | |
381 | ||
382 | $lastaccess = null; | |
383 | // Check if last access is a hidden field. | |
384 | $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); | |
385 | $canviewlastaccess = $sameuser || !isset($hiddenfields['lastaccess']); | |
386 | if (!$canviewlastaccess) { | |
387 | $canviewlastaccess = has_capability('moodle/course:viewhiddenuserfields', $context); | |
388 | } | |
389 | ||
390 | if ($canviewlastaccess && isset($user->lastcourseaccess[$course->id])) { | |
391 | $lastaccess = $user->lastcourseaccess[$course->id]; | |
392 | } | |
393 | ||
8e7b8cf0 JL |
394 | $hidden = false; |
395 | if ($sameuser) { | |
396 | $hidden = boolval(get_user_preferences('block_myoverview_hidden_course_' . $course->id, 0)); | |
397 | } | |
398 | ||
b36ee81e JL |
399 | // Retrieve course overview used files. |
400 | $courselist = new core_course_list_element($course); | |
401 | $overviewfiles = array(); | |
402 | foreach ($courselist->get_course_overviewfiles() as $file) { | |
403 | $fileurl = moodle_url::make_webservice_pluginfile_url($file->get_contextid(), $file->get_component(), | |
404 | $file->get_filearea(), null, $file->get_filepath(), | |
405 | $file->get_filename())->out(false); | |
406 | $overviewfiles[] = array( | |
407 | 'filename' => $file->get_filename(), | |
408 | 'fileurl' => $fileurl, | |
409 | 'filesize' => $file->get_filesize(), | |
410 | 'filepath' => $file->get_filepath(), | |
411 | 'mimetype' => $file->get_mimetype(), | |
412 | 'timemodified' => $file->get_timemodified(), | |
413 | ); | |
80ece084 AN |
414 | } |
415 | ||
7d4c3458 | 416 | $courseresult = [ |
27c7ed0b JL |
417 | 'id' => $course->id, |
418 | 'shortname' => $course->shortname, | |
419 | 'fullname' => $course->fullname, | |
b36ee81e | 420 | 'displayname' => $displayname, |
27c7ed0b JL |
421 | 'idnumber' => $course->idnumber, |
422 | 'visible' => $course->visible, | |
27c7ed0b JL |
423 | 'summary' => $course->summary, |
424 | 'summaryformat' => $course->summaryformat, | |
425 | 'format' => $course->format, | |
426 | 'showgrades' => $course->showgrades, | |
6db24235 | 427 | 'lang' => clean_param($course->lang, PARAM_LANG), |
27c7ed0b | 428 | 'enablecompletion' => $course->enablecompletion, |
8e7b8cf0 | 429 | 'completionhascriteria' => $completionhascriteria, |
dfcf8342 | 430 | 'completionusertracked' => $completionusertracked, |
80ece084 AN |
431 | 'category' => $course->category, |
432 | 'progress' => $progress, | |
b36ee81e | 433 | 'completed' => $completed, |
01c26702 JL |
434 | 'startdate' => $course->startdate, |
435 | 'enddate' => $course->enddate, | |
b36ee81e JL |
436 | 'marker' => $course->marker, |
437 | 'lastaccess' => $lastaccess, | |
8e7b8cf0 JL |
438 | 'isfavourite' => isset($favouritecourseids[$course->id]), |
439 | 'hidden' => $hidden, | |
b36ee81e | 440 | 'overviewfiles' => $overviewfiles, |
7d4c3458 MJ |
441 | ]; |
442 | if ($returnusercount) { | |
443 | $courseresult['enrolledusercount'] = $enrolledusercount; | |
444 | } | |
445 | $result[] = $courseresult; | |
5d1017e1 | 446 | } |
df997f84 | 447 | |
5d1017e1 JM |
448 | return $result; |
449 | } | |
450 | ||
451 | /** | |
452 | * Returns description of method result value | |
4615817d | 453 | * |
5d1017e1 JM |
454 | * @return external_description |
455 | */ | |
456 | public static function get_users_courses_returns() { | |
457 | return new external_multiple_structure( | |
458 | new external_single_structure( | |
459 | array( | |
460 | 'id' => new external_value(PARAM_INT, 'id of course'), | |
461 | 'shortname' => new external_value(PARAM_RAW, 'short name of course'), | |
462 | 'fullname' => new external_value(PARAM_RAW, 'long name of course'), | |
b36ee81e | 463 | 'displayname' => new external_value(PARAM_TEXT, 'course display name for lists.', VALUE_OPTIONAL), |
7d4c3458 MJ |
464 | 'enrolledusercount' => new external_value(PARAM_INT, 'Number of enrolled users in this course', |
465 | VALUE_OPTIONAL), | |
5d1017e1 | 466 | 'idnumber' => new external_value(PARAM_RAW, 'id number of course'), |
8e7b8cf0 | 467 | 'visible' => new external_value(PARAM_INT, '1 means visible, 0 means not yet visible course'), |
170717e2 CC |
468 | 'summary' => new external_value(PARAM_RAW, 'summary', VALUE_OPTIONAL), |
469 | 'summaryformat' => new external_format_value('summary', VALUE_OPTIONAL), | |
470 | 'format' => new external_value(PARAM_PLUGIN, 'course format: weeks, topics, social, site', VALUE_OPTIONAL), | |
471 | 'showgrades' => new external_value(PARAM_BOOL, 'true if grades are shown, otherwise false', VALUE_OPTIONAL), | |
472 | 'lang' => new external_value(PARAM_LANG, 'forced course language', VALUE_OPTIONAL), | |
ba62015b | 473 | 'enablecompletion' => new external_value(PARAM_BOOL, 'true if completion is enabled, otherwise false', |
27c7ed0b | 474 | VALUE_OPTIONAL), |
8e7b8cf0 | 475 | 'completionhascriteria' => new external_value(PARAM_BOOL, 'If completion criteria is set.', VALUE_OPTIONAL), |
dfcf8342 | 476 | 'completionusertracked' => new external_value(PARAM_BOOL, 'If the user is completion tracked.', VALUE_OPTIONAL), |
27c7ed0b | 477 | 'category' => new external_value(PARAM_INT, 'course category id', VALUE_OPTIONAL), |
80ece084 | 478 | 'progress' => new external_value(PARAM_FLOAT, 'Progress percentage', VALUE_OPTIONAL), |
b36ee81e | 479 | 'completed' => new external_value(PARAM_BOOL, 'Whether the course is completed.', VALUE_OPTIONAL), |
01c26702 JL |
480 | 'startdate' => new external_value(PARAM_INT, 'Timestamp when the course start', VALUE_OPTIONAL), |
481 | 'enddate' => new external_value(PARAM_INT, 'Timestamp when the course end', VALUE_OPTIONAL), | |
b36ee81e JL |
482 | 'marker' => new external_value(PARAM_INT, 'Course section marker.', VALUE_OPTIONAL), |
483 | 'lastaccess' => new external_value(PARAM_INT, 'Last access to the course (timestamp).', VALUE_OPTIONAL), | |
8e7b8cf0 JL |
484 | 'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked this course a favourite.', VALUE_OPTIONAL), |
485 | 'hidden' => new external_value(PARAM_BOOL, 'If the user hide the course from the dashboard.', VALUE_OPTIONAL), | |
b36ee81e | 486 | 'overviewfiles' => new external_files('Overview files attached to this course.', VALUE_OPTIONAL), |
5d1017e1 JM |
487 | ) |
488 | ) | |
489 | ); | |
490 | } | |
e6acc551 | 491 | |
a60e8ba5 DW |
492 | /** |
493 | * Returns description of method parameters value | |
494 | * | |
495 | * @return external_description | |
496 | */ | |
497 | public static function get_potential_users_parameters() { | |
498 | return new external_function_parameters( | |
499 | array( | |
500 | 'courseid' => new external_value(PARAM_INT, 'course id'), | |
501 | 'enrolid' => new external_value(PARAM_INT, 'enrolment id'), | |
502 | 'search' => new external_value(PARAM_RAW, 'query'), | |
503 | 'searchanywhere' => new external_value(PARAM_BOOL, 'find a match anywhere, or only at the beginning'), | |
504 | 'page' => new external_value(PARAM_INT, 'Page number'), | |
505 | 'perpage' => new external_value(PARAM_INT, 'Number per page'), | |
506 | ) | |
507 | ); | |
508 | } | |
509 | ||
510 | /** | |
511 | * Get potential users. | |
512 | * | |
513 | * @param int $courseid Course id | |
514 | * @param int $enrolid Enrolment id | |
515 | * @param string $search The query | |
516 | * @param boolean $searchanywhere Match anywhere in the string | |
517 | * @param int $page Page number | |
518 | * @param int $perpage Max per page | |
519 | * @return array An array of users | |
520 | */ | |
521 | public static function get_potential_users($courseid, $enrolid, $search, $searchanywhere, $page, $perpage) { | |
0fa35b1a DW |
522 | global $PAGE, $DB, $CFG; |
523 | ||
524 | require_once($CFG->dirroot.'/enrol/locallib.php'); | |
525 | require_once($CFG->dirroot.'/user/lib.php'); | |
a60e8ba5 DW |
526 | |
527 | $params = self::validate_parameters( | |
528 | self::get_potential_users_parameters(), | |
529 | array( | |
530 | 'courseid' => $courseid, | |
531 | 'enrolid' => $enrolid, | |
532 | 'search' => $search, | |
533 | 'searchanywhere' => $searchanywhere, | |
534 | 'page' => $page, | |
535 | 'perpage' => $perpage | |
536 | ) | |
537 | ); | |
538 | $context = context_course::instance($params['courseid']); | |
0fa35b1a DW |
539 | try { |
540 | self::validate_context($context); | |
541 | } catch (Exception $e) { | |
542 | $exceptionparam = new stdClass(); | |
543 | $exceptionparam->message = $e->getMessage(); | |
544 | $exceptionparam->courseid = $params['courseid']; | |
545 | throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); | |
546 | } | |
a60e8ba5 DW |
547 | require_capability('moodle/course:enrolreview', $context); |
548 | ||
549 | $course = $DB->get_record('course', array('id' => $params['courseid'])); | |
550 | $manager = new course_enrolment_manager($PAGE, $course); | |
551 | ||
552 | $users = $manager->get_potential_users($params['enrolid'], | |
553 | $params['search'], | |
554 | $params['searchanywhere'], | |
555 | $params['page'], | |
556 | $params['perpage']); | |
557 | ||
558 | $results = array(); | |
46ea440b SA |
559 | // Add also extra user fields. |
560 | $requiredfields = array_merge( | |
561 | ['id', 'fullname', 'profileimageurl', 'profileimageurlsmall'], | |
562 | get_extra_user_fields($context) | |
563 | ); | |
0fa35b1a | 564 | foreach ($users['users'] as $id => $user) { |
2cc2001b DW |
565 | // Note: We pass the course here to validate that the current user can at least view user details in this course. |
566 | // The user we are looking at is not in this course yet though - but we only fetch the minimal set of | |
567 | // user records, and the user has been validated to have course:enrolreview in this course. Otherwise | |
568 | // there is no way to find users who aren't in the course in order to enrol them. | |
af6d2385 | 569 | if ($userdetails = user_get_user_details($user, $course, $requiredfields)) { |
a60e8ba5 DW |
570 | $results[] = $userdetails; |
571 | } | |
572 | } | |
573 | return $results; | |
574 | } | |
575 | ||
576 | /** | |
577 | * Returns description of method result value | |
578 | * | |
579 | * @return external_description | |
580 | */ | |
581 | public static function get_potential_users_returns() { | |
582 | global $CFG; | |
583 | require_once($CFG->dirroot . '/user/externallib.php'); | |
584 | return new external_multiple_structure(core_user_external::user_description()); | |
585 | } | |
586 | ||
0f308fcd SR |
587 | /** |
588 | * Returns description of method parameters | |
589 | * | |
590 | * @return external_function_parameters | |
591 | */ | |
592 | public static function search_users_parameters(): external_function_parameters { | |
593 | return new external_function_parameters( | |
594 | [ | |
595 | 'courseid' => new external_value(PARAM_INT, 'course id'), | |
596 | 'search' => new external_value(PARAM_RAW, 'query'), | |
597 | 'searchanywhere' => new external_value(PARAM_BOOL, 'find a match anywhere, or only at the beginning'), | |
598 | 'page' => new external_value(PARAM_INT, 'Page number'), | |
599 | 'perpage' => new external_value(PARAM_INT, 'Number per page'), | |
600 | ] | |
601 | ); | |
602 | } | |
603 | ||
604 | /** | |
605 | * Search course participants. | |
606 | * | |
607 | * @param int $courseid Course id | |
608 | * @param string $search The query | |
609 | * @param bool $searchanywhere Match anywhere in the string | |
610 | * @param int $page Page number | |
611 | * @param int $perpage Max per page | |
612 | * @return array An array of users | |
613 | * @throws moodle_exception | |
614 | */ | |
615 | public static function search_users(int $courseid, string $search, bool $searchanywhere, int $page, int $perpage): array { | |
616 | global $PAGE, $DB, $CFG; | |
617 | ||
618 | require_once($CFG->dirroot.'/enrol/locallib.php'); | |
619 | require_once($CFG->dirroot.'/user/lib.php'); | |
620 | ||
621 | $params = self::validate_parameters( | |
622 | self::search_users_parameters(), | |
623 | [ | |
624 | 'courseid' => $courseid, | |
625 | 'search' => $search, | |
626 | 'searchanywhere' => $searchanywhere, | |
627 | 'page' => $page, | |
628 | 'perpage' => $perpage | |
629 | ] | |
630 | ); | |
631 | $context = context_course::instance($params['courseid']); | |
632 | try { | |
633 | self::validate_context($context); | |
634 | } catch (Exception $e) { | |
635 | $exceptionparam = new stdClass(); | |
636 | $exceptionparam->message = $e->getMessage(); | |
637 | $exceptionparam->courseid = $params['courseid']; | |
638 | throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); | |
639 | } | |
640 | course_require_view_participants($context); | |
641 | ||
642 | $course = $DB->get_record('course', ['id' => $params['courseid']]); | |
643 | $manager = new course_enrolment_manager($PAGE, $course); | |
644 | ||
645 | $users = $manager->search_users($params['search'], | |
646 | $params['searchanywhere'], | |
647 | $params['page'], | |
648 | $params['perpage']); | |
649 | ||
650 | $results = []; | |
651 | // Add also extra user fields. | |
652 | $requiredfields = array_merge( | |
653 | ['id', 'fullname', 'profileimageurl', 'profileimageurlsmall'], | |
654 | get_extra_user_fields($context) | |
655 | ); | |
656 | foreach ($users['users'] as $user) { | |
657 | // Note: We pass the course here to validate that the current user can at least view user details in this course. | |
658 | // The user we are looking at is not in this course yet though - but we only fetch the minimal set of | |
659 | // user records, and the user has been validated to have course:enrolreview in this course. Otherwise | |
660 | // there is no way to find users who aren't in the course in order to enrol them. | |
661 | if ($userdetails = user_get_user_details($user, $course, $requiredfields)) { | |
662 | $results[] = $userdetails; | |
663 | } | |
664 | } | |
665 | return $results; | |
666 | } | |
667 | ||
668 | /** | |
669 | * Returns description of method result value | |
670 | * | |
671 | * @return external_multiple_structure | |
672 | */ | |
673 | public static function search_users_returns(): external_multiple_structure { | |
674 | global $CFG; | |
675 | require_once($CFG->dirroot . '/user/externallib.php'); | |
676 | return new external_multiple_structure(core_user_external::user_description()); | |
677 | } | |
678 | ||
5d1017e1 JM |
679 | /** |
680 | * Returns description of method parameters | |
4615817d | 681 | * |
5d1017e1 JM |
682 | * @return external_function_parameters |
683 | */ | |
684 | public static function get_enrolled_users_parameters() { | |
685 | return new external_function_parameters( | |
686 | array( | |
687 | 'courseid' => new external_value(PARAM_INT, 'course id'), | |
688 | 'options' => new external_multiple_structure( | |
689 | new external_single_structure( | |
690 | array( | |
691 | 'name' => new external_value(PARAM_ALPHANUMEXT, 'option name'), | |
692 | 'value' => new external_value(PARAM_RAW, 'option value') | |
693 | ) | |
3ed74dd1 DC |
694 | ), 'Option names: |
695 | * withcapability (string) return only users with this capability. This option requires \'moodle/role:review\' on the course context. | |
b036215a DP |
696 | * groupid (integer) return only users in this group id. If the course has groups enabled and this param |
697 | isn\'t defined, returns all the viewable users. | |
698 | This option requires \'moodle/site:accessallgroups\' on the course context if the | |
699 | user doesn\'t belong to the group. | |
3ed74dd1 DC |
700 | * onlyactive (integer) return only users with active enrolments and matching time restrictions. This option requires \'moodle/course:enrolreview\' on the course context. |
701 | * userfields (\'string, string, ...\') return only the values of these user fields. | |
702 | * limitfrom (integer) sql limit from. | |
4bc38ba9 JL |
703 | * limitnumber (integer) maximum number of returned users. |
704 | * sortby (string) sort by id, firstname or lastname. For ordering like the site does, use siteorder. | |
705 | * sortdirection (string) ASC or DESC', | |
706 | VALUE_DEFAULT, array()), | |
5d1017e1 JM |
707 | ) |
708 | ); | |
709 | } | |
710 | ||
711 | /** | |
712 | * Get course participants details | |
4615817d | 713 | * |
5d1017e1 JM |
714 | * @param int $courseid course id |
715 | * @param array $options options { | |
4615817d JM |
716 | * 'name' => option name |
717 | * 'value' => option value | |
718 | * } | |
5d1017e1 JM |
719 | * @return array An array of users |
720 | */ | |
3297d575 | 721 | public static function get_enrolled_users($courseid, $options = array()) { |
5d1017e1 | 722 | global $CFG, $USER, $DB; |
93b47710 MN |
723 | |
724 | require_once($CFG->dirroot . '/course/lib.php'); | |
5d1017e1 JM |
725 | require_once($CFG->dirroot . "/user/lib.php"); |
726 | ||
727 | $params = self::validate_parameters( | |
f4a75854 | 728 | self::get_enrolled_users_parameters(), |
5d1017e1 JM |
729 | array( |
730 | 'courseid'=>$courseid, | |
731 | 'options'=>$options | |
732 | ) | |
733 | ); | |
734 | $withcapability = ''; | |
735 | $groupid = 0; | |
736 | $onlyactive = false; | |
ad7612f5 | 737 | $userfields = array(); |
3ed74dd1 DC |
738 | $limitfrom = 0; |
739 | $limitnumber = 0; | |
4bc38ba9 JL |
740 | $sortby = 'us.id'; |
741 | $sortparams = array(); | |
742 | $sortdirection = 'ASC'; | |
5d1017e1 JM |
743 | foreach ($options as $option) { |
744 | switch ($option['name']) { | |
745 | case 'withcapability': | |
746 | $withcapability = $option['value']; | |
747 | break; | |
748 | case 'groupid': | |
749 | $groupid = (int)$option['value']; | |
750 | break; | |
751 | case 'onlyactive': | |
752 | $onlyactive = !empty($option['value']); | |
753 | break; | |
ad7612f5 DC |
754 | case 'userfields': |
755 | $thefields = explode(',', $option['value']); | |
756 | foreach ($thefields as $f) { | |
757 | $userfields[] = clean_param($f, PARAM_ALPHANUMEXT); | |
758 | } | |
457b82f2 | 759 | break; |
3ed74dd1 DC |
760 | case 'limitfrom' : |
761 | $limitfrom = clean_param($option['value'], PARAM_INT); | |
762 | break; | |
763 | case 'limitnumber' : | |
764 | $limitnumber = clean_param($option['value'], PARAM_INT); | |
ad7612f5 | 765 | break; |
4bc38ba9 JL |
766 | case 'sortby': |
767 | $sortallowedvalues = array('id', 'firstname', 'lastname', 'siteorder'); | |
768 | if (!in_array($option['value'], $sortallowedvalues)) { | |
769 | throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $option['value'] . '),' . | |
770 | 'allowed values are: ' . implode(',', $sortallowedvalues)); | |
771 | } | |
772 | if ($option['value'] == 'siteorder') { | |
773 | list($sortby, $sortparams) = users_order_by_sql('us'); | |
774 | } else { | |
775 | $sortby = 'us.' . $option['value']; | |
776 | } | |
777 | break; | |
778 | case 'sortdirection': | |
779 | $sortdirection = strtoupper($option['value']); | |
780 | $directionallowedvalues = array('ASC', 'DESC'); | |
781 | if (!in_array($sortdirection, $directionallowedvalues)) { | |
782 | throw new invalid_parameter_exception('Invalid value for sortdirection parameter | |
783 | (value: ' . $sortdirection . '),' . 'allowed values are: ' . implode(',', $directionallowedvalues)); | |
784 | } | |
785 | break; | |
5d1017e1 JM |
786 | } |
787 | } | |
788 | ||
74df2951 | 789 | $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST); |
55bcef29 | 790 | $coursecontext = context_course::instance($courseid, IGNORE_MISSING); |
5d1017e1 | 791 | if ($courseid == SITEID) { |
0601e0ee | 792 | $context = context_system::instance(); |
5d1017e1 JM |
793 | } else { |
794 | $context = $coursecontext; | |
795 | } | |
796 | try { | |
797 | self::validate_context($context); | |
798 | } catch (Exception $e) { | |
799 | $exceptionparam = new stdClass(); | |
800 | $exceptionparam->message = $e->getMessage(); | |
801 | $exceptionparam->courseid = $params['courseid']; | |
96d3b93b | 802 | throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); |
5d1017e1 JM |
803 | } |
804 | ||
93b47710 MN |
805 | course_require_view_participants($context); |
806 | ||
d5b68e28 PS |
807 | // to overwrite this parameter, you need role:review capability |
808 | if ($withcapability) { | |
809 | require_capability('moodle/role:review', $coursecontext); | |
810 | } | |
811 | // need accessallgroups capability if you want to overwrite this option | |
b036215a | 812 | if (!empty($groupid) && !groups_is_member($groupid)) { |
d5b68e28 PS |
813 | require_capability('moodle/site:accessallgroups', $coursecontext); |
814 | } | |
815 | // to overwrite this option, you need course:enrolereview permission | |
816 | if ($onlyactive) { | |
817 | require_capability('moodle/course:enrolreview', $coursecontext); | |
818 | } | |
819 | ||
5d1017e1 | 820 | list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext, $withcapability, $groupid, $onlyactive); |
2e4c0c91 FM |
821 | $ctxselect = ', ' . context_helper::get_preload_record_columns_sql('ctx'); |
822 | $ctxjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel)"; | |
823 | $enrolledparams['contextlevel'] = CONTEXT_USER; | |
b036215a DP |
824 | |
825 | $groupjoin = ''; | |
826 | if (empty($groupid) && groups_get_course_groupmode($course) == SEPARATEGROUPS && | |
827 | !has_capability('moodle/site:accessallgroups', $coursecontext)) { | |
828 | // Filter by groups the user can view. | |
829 | $usergroups = groups_get_user_groups($course->id); | |
830 | if (!empty($usergroups['0'])) { | |
831 | list($groupsql, $groupparams) = $DB->get_in_or_equal($usergroups['0'], SQL_PARAMS_NAMED); | |
832 | $groupjoin = "JOIN {groups_members} gm ON (u.id = gm.userid AND gm.groupid $groupsql)"; | |
833 | $enrolledparams = array_merge($enrolledparams, $groupparams); | |
834 | } else { | |
835 | // User doesn't belong to any group, so he can't see any user. Return an empty array. | |
836 | return array(); | |
837 | } | |
838 | } | |
1f87a7f6 | 839 | $sql = "SELECT us.*, COALESCE(ul.timeaccess, 0) AS lastcourseaccess |
b036215a DP |
840 | FROM {user} us |
841 | JOIN ( | |
842 | SELECT DISTINCT u.id $ctxselect | |
843 | FROM {user} u $ctxjoin $groupjoin | |
844 | WHERE u.id IN ($enrolledsql) | |
845 | ) q ON q.id = us.id | |
1f87a7f6 | 846 | LEFT JOIN {user_lastaccess} ul ON (ul.userid = us.id AND ul.courseid = :courseid) |
4bc38ba9 JL |
847 | ORDER BY $sortby $sortdirection"; |
848 | $enrolledparams = array_merge($enrolledparams, $sortparams); | |
1f87a7f6 JL |
849 | $enrolledparams['courseid'] = $courseid; |
850 | ||
3ed74dd1 | 851 | $enrolledusers = $DB->get_recordset_sql($sql, $enrolledparams, $limitfrom, $limitnumber); |
5d1017e1 JM |
852 | $users = array(); |
853 | foreach ($enrolledusers as $user) { | |
db314f34 | 854 | context_helper::preload_from_record($user); |
ad7612f5 | 855 | if ($userdetails = user_get_user_details($user, $course, $userfields)) { |
5d1017e1 JM |
856 | $users[] = $userdetails; |
857 | } | |
858 | } | |
859 | $enrolledusers->close(); | |
860 | ||
861 | return $users; | |
862 | } | |
e6acc551 | 863 | |
5d1017e1 JM |
864 | /** |
865 | * Returns description of method result value | |
4615817d | 866 | * |
5d1017e1 JM |
867 | * @return external_description |
868 | */ | |
869 | public static function get_enrolled_users_returns() { | |
870 | return new external_multiple_structure( | |
871 | new external_single_structure( | |
872 | array( | |
61cca0b7 | 873 | 'id' => new external_value(PARAM_INT, 'ID of the user'), |
5d1017e1 JM |
874 | 'username' => new external_value(PARAM_RAW, 'Username policy is defined in Moodle security config', VALUE_OPTIONAL), |
875 | 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL), | |
876 | 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), | |
877 | 'fullname' => new external_value(PARAM_NOTAGS, 'The fullname of the user'), | |
878 | 'email' => new external_value(PARAM_TEXT, 'An email address - allow email as root@localhost', VALUE_OPTIONAL), | |
071e68f9 | 879 | 'address' => new external_value(PARAM_TEXT, 'Postal address', VALUE_OPTIONAL), |
5d1017e1 JM |
880 | 'phone1' => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL), |
881 | 'phone2' => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL), | |
882 | 'icq' => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL), | |
883 | 'skype' => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL), | |
884 | 'yahoo' => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL), | |
885 | 'aim' => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL), | |
886 | 'msn' => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL), | |
887 | 'department' => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL), | |
888 | 'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL), | |
3a3f3b22 | 889 | 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), |
5d1017e1 JM |
890 | 'interests' => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL), |
891 | 'firstaccess' => new external_value(PARAM_INT, 'first access to the site (0 if never)', VALUE_OPTIONAL), | |
892 | 'lastaccess' => new external_value(PARAM_INT, 'last access to the site (0 if never)', VALUE_OPTIONAL), | |
1f87a7f6 | 893 | 'lastcourseaccess' => new external_value(PARAM_INT, 'last access to the course (0 if never)', VALUE_OPTIONAL), |
5d1017e1 | 894 | 'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL), |
93ce0e82 | 895 | 'descriptionformat' => new external_format_value('description', VALUE_OPTIONAL), |
5d1017e1 JM |
896 | 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), |
897 | 'url' => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL), | |
898 | 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), | |
ad7612f5 DC |
899 | 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version', VALUE_OPTIONAL), |
900 | 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version', VALUE_OPTIONAL), | |
5d1017e1 JM |
901 | 'customfields' => new external_multiple_structure( |
902 | new external_single_structure( | |
903 | array( | |
904 | 'type' => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'), | |
905 | 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), | |
906 | 'name' => new external_value(PARAM_RAW, 'The name of the custom field'), | |
907 | 'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'), | |
908 | ) | |
909 | ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL), | |
910 | 'groups' => new external_multiple_structure( | |
911 | new external_single_structure( | |
912 | array( | |
913 | 'id' => new external_value(PARAM_INT, 'group id'), | |
914 | 'name' => new external_value(PARAM_RAW, 'group name'), | |
915 | 'description' => new external_value(PARAM_RAW, 'group description'), | |
93ce0e82 | 916 | 'descriptionformat' => new external_format_value('description'), |
5d1017e1 JM |
917 | ) |
918 | ), 'user groups', VALUE_OPTIONAL), | |
919 | 'roles' => new external_multiple_structure( | |
920 | new external_single_structure( | |
921 | array( | |
922 | 'roleid' => new external_value(PARAM_INT, 'role id'), | |
923 | 'name' => new external_value(PARAM_RAW, 'role name'), | |
924 | 'shortname' => new external_value(PARAM_ALPHANUMEXT, 'role shortname'), | |
925 | 'sortorder' => new external_value(PARAM_INT, 'role sortorder') | |
926 | ) | |
927 | ), 'user roles', VALUE_OPTIONAL), | |
928 | 'preferences' => new external_multiple_structure( | |
929 | new external_single_structure( | |
930 | array( | |
abdb8f59 | 931 | 'name' => new external_value(PARAM_RAW, 'The name of the preferences'), |
5d1017e1 JM |
932 | 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), |
933 | ) | |
934 | ), 'User preferences', VALUE_OPTIONAL), | |
935 | 'enrolledcourses' => new external_multiple_structure( | |
936 | new external_single_structure( | |
937 | array( | |
938 | 'id' => new external_value(PARAM_INT, 'Id of the course'), | |
939 | 'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'), | |
940 | 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course') | |
941 | ) | |
942 | ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL) | |
943 | ) | |
944 | ) | |
945 | ); | |
946 | } | |
947 | ||
be9bf94e RT |
948 | /** |
949 | * Returns description of get_course_enrolment_methods() parameters | |
950 | * | |
951 | * @return external_function_parameters | |
952 | */ | |
953 | public static function get_course_enrolment_methods_parameters() { | |
954 | return new external_function_parameters( | |
955 | array( | |
956 | 'courseid' => new external_value(PARAM_INT, 'Course id') | |
957 | ) | |
958 | ); | |
959 | } | |
960 | ||
961 | /** | |
962 | * Get list of active course enrolment methods for current user. | |
963 | * | |
964 | * @param int $courseid | |
965 | * @return array of course enrolment methods | |
4323a973 | 966 | * @throws moodle_exception |
be9bf94e RT |
967 | */ |
968 | public static function get_course_enrolment_methods($courseid) { | |
4323a973 | 969 | global $DB; |
be9bf94e RT |
970 | |
971 | $params = self::validate_parameters(self::get_course_enrolment_methods_parameters(), array('courseid' => $courseid)); | |
67ee1030 | 972 | self::validate_context(context_system::instance()); |
4323a973 JL |
973 | |
974 | $course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST); | |
beff3806 | 975 | if (!core_course_category::can_view_course_info($course) && !can_access_course($course)) { |
4323a973 JL |
976 | throw new moodle_exception('coursehidden'); |
977 | } | |
be9bf94e RT |
978 | |
979 | $result = array(); | |
980 | $enrolinstances = enrol_get_instances($params['courseid'], true); | |
981 | foreach ($enrolinstances as $enrolinstance) { | |
982 | if ($enrolplugin = enrol_get_plugin($enrolinstance->enrol)) { | |
983 | if ($instanceinfo = $enrolplugin->get_enrol_info($enrolinstance)) { | |
984 | $result[] = (array) $instanceinfo; | |
985 | } | |
986 | } | |
987 | } | |
988 | return $result; | |
989 | } | |
990 | ||
991 | /** | |
992 | * Returns description of get_course_enrolment_methods() result value | |
993 | * | |
994 | * @return external_description | |
995 | */ | |
996 | public static function get_course_enrolment_methods_returns() { | |
997 | return new external_multiple_structure( | |
998 | new external_single_structure( | |
999 | array( | |
1000 | 'id' => new external_value(PARAM_INT, 'id of course enrolment instance'), | |
1001 | 'courseid' => new external_value(PARAM_INT, 'id of course'), | |
1002 | 'type' => new external_value(PARAM_PLUGIN, 'type of enrolment plugin'), | |
1003 | 'name' => new external_value(PARAM_RAW, 'name of enrolment plugin'), | |
1004 | 'status' => new external_value(PARAM_RAW, 'status of enrolment plugin'), | |
1005 | 'wsfunction' => new external_value(PARAM_ALPHANUMEXT, 'webservice function to get more information', VALUE_OPTIONAL), | |
1006 | ) | |
1007 | ) | |
1008 | ); | |
1009 | } | |
58c20c81 JP |
1010 | |
1011 | /** | |
1012 | * Returns description of edit_user_enrolment() parameters | |
1013 | * | |
2d4ce64d | 1014 | * @deprecated since 3.8 |
58c20c81 JP |
1015 | * @return external_function_parameters |
1016 | */ | |
1017 | public static function edit_user_enrolment_parameters() { | |
1018 | return new external_function_parameters( | |
1019 | array( | |
1020 | 'courseid' => new external_value(PARAM_INT, 'User enrolment ID'), | |
1021 | 'ueid' => new external_value(PARAM_INT, 'User enrolment ID'), | |
1022 | 'status' => new external_value(PARAM_INT, 'Enrolment status'), | |
1023 | 'timestart' => new external_value(PARAM_INT, 'Enrolment start timestamp', VALUE_DEFAULT, 0), | |
1024 | 'timeend' => new external_value(PARAM_INT, 'Enrolment end timestamp', VALUE_DEFAULT, 0), | |
1025 | ) | |
1026 | ); | |
1027 | } | |
1028 | ||
1029 | /** | |
1030 | * External function that updates a given user enrolment. | |
1031 | * | |
2d4ce64d | 1032 | * @deprecated since 3.8 |
58c20c81 JP |
1033 | * @param int $courseid The course ID. |
1034 | * @param int $ueid The user enrolment ID. | |
1035 | * @param int $status The enrolment status. | |
1036 | * @param int $timestart Enrolment start timestamp. | |
1037 | * @param int $timeend Enrolment end timestamp. | |
1038 | * @return array An array consisting of the processing result, errors and form output, if available. | |
1039 | */ | |
1040 | public static function edit_user_enrolment($courseid, $ueid, $status, $timestart = 0, $timeend = 0) { | |
1041 | global $CFG, $DB, $PAGE; | |
1042 | ||
1043 | $params = self::validate_parameters(self::edit_user_enrolment_parameters(), [ | |
1044 | 'courseid' => $courseid, | |
1045 | 'ueid' => $ueid, | |
1046 | 'status' => $status, | |
1047 | 'timestart' => $timestart, | |
1048 | 'timeend' => $timeend, | |
1049 | ]); | |
1050 | ||
1051 | $course = get_course($courseid); | |
1052 | $context = context_course::instance($course->id); | |
1053 | self::validate_context($context); | |
1054 | ||
1055 | $userenrolment = $DB->get_record('user_enrolments', ['id' => $params['ueid']], '*', MUST_EXIST); | |
1056 | $userenroldata = [ | |
1057 | 'status' => $params['status'], | |
1058 | 'timestart' => $params['timestart'], | |
1059 | 'timeend' => $params['timeend'], | |
1060 | ]; | |
1061 | ||
1062 | $result = false; | |
1063 | $errors = []; | |
1064 | ||
1065 | // Validate data against the edit user enrolment form. | |
af835c24 MN |
1066 | $instance = $DB->get_record('enrol', ['id' => $userenrolment->enrolid], '*', MUST_EXIST); |
1067 | $plugin = enrol_get_plugin($instance->enrol); | |
58c20c81 JP |
1068 | require_once("$CFG->dirroot/enrol/editenrolment_form.php"); |
1069 | $customformdata = [ | |
1070 | 'ue' => $userenrolment, | |
1071 | 'modal' => true, | |
af835c24 | 1072 | 'enrolinstancename' => $plugin->get_instance_name($instance) |
58c20c81 JP |
1073 | ]; |
1074 | $mform = new \enrol_user_enrolment_form(null, $customformdata, 'post', '', null, true, $userenroldata); | |
1075 | $mform->set_data($userenroldata); | |
1076 | $validationerrors = $mform->validation($userenroldata, null); | |
1077 | if (empty($validationerrors)) { | |
1078 | require_once($CFG->dirroot . '/enrol/locallib.php'); | |
1079 | $manager = new course_enrolment_manager($PAGE, $course); | |
1080 | $result = $manager->edit_enrolment($userenrolment, (object)$userenroldata); | |
1081 | } else { | |
1082 | foreach ($validationerrors as $key => $errormessage) { | |
1083 | $errors[] = (object)[ | |
1084 | 'key' => $key, | |
1085 | 'message' => $errormessage | |
1086 | ]; | |
1087 | } | |
1088 | } | |
1089 | ||
1090 | return [ | |
1091 | 'result' => $result, | |
1092 | 'errors' => $errors, | |
1093 | ]; | |
1094 | } | |
1095 | ||
1096 | /** | |
1097 | * Returns description of edit_user_enrolment() result value | |
1098 | * | |
2d4ce64d | 1099 | * @deprecated since 3.8 |
58c20c81 JP |
1100 | * @return external_description |
1101 | */ | |
1102 | public static function edit_user_enrolment_returns() { | |
c8351261 MG |
1103 | return new external_single_structure( |
1104 | array( | |
1105 | 'result' => new external_value(PARAM_BOOL, 'True if the user\'s enrolment was successfully updated'), | |
1106 | 'errors' => new external_multiple_structure( | |
1107 | new external_single_structure( | |
1108 | array( | |
1109 | 'key' => new external_value(PARAM_TEXT, 'The data that failed the validation'), | |
1110 | 'message' => new external_value(PARAM_TEXT, 'The error message'), | |
1111 | ) | |
1112 | ), 'List of validation errors' | |
1113 | ), | |
1114 | ) | |
1115 | ); | |
1116 | } | |
1117 | ||
2d4ce64d SR |
1118 | /** |
1119 | * Mark the edit_user_enrolment web service as deprecated. | |
1120 | * | |
1121 | * @return bool | |
1122 | */ | |
1123 | public static function edit_user_enrolment_is_deprecated() { | |
1124 | return true; | |
1125 | } | |
1126 | ||
1127 | /** | |
1128 | * Returns description of submit_user_enrolment_form parameters. | |
1129 | * | |
1130 | * @return external_function_parameters. | |
1131 | */ | |
1132 | public static function submit_user_enrolment_form_parameters() { | |
1133 | return new external_function_parameters([ | |
1134 | 'formdata' => new external_value(PARAM_RAW, 'The data from the event form'), | |
1135 | ]); | |
1136 | } | |
1137 | ||
1138 | /** | |
1139 | * External function that handles the user enrolment form submission. | |
1140 | * | |
1141 | * @param string $formdata The user enrolment form data in s URI encoded param string | |
1142 | * @return array An array consisting of the processing result and error flag, if available | |
1143 | */ | |
1144 | public static function submit_user_enrolment_form($formdata) { | |
1145 | global $CFG, $DB, $PAGE; | |
1146 | ||
1147 | // Parameter validation. | |
1148 | $params = self::validate_parameters(self::submit_user_enrolment_form_parameters(), ['formdata' => $formdata]); | |
1149 | ||
1150 | $data = []; | |
1151 | parse_str($params['formdata'], $data); | |
1152 | ||
1153 | $userenrolment = $DB->get_record('user_enrolments', ['id' => $data['ue']], '*', MUST_EXIST); | |
1154 | $instance = $DB->get_record('enrol', ['id' => $userenrolment->enrolid], '*', MUST_EXIST); | |
1155 | $plugin = enrol_get_plugin($instance->enrol); | |
1156 | $course = get_course($instance->courseid); | |
1157 | $context = context_course::instance($course->id); | |
1158 | self::validate_context($context); | |
1159 | ||
1160 | require_once("$CFG->dirroot/enrol/editenrolment_form.php"); | |
1161 | $customformdata = [ | |
1162 | 'ue' => $userenrolment, | |
1163 | 'modal' => true, | |
1164 | 'enrolinstancename' => $plugin->get_instance_name($instance) | |
1165 | ]; | |
1166 | $mform = new enrol_user_enrolment_form(null, $customformdata, 'post', '', null, true, $data); | |
1167 | ||
1168 | if ($validateddata = $mform->get_data()) { | |
1169 | if (!empty($validateddata->duration) && $validateddata->timeend == 0) { | |
1170 | $validateddata->timeend = $validateddata->timestart + $validateddata->duration; | |
1171 | } | |
1172 | require_once($CFG->dirroot . '/enrol/locallib.php'); | |
1173 | $manager = new course_enrolment_manager($PAGE, $course); | |
1174 | $result = $manager->edit_enrolment($userenrolment, $validateddata); | |
1175 | ||
1176 | return ['result' => $result]; | |
1177 | } else { | |
1178 | return ['result' => false, 'validationerror' => true]; | |
1179 | } | |
1180 | } | |
1181 | ||
1182 | /** | |
1183 | * Returns description of submit_user_enrolment_form() result value | |
1184 | * | |
1185 | * @return external_description | |
1186 | */ | |
1187 | public static function submit_user_enrolment_form_returns() { | |
1188 | return new external_single_structure([ | |
1189 | 'result' => new external_value(PARAM_BOOL, 'True if the user\'s enrolment was successfully updated'), | |
1190 | 'validationerror' => new external_value(PARAM_BOOL, 'Indicates invalid form data', VALUE_DEFAULT, false), | |
1191 | ]); | |
1192 | } | |
1193 | ||
c8351261 MG |
1194 | /** |
1195 | * Returns description of unenrol_user_enrolment() parameters | |
1196 | * | |
1197 | * @return external_function_parameters | |
1198 | */ | |
1199 | public static function unenrol_user_enrolment_parameters() { | |
1200 | return new external_function_parameters( | |
1201 | array( | |
1202 | 'ueid' => new external_value(PARAM_INT, 'User enrolment ID') | |
1203 | ) | |
1204 | ); | |
1205 | } | |
1206 | ||
1207 | /** | |
1208 | * External function that unenrols a given user enrolment. | |
1209 | * | |
1210 | * @param int $ueid The user enrolment ID. | |
1211 | * @return array An array consisting of the processing result, errors. | |
1212 | */ | |
1213 | public static function unenrol_user_enrolment($ueid) { | |
1214 | global $CFG, $DB, $PAGE; | |
1215 | ||
1216 | $params = self::validate_parameters(self::unenrol_user_enrolment_parameters(), [ | |
1217 | 'ueid' => $ueid | |
1218 | ]); | |
1219 | ||
1220 | $result = false; | |
1221 | $errors = []; | |
1222 | ||
1223 | $userenrolment = $DB->get_record('user_enrolments', ['id' => $params['ueid']], '*'); | |
1224 | if ($userenrolment) { | |
1225 | $userid = $userenrolment->userid; | |
1226 | $enrolid = $userenrolment->enrolid; | |
1227 | $enrol = $DB->get_record('enrol', ['id' => $enrolid], '*', MUST_EXIST); | |
1228 | $courseid = $enrol->courseid; | |
1229 | $course = get_course($courseid); | |
1230 | $context = context_course::instance($course->id); | |
1231 | self::validate_context($context); | |
1232 | } else { | |
1233 | $validationerrors['invalidrequest'] = get_string('invalidrequest', 'enrol'); | |
1234 | } | |
1235 | ||
1236 | // If the userenrolment exists, unenrol the user. | |
1237 | if (!isset($validationerrors)) { | |
1238 | require_once($CFG->dirroot . '/enrol/locallib.php'); | |
1239 | $manager = new course_enrolment_manager($PAGE, $course); | |
1240 | $result = $manager->unenrol_user($userenrolment); | |
1241 | } else { | |
1242 | foreach ($validationerrors as $key => $errormessage) { | |
1243 | $errors[] = (object)[ | |
1244 | 'key' => $key, | |
1245 | 'message' => $errormessage | |
1246 | ]; | |
1247 | } | |
1248 | } | |
1249 | ||
1250 | return [ | |
1251 | 'result' => $result, | |
1252 | 'errors' => $errors, | |
1253 | ]; | |
1254 | } | |
1255 | ||
1256 | /** | |
1257 | * Returns description of unenrol_user_enrolment() result value | |
1258 | * | |
1259 | * @return external_description | |
1260 | */ | |
1261 | public static function unenrol_user_enrolment_returns() { | |
58c20c81 JP |
1262 | return new external_single_structure( |
1263 | array( | |
1264 | 'result' => new external_value(PARAM_BOOL, 'True if the user\'s enrolment was successfully updated'), | |
1265 | 'errors' => new external_multiple_structure( | |
1266 | new external_single_structure( | |
1267 | array( | |
1268 | 'key' => new external_value(PARAM_TEXT, 'The data that failed the validation'), | |
1269 | 'message' => new external_value(PARAM_TEXT, 'The error message'), | |
1270 | ) | |
1271 | ), 'List of validation errors' | |
1272 | ), | |
1273 | ) | |
1274 | ); | |
1275 | } | |
5d1017e1 JM |
1276 | } |
1277 | ||
1278 | /** | |
4615817d JM |
1279 | * Role external functions |
1280 | * | |
1281 | * @package core_role | |
1282 | * @category external | |
1283 | * @copyright 2011 Jerome Mouneyrac | |
1284 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
1285 | * @since Moodle 2.2 | |
5d1017e1 JM |
1286 | */ |
1287 | class core_role_external extends external_api { | |
1288 | ||
1289 | /** | |
1290 | * Returns description of method parameters | |
4615817d | 1291 | * |
5d1017e1 JM |
1292 | * @return external_function_parameters |
1293 | */ | |
1294 | public static function assign_roles_parameters() { | |
1295 | return new external_function_parameters( | |
1296 | array( | |
1297 | 'assignments' => new external_multiple_structure( | |
1298 | new external_single_structure( | |
1299 | array( | |
1300 | 'roleid' => new external_value(PARAM_INT, 'Role to assign to the user'), | |
1301 | 'userid' => new external_value(PARAM_INT, 'The user that is going to be assigned'), | |
3a68f798 AA |
1302 | 'contextid' => new external_value(PARAM_INT, 'The context to assign the user role in', VALUE_OPTIONAL), |
1303 | 'contextlevel' => new external_value(PARAM_ALPHA, 'The context level to assign the user role in | |
1304 | (block, course, coursecat, system, user, module)', VALUE_OPTIONAL), | |
1305 | 'instanceid' => new external_value(PARAM_INT, 'The Instance id of item where the role needs to be assigned', VALUE_OPTIONAL), | |
5d1017e1 JM |
1306 | ) |
1307 | ) | |
1308 | ) | |
1309 | ) | |
1310 | ); | |
1311 | } | |
1312 | ||
1313 | /** | |
1314 | * Manual role assignments to users | |
1315 | * | |
4615817d | 1316 | * @param array $assignments An array of manual role assignment |
5d1017e1 JM |
1317 | */ |
1318 | public static function assign_roles($assignments) { | |
1319 | global $DB; | |
1320 | ||
1321 | // Do basic automatic PARAM checks on incoming data, using params description | |
1322 | // If any problems are found then exceptions are thrown with helpful error messages | |
1323 | $params = self::validate_parameters(self::assign_roles_parameters(), array('assignments'=>$assignments)); | |
1324 | ||
1325 | $transaction = $DB->start_delegated_transaction(); | |
1326 | ||
1327 | foreach ($params['assignments'] as $assignment) { | |
3a68f798 | 1328 | // Ensure correct context level with a instance id or contextid is passed. |
5b23d9ad | 1329 | $context = self::get_context_from_params($assignment); |
3a68f798 AA |
1330 | |
1331 | // Ensure the current user is allowed to run this function in the enrolment context. | |
5d1017e1 JM |
1332 | self::validate_context($context); |
1333 | require_capability('moodle/role:assign', $context); | |
1334 | ||
1335 | // throw an exception if user is not able to assign the role in this context | |
1336 | $roles = get_assignable_roles($context, ROLENAME_SHORT); | |
1337 | ||
12fc8acf | 1338 | if (!array_key_exists($assignment['roleid'], $roles)) { |
5d1017e1 JM |
1339 | throw new invalid_parameter_exception('Can not assign roleid='.$assignment['roleid'].' in contextid='.$assignment['contextid']); |
1340 | } | |
1341 | ||
3a68f798 | 1342 | role_assign($assignment['roleid'], $assignment['userid'], $context->id); |
5d1017e1 JM |
1343 | } |
1344 | ||
1345 | $transaction->allow_commit(); | |
1346 | } | |
1347 | ||
1348 | /** | |
1349 | * Returns description of method result value | |
4615817d JM |
1350 | * |
1351 | * @return null | |
5d1017e1 JM |
1352 | */ |
1353 | public static function assign_roles_returns() { | |
1354 | return null; | |
1355 | } | |
1356 | ||
1357 | ||
1358 | /** | |
1359 | * Returns description of method parameters | |
4615817d | 1360 | * |
5d1017e1 JM |
1361 | * @return external_function_parameters |
1362 | */ | |
1363 | public static function unassign_roles_parameters() { | |
1364 | return new external_function_parameters( | |
1365 | array( | |
1366 | 'unassignments' => new external_multiple_structure( | |
1367 | new external_single_structure( | |
1368 | array( | |
1369 | 'roleid' => new external_value(PARAM_INT, 'Role to assign to the user'), | |
1370 | 'userid' => new external_value(PARAM_INT, 'The user that is going to be assigned'), | |
1e631792 AA |
1371 | 'contextid' => new external_value(PARAM_INT, 'The context to unassign the user role from', VALUE_OPTIONAL), |
1372 | 'contextlevel' => new external_value(PARAM_ALPHA, 'The context level to unassign the user role in | |
1373 | + (block, course, coursecat, system, user, module)', VALUE_OPTIONAL), | |
1374 | 'instanceid' => new external_value(PARAM_INT, 'The Instance id of item where the role needs to be unassigned', VALUE_OPTIONAL), | |
5d1017e1 JM |
1375 | ) |
1376 | ) | |
1377 | ) | |
1378 | ) | |
1379 | ); | |
1380 | } | |
1381 | ||
1382 | /** | |
1383 | * Unassign roles from users | |
1384 | * | |
4615817d | 1385 | * @param array $unassignments An array of unassignment |
5d1017e1 JM |
1386 | */ |
1387 | public static function unassign_roles($unassignments) { | |
1388 | global $DB; | |
1389 | ||
1390 | // Do basic automatic PARAM checks on incoming data, using params description | |
1391 | // If any problems are found then exceptions are thrown with helpful error messages | |
1392 | $params = self::validate_parameters(self::unassign_roles_parameters(), array('unassignments'=>$unassignments)); | |
1393 | ||
1394 | $transaction = $DB->start_delegated_transaction(); | |
1395 | ||
1396 | foreach ($params['unassignments'] as $unassignment) { | |
1397 | // Ensure the current user is allowed to run this function in the unassignment context | |
1e631792 | 1398 | $context = self::get_context_from_params($unassignment); |
5d1017e1 JM |
1399 | self::validate_context($context); |
1400 | require_capability('moodle/role:assign', $context); | |
1401 | ||
1402 | // throw an exception if user is not able to unassign the role in this context | |
1403 | $roles = get_assignable_roles($context, ROLENAME_SHORT); | |
12fc8acf | 1404 | if (!array_key_exists($unassignment['roleid'], $roles)) { |
5d1017e1 JM |
1405 | throw new invalid_parameter_exception('Can not unassign roleid='.$unassignment['roleid'].' in contextid='.$unassignment['contextid']); |
1406 | } | |
1407 | ||
1e631792 | 1408 | role_unassign($unassignment['roleid'], $unassignment['userid'], $context->id); |
5d1017e1 JM |
1409 | } |
1410 | ||
1411 | $transaction->allow_commit(); | |
1412 | } | |
1413 | ||
1414 | /** | |
1415 | * Returns description of method result value | |
4615817d | 1416 | * |
5d1017e1 JM |
1417 | * @return null |
1418 | */ | |
1419 | public static function unassign_roles_returns() { | |
1420 | return null; | |
1421 | } | |
1422 | } |