MDL-29938 get_users - search users external function
[moodle.git] / user / externallib.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/>.
18 /**
19  * External user API
20  *
21  * @package    core_user
22  * @category   external
23  * @copyright  2009 Petr Skodak
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 require_once("$CFG->libdir/externallib.php");
29 /**
30  * User external functions
31  *
32  * @package    core_user
33  * @category   external
34  * @copyright  2011 Jerome Mouneyrac
35  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  * @since Moodle 2.2
37  */
38 class core_user_external extends external_api {
40     /**
41      * Returns description of method parameters
42      *
43      * @return external_function_parameters
44      * @since Moodle 2.2
45      */
46     public static function create_users_parameters() {
47         global $CFG;
49         return new external_function_parameters(
50             array(
51                 'users' => new external_multiple_structure(
52                     new external_single_structure(
53                         array(
54                             'username'    => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config. Must be lowercase.'),
55                             'password'    => new external_value(PARAM_RAW, 'Plain text password consisting of any characters'),
56                             'firstname'   => new external_value(PARAM_NOTAGS, 'The first name(s) of the user'),
57                             'lastname'    => new external_value(PARAM_NOTAGS, 'The family name of the user'),
58                             'email'       => new external_value(PARAM_EMAIL, 'A valid and unique email address'),
59                             'auth'        => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_DEFAULT, 'manual', NULL_NOT_ALLOWED),
60                             'idnumber'    => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_DEFAULT, ''),
61                             'lang'        => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_DEFAULT, $CFG->lang, NULL_NOT_ALLOWED),
62                             'theme'       => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
63                             'timezone'    => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
64                             'mailformat'  => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
65                             'description' => new external_value(PARAM_TEXT, 'User profile description, no HTML', VALUE_OPTIONAL),
66                             'city'        => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL),
67                             'country'     => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL),
68                             'preferences' => new external_multiple_structure(
69                                 new external_single_structure(
70                                     array(
71                                         'type'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the preference'),
72                                         'value' => new external_value(PARAM_RAW, 'The value of the preference')
73                                     )
74                                 ), 'User preferences', VALUE_OPTIONAL),
75                             'customfields' => new external_multiple_structure(
76                                 new external_single_structure(
77                                     array(
78                                         'type'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'),
79                                         'value' => new external_value(PARAM_RAW, 'The value of the custom field')
80                                     )
81                                 ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL)
82                         )
83                     )
84                 )
85             )
86         );
87     }
89     /**
90      * Create one or more users
91      *
92      * @param array $users An array of users to create.
93      * @return array An array of arrays
94      * @since Moodle 2.2
95      */
96     public static function create_users($users) {
97         global $CFG, $DB;
98         require_once($CFG->dirroot."/lib/weblib.php");
99         require_once($CFG->dirroot."/user/lib.php");
100         require_once($CFG->dirroot."/user/profile/lib.php"); //required for customfields related function
102         // Ensure the current user is allowed to run this function
103         $context = context_system::instance();
104         self::validate_context($context);
105         require_capability('moodle/user:create', $context);
107         // Do basic automatic PARAM checks on incoming data, using params description
108         // If any problems are found then exceptions are thrown with helpful error messages
109         $params = self::validate_parameters(self::create_users_parameters(), array('users'=>$users));
111         $availableauths  = get_plugin_list('auth');
112         unset($availableauths['mnet']);       // these would need mnethostid too
113         unset($availableauths['webservice']); // we do not want new webservice users for now
115         $availablethemes = get_plugin_list('theme');
116         $availablelangs  = get_string_manager()->get_list_of_translations();
118         $transaction = $DB->start_delegated_transaction();
120         $userids = array();
121         foreach ($params['users'] as $user) {
122             // Make sure that the username doesn't already exist
123             if ($DB->record_exists('user', array('username'=>$user['username'], 'mnethostid'=>$CFG->mnet_localhost_id))) {
124                 throw new invalid_parameter_exception('Username already exists: '.$user['username']);
125             }
127             // Make sure auth is valid
128             if (empty($availableauths[$user['auth']])) {
129                 throw new invalid_parameter_exception('Invalid authentication type: '.$user['auth']);
130             }
132             // Make sure lang is valid
133             if (empty($availablelangs[$user['lang']])) {
134                 throw new invalid_parameter_exception('Invalid language code: '.$user['lang']);
135             }
137             // Make sure lang is valid
138             if (!empty($user['theme']) && empty($availablethemes[$user['theme']])) { //theme is VALUE_OPTIONAL,
139                                                                                      // so no default value.
140                                                                                      // We need to test if the client sent it
141                                                                                      // => !empty($user['theme'])
142                 throw new invalid_parameter_exception('Invalid theme: '.$user['theme']);
143             }
145             $user['confirmed'] = true;
146             $user['mnethostid'] = $CFG->mnet_localhost_id;
148             // Start of user info validation.
149             // Lets make sure we validate current user info as handled by current GUI. see user/editadvanced_form.php function validation()
150             if (!validate_email($user['email'])) {
151                 throw new invalid_parameter_exception('Email address is invalid: '.$user['email']);
152             } else if ($DB->record_exists('user', array('email'=>$user['email'], 'mnethostid'=>$user['mnethostid']))) {
153                 throw new invalid_parameter_exception('Email address already exists: '.$user['email']);
154             }
155             // End of user info validation.
157             // create the user data now!
158             $user['id'] = user_create_user($user);
160             // custom fields
161             if(!empty($user['customfields'])) {
162                 foreach($user['customfields'] as $customfield) {
163                     $user["profile_field_".$customfield['type']] = $customfield['value']; //profile_save_data() saves profile file
164                                                                                             //it's expecting a user with the correct id,
165                                                                                             //and custom field to be named profile_field_"shortname"
166                 }
167                 profile_save_data((object) $user);
168             }
170             //preferences
171             if (!empty($user['preferences'])) {
172                 foreach($user['preferences'] as $preference) {
173                     set_user_preference($preference['type'], $preference['value'],$user['id']);
174                 }
175             }
177             $userids[] = array('id'=>$user['id'], 'username'=>$user['username']);
178         }
180         $transaction->allow_commit();
182         return $userids;
183     }
185    /**
186      * Returns description of method result value
187      *
188      * @return external_description
189      * @since Moodle 2.2
190      */
191     public static function create_users_returns() {
192         return new external_multiple_structure(
193             new external_single_structure(
194                 array(
195                     'id'       => new external_value(PARAM_INT, 'user id'),
196                     'username' => new external_value(PARAM_USERNAME, 'user name'),
197                 )
198             )
199         );
200     }
203     /**
204      * Returns description of method parameters
205      *
206      * @return external_function_parameters
207      * @since Moodle 2.2
208      */
209     public static function delete_users_parameters() {
210         return new external_function_parameters(
211             array(
212                 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user ID')),
213             )
214         );
215     }
217     /**
218      * Delete users
219      *
220      * @param array $userids
221      * @return null
222      * @since Moodle 2.2
223      */
224     public static function delete_users($userids) {
225         global $CFG, $DB, $USER;
226         require_once($CFG->dirroot."/user/lib.php");
228         // Ensure the current user is allowed to run this function
229         $context = context_system::instance();
230         require_capability('moodle/user:delete', $context);
231         self::validate_context($context);
233         $params = self::validate_parameters(self::delete_users_parameters(), array('userids'=>$userids));
235         $transaction = $DB->start_delegated_transaction();
237         foreach ($params['userids'] as $userid) {
238             $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0), '*', MUST_EXIST);
239             // must not allow deleting of admins or self!!!
240             if (is_siteadmin($user)) {
241                 throw new moodle_exception('useradminodelete', 'error');
242             }
243             if ($USER->id == $user->id) {
244                 throw new moodle_exception('usernotdeletederror', 'error');
245             }
246             user_delete_user($user);
247         }
249         $transaction->allow_commit();
251         return null;
252     }
254    /**
255      * Returns description of method result value
256      *
257      * @return null
258      * @since Moodle 2.2
259      */
260     public static function delete_users_returns() {
261         return null;
262     }
265     /**
266      * Returns description of method parameters
267      *
268      * @return external_function_parameters
269      * @since Moodle 2.2
270      */
271     public static function update_users_parameters() {
272         global $CFG;
273         return new external_function_parameters(
274             array(
275                 'users' => new external_multiple_structure(
276                     new external_single_structure(
277                         array(
278                             'id'    => new external_value(PARAM_INT, 'ID of the user'),
279                             'username'    => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config. Must be lowercase.', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED),
280                             'password'    => new external_value(PARAM_RAW, 'Plain text password consisting of any characters', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED),
281                             'firstname'   => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED),
282                             'lastname'    => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL),
283                             'email'       => new external_value(PARAM_EMAIL, 'A valid and unique email address', VALUE_OPTIONAL, '',NULL_NOT_ALLOWED),
284                             'auth'        => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED),
285                             'idnumber'    => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL),
286                             'lang'        => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED),
287                             'theme'       => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
288                             'timezone'    => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
289                             'mailformat'  => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
290                             'description' => new external_value(PARAM_TEXT, 'User profile description, no HTML', VALUE_OPTIONAL),
291                             'city'        => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL),
292                             'country'     => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL),
293                             'customfields' => new external_multiple_structure(
294                                 new external_single_structure(
295                                     array(
296                                         'type'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'),
297                                         'value' => new external_value(PARAM_RAW, 'The value of the custom field')
298                                     )
299                                 ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL),
300                             'preferences' => new external_multiple_structure(
301                                 new external_single_structure(
302                                     array(
303                                         'type'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the preference'),
304                                         'value' => new external_value(PARAM_RAW, 'The value of the preference')
305                                     )
306                                 ), 'User preferences', VALUE_OPTIONAL),
307                         )
308                     )
309                 )
310             )
311         );
312     }
314     /**
315      * Update users
316      *
317      * @param array $users
318      * @return null
319      * @since Moodle 2.2
320      */
321     public static function update_users($users) {
322         global $CFG, $DB;
323         require_once($CFG->dirroot."/user/lib.php");
324         require_once($CFG->dirroot."/user/profile/lib.php"); //required for customfields related function
326         // Ensure the current user is allowed to run this function
327         $context = context_system::instance();
328         require_capability('moodle/user:update', $context);
329         self::validate_context($context);
331         $params = self::validate_parameters(self::update_users_parameters(), array('users'=>$users));
333         $transaction = $DB->start_delegated_transaction();
335         foreach ($params['users'] as $user) {
336             user_update_user($user);
337             //update user custom fields
338             if(!empty($user['customfields'])) {
340                 foreach($user['customfields'] as $customfield) {
341                     $user["profile_field_".$customfield['type']] = $customfield['value']; //profile_save_data() saves profile file
342                                                                                             //it's expecting a user with the correct id,
343                                                                                             //and custom field to be named profile_field_"shortname"
344                 }
345                 profile_save_data((object) $user);
346             }
348             //preferences
349             if (!empty($user['preferences'])) {
350                 foreach($user['preferences'] as $preference) {
351                     set_user_preference($preference['type'], $preference['value'],$user['id']);
352                 }
353             }
354         }
356         $transaction->allow_commit();
358         return null;
359     }
361    /**
362      * Returns description of method result value
363      *
364      * @return null
365      * @since Moodle 2.2
366      */
367     public static function update_users_returns() {
368         return null;
369     }
371    /**
372    * Returns description of method parameters
373    *
374    * @return external_function_parameters
375    * @since Moodle 2.4
376    */
377     public static function get_users_by_field_parameters() {
378         return new external_function_parameters(
379             array(
380                 'field' => new external_value(PARAM_ALPHA, 'the search field can be
381                     \'id\' or \'idnumber\' or \'username\' or \'email\''),
382                 'values' => new external_multiple_structure(
383                         new external_value(PARAM_RAW, 'the value to match'))
384             )
385         );
386     }
388     /**
389      * Get user information for a unique field.
390      *
391      * @param string $field
392      * @param array $values
393      * @return array An array of arrays containg user profiles.
394      * @since Moodle 2.4
395      */
396     public static function get_users_by_field($field, $values) {
397         global $CFG, $USER, $DB;
398         require_once($CFG->dirroot . "/user/lib.php");
400         $params = self::validate_parameters(self::get_users_by_field_parameters(),
401                 array('field' => $field, 'values' => $values));
403         // This array will keep all the users that are allowed to be searched,
404         // according to the current user's privileges.
405         $cleanedvalues = array();
407         switch ($field) {
408             case 'id':
409                 $paramtype = PARAM_INT;
410                 break;
411             case 'idnumber':
412                 $paramtype = PARAM_RAW;
413                 break;
414             case 'username':
415                 $paramtype = PARAM_USERNAME;
416                 break;
417             case 'email':
418                 $paramtype = PARAM_EMAIL;
419                 break;
420             default:
421                 throw new coding_exception('invalid field parameter',
422                         'The search field \'' . $field . '\' is not supported, look at the web service documentation');
423         }
425         // Clean the values
426         foreach ($values as $value) {
427             $cleanedvalue = clean_param($value, $paramtype);
428             if ( $value != $cleanedvalue) {
429                 throw new invalid_parameter_exception('The field \'' . $field .
430                         '\' value is invalid: ' . $value . '(cleaned value: '.$cleanedvalue.')');
431             }
432             $cleanedvalues[] = $cleanedvalue;
433         }
435         // Retrieve the users
436         $users = $DB->get_records_list('user', $field, $cleanedvalues, 'id');
438         // Finally retrieve each users information
439         $returnedusers = array();
440         foreach ($users as $user) {
442             $userdetails = user_get_user_details_courses($user);
444             // Return the user only if the searched field is returned
445             // Otherwise it means that the $USER was not allowed to search the returned user
446             if (!empty($userdetails) and !empty($userdetails[$field])) {
447                 $returnedusers[] = $userdetails;
448             }
449         }
451         return $returnedusers;
452     }
454     /**
455      * Returns description of method result value
456      *
457      * @return external_multiple_structure
458      * @since Moodle 2.4
459      */
460     public static function get_users_by_field_returns() {
461         return new external_multiple_structure(core_user_external::user_description());
462     }
465     /**
466      * Returns description of get_users() parameters
467      *
468      * @return external_function_parameters
469      * @since Moodle 2.4
470      */
471     public static function get_users_parameters() {
472         return new external_function_parameters(
473             array(
474                 'criteria' => new external_multiple_structure(
475                     new external_single_structure(
476                         array(
477                             'key'        => new external_value(PARAM_ALPHA, 'the user column to search, expected keys (value format) are:
478                                                     "id" (int) matching user id,
479                                                     "lastname" (string) user last name (Note: you can use % for searching but it can be slow!),
480                                                     "firstname" (string) user first name (Note: you can use % for searching but it can be slow!),
481                                                     "idnumber" (string) matching user idnumber,
482                                                     "username" (string) matching user username,
483                                                     "email" (string) user email (Note: you can use % for searching but it can be slow!),
484                                                     "auth" (plugin) matching user auth plugin'),
485                             'value'      => new external_value(PARAM_RAW, 'the value to search')
486                         )
487                     ), 'the key/value pairs to be considered in user search. Values can not be empty.
488                         Specifiy different keys only once (fullname => \'user1\', auth => \'manual\', ...) -
489                         key occurences are ignored, only the last occurence is considered.
490                         The search is executed with AND operator on the criterias.'
491                 )
492             )
493         );
494     }
496     /**
497      * Retrieve matching user
498      *
499      * @param string $field
500      * @param array $values
501      * @return array An array of arrays containg user profiles.
502      * @since Moodle 2.4
503      */
504     public static function get_users($criteria = array()) {
505         global $CFG, $USER, $DB;
507         require_once($CFG->dirroot . "/user/lib.php");
509         $params = self::validate_parameters(self::get_users_parameters(),
510                 array('criteria' => $criteria));
512         // Validate the criteria and retrieve the users
513         $cleanedvalues = array();
514         $firstcriteria = true;
515         $users = array();
516         $warnings = array();
517         $sql = '';
518         $sqlparams = array();
520         foreach ($params['criteria'] as $criteria) {
522             // Clean the parameters
523             $paramtype = PARAM_RAW;
524             switch ($criteria['key']) {
525                 case 'id':
526                     $paramtype = PARAM_INT;
527                     break;
528                 case 'idnumber':
529                     $paramtype = PARAM_RAW;
530                     break;
531                 case 'username':
532                     $paramtype = PARAM_USERNAME;
533                     break;
534                 case 'email':
535                     // we use PARAM_RAW to allow searches with %
536                     $paramtype = PARAM_RAW;
537                     break;
538                 case 'auth':
539                     $paramtype = PARAM_AUTH;
540                     break;
541                 case 'lastname':
542                 case 'firstname':
543                     $paramtype = PARAM_TEXT;
544                     break;
545                 default:
546                     // Send back a warning that this search key is not supported in this version
547                     // This warning will make the function extandable without breaking clients
548                     $warnings[] = array(
549                         'item' => 'key',
550                         'itemid' => $criteria['key'],
551                         'warningcode' => 'invalidfieldparameter',
552                         'message' => 'The search key \'' . $$criteria['key'] . '\' is not supported, look at the web service documentation'
553                     );
554             }
555             $cleanedvalue = clean_param($criteria['value'], $paramtype);
557             // If first criteria do not add AND to the query
558             if ($firstcriteria) {
559                 $firstcriteria = false;
560             } else {
561                 $sql .= ' AND ';
562             }
564             // Create the SQL
565             switch ($criteria['key']) {
566                 case 'id':
567                 case 'idnumber':
568                 case 'username':
569                 case 'auth':
570                     $sql .= $criteria['key'] . ' = :' . $criteria['key'];
571                     $sqlparams[$criteria['key']] = $cleanedvalue;
572                     break;
573                 case 'email':
574                 case 'lastname':
575                 case 'firstname':
576                     $sql .= $DB->sql_like($criteria['key'], ':'.$criteria['key'], false);
577                     $sqlparams[$criteria['key']] = $cleanedvalue;
578                     break;
579                 default:
580                     break;
581             }
582         }
584         $users = $DB->get_records_select('user', $sql, $sqlparams, 'id ASC');
586         // Finally retrieve each users information
587         $returnedusers = array();
588         foreach ($users as $user) {
590             $userdetails = user_get_user_details_courses($user);
592             // Return the user only if all the searched fields are returned.
593             // Otherwise it means that the $USER was not allowed to search the returned user.
594             if (!empty($userdetails)) {
595                 $validuser = true;
597                 foreach($params['criteria'] as $criteria) {
598                     if (empty($userdetails[$criteria['key']])) {
599                         $validuser = false;
600                     }
601                 }
603                 if ($validuser) {
604                     $returnedusers[] = $userdetails;
605                 }
606             }
607         }
609         return array('users' => $returnedusers, 'warnings' => $warnings);
610     }
612     /**
613      * Returns description of get_users result value
614      *
615      * @return external_description
616      * @since Moodle 2.3
617      */
618     public static function get_users_returns() {
619         return new external_single_structure(
620             array('users' => new external_multiple_structure(
621                                 core_user_external::user_description()
622                              ),
623                   'warnings' => new external_warnings()
624             )
625         );
626     }
628     /**
629      * Returns description of method parameters
630      *
631      * @return external_function_parameters
632      * @since Moodle 2.2
633      */
634     public static function get_users_by_id_parameters() {
635         return new external_function_parameters(
636                 array(
637                     'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user ID')),
638                 )
639         );
640     }
642     /**
643      * Get user information
644      * - This function is matching the permissions of /user/profil.php
645      * - It is also matching some permissions from /user/editadvanced.php for the following fields:
646      *   auth, confirmed, idnumber, lang, theme, timezone, mailformat
647      *
648      * @param array $userids  array of user ids
649      * @return array An array of arrays describing users
650      * @since Moodle 2.2
651      */
652     public static function get_users_by_id($userids) {
653         global $CFG, $USER, $DB;
654         require_once($CFG->dirroot . "/user/lib.php");
656         $params = self::validate_parameters(self::get_users_by_id_parameters(),
657                 array('userids'=>$userids));
659         list($uselect, $ujoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx');
660         list($sqluserids, $params) = $DB->get_in_or_equal($userids);
661         $usersql = "SELECT u.* $uselect
662                       FROM {user} u $ujoin
663                      WHERE u.id $sqluserids";
664         $users = $DB->get_recordset_sql($usersql, $params);
666         $result = array();
667         $hasuserupdatecap = has_capability('moodle/user:update', get_system_context());
668         foreach ($users as $user) {
669             if (!empty($user->deleted)) {
670                 continue;
671             }
672             context_instance_preload($user);
673             $usercontext = context_user::instance($user->id, IGNORE_MISSING);
674             self::validate_context($usercontext);
675             $currentuser = ($user->id == $USER->id);
677             if ($userarray  = user_get_user_details($user)) {
678                 //fields matching permissions from /user/editadvanced.php
679                 if ($currentuser or $hasuserupdatecap) {
680                     $userarray['auth']       = $user->auth;
681                     $userarray['confirmed']  = $user->confirmed;
682                     $userarray['idnumber']   = $user->idnumber;
683                     $userarray['lang']       = $user->lang;
684                     $userarray['theme']      = $user->theme;
685                     $userarray['timezone']   = $user->timezone;
686                     $userarray['mailformat'] = $user->mailformat;
687                 }
688                 $result[] = $userarray;
689             }
690         }
691         $users->close();
693         return $result;
694     }
698     /**
699      * Returns description of method result value
700      *
701      * @return external_description
702      * @since Moodle 2.2
703      */
704     public static function get_users_by_id_returns() {
705         return new external_multiple_structure(
706             core_user_external::user_description()
707         );
708     }
709     /**
710      * Returns description of method parameters
711      *
712      * @return external_function_parameters
713      * @since Moodle 2.2
714      */
715     public static function get_course_user_profiles_parameters() {
716         return new external_function_parameters(
717             array(
718                 'userlist' => new external_multiple_structure(
719                     new external_single_structure(
720                         array(
721                             'userid'    => new external_value(PARAM_INT, 'userid'),
722                             'courseid'    => new external_value(PARAM_INT, 'courseid'),
723                         )
724                     )
725                 )
726             )
727         );
728     }
730     /**
731      * Get course participant's details
732      *
733      * @param array $userlist  array of user ids and according course ids
734      * @return array An array of arrays describing course participants
735      * @since Moodle 2.2
736      */
737     public static function get_course_user_profiles($userlist) {
738         global $CFG, $USER, $DB;
739         require_once($CFG->dirroot . "/user/lib.php");
740         $params = self::validate_parameters(self::get_course_user_profiles_parameters(), array('userlist'=>$userlist));
742         $userids = array();
743         $courseids = array();
744         foreach ($params['userlist'] as $value) {
745             $userids[] = $value['userid'];
746             $courseids[$value['userid']] = $value['courseid'];
747         }
749         // cache all courses
750         $courses = array();
751         list($cselect, $cjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
752         list($sqlcourseids, $params) = $DB->get_in_or_equal(array_unique($courseids));
753         $coursesql = "SELECT c.* $cselect
754                         FROM {course} c $cjoin
755                        WHERE c.id $sqlcourseids";
756         $rs = $DB->get_recordset_sql($coursesql, $params);
757         foreach ($rs as $course) {
758             // adding course contexts to cache
759             context_instance_preload($course);
760             // cache courses
761             $courses[$course->id] = $course;
762         }
763         $rs->close();
765         list($uselect, $ujoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx');
766         list($sqluserids, $params) = $DB->get_in_or_equal($userids);
767         $usersql = "SELECT u.* $uselect
768                       FROM {user} u $ujoin
769                      WHERE u.id $sqluserids";
770         $users = $DB->get_recordset_sql($usersql, $params);
771         $result = array();
772         foreach ($users as $user) {
773             if (!empty($user->deleted)) {
774                 continue;
775             }
776             context_instance_preload($user);
777             $course = $courses[$courseids[$user->id]];
778             $context = context_course::instance($courseids[$user->id], IGNORE_MISSING);
779             self::validate_context($context);
780             if ($userarray = user_get_user_details($user, $course)) {
781                 $result[] = $userarray;
782             }
783         }
785         $users->close();
787         return $result;
788     }
790     /**
791      * Returns description of method result value
792      *
793      * @return external_description
794      * @since Moodle 2.2
795      */
796     public static function get_course_user_profiles_returns() {
797         $additionalfields = array(
798                     'groups' => new external_multiple_structure(
799                         new external_single_structure(
800                             array(
801                                 'id'  => new external_value(PARAM_INT, 'group id'),
802                                 'name' => new external_value(PARAM_RAW, 'group name'),
803                                 'description' => new external_value(PARAM_RAW, 'group description'),
804                                 'descriptionformat' => new external_format_value('description'),
805                             )
806                         ), 'user groups', VALUE_OPTIONAL),
807                     'roles' => new external_multiple_structure(
808                         new external_single_structure(
809                             array(
810                                 'roleid'       => new external_value(PARAM_INT, 'role id'),
811                                 'name'         => new external_value(PARAM_RAW, 'role name'),
812                                 'shortname'    => new external_value(PARAM_ALPHANUMEXT, 'role shortname'),
813                                 'sortorder'    => new external_value(PARAM_INT, 'role sortorder')
814                             )
815                         ), 'user roles', VALUE_OPTIONAL),
816                     'enrolledcourses' => new external_multiple_structure(
817                             new external_single_structure(
818                                     array(
819                                             'id'  => new external_value(PARAM_INT, 'Id of the course'),
820                                             'fullname'  => new external_value(PARAM_RAW, 'Fullname of the course'),
821                                             'shortname' => new external_value(PARAM_RAW, 'Shortname of the course')
822                                     )
823                             ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL)
824                     );
826         return new external_multiple_structure(core_user_external::user_description($additionalfields));
827     }
829     /**
830      * Create user return value description.
831      *
832      * @param array $additionalfiels some additional field
833      * @return single_structure_description
834      */
835     public static function user_description($additionalfiels = array()) {
836         $userfields = array(
837                     'id'    => new external_value(PARAM_INT, 'ID of the user'),
838                     'username'    => new external_value(PARAM_USERNAME, 'Username policy is defined in Moodle security config', VALUE_OPTIONAL),
839                     'firstname'   => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL),
840                     'lastname'    => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL),
841                     'fullname'    => new external_value(PARAM_NOTAGS, 'The fullname of the user'),
842                     'email'       => new external_value(PARAM_TEXT, 'An email address - allow email as root@localhost', VALUE_OPTIONAL),
843                     'address'     => new external_value(PARAM_TEXT, 'Postal address', VALUE_OPTIONAL),
844                     'phone1'      => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL),
845                     'phone2'      => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL),
846                     'icq'         => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL),
847                     'skype'       => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL),
848                     'yahoo'       => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL),
849                     'aim'         => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL),
850                     'msn'         => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL),
851                     'department'  => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL),
852                     'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL),
853                     'idnumber'    => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL),
854                     'interests'   => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL),
855                     'firstaccess' => new external_value(PARAM_INT, 'first access to the site (0 if never)', VALUE_OPTIONAL),
856                     'lastaccess'  => new external_value(PARAM_INT, 'last access to the site (0 if never)', VALUE_OPTIONAL),
857                     'auth'        => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL),
858                     'confirmed'   => new external_value(PARAM_INT, 'Active user: 1 if confirmed, 0 otherwise', VALUE_OPTIONAL),
859                     'lang'        => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL),
860                     'theme'       => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
861                     'timezone'    => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
862                     'mailformat'  => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
863                     'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL),
864                     'descriptionformat' => new external_format_value('description', VALUE_OPTIONAL),
865                     'city'        => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL),
866                     'url'         => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL),
867                     'country'     => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL),
868                     'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'),
869                     'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'),
870                     'customfields' => new external_multiple_structure(
871                         new external_single_structure(
872                             array(
873                                 'type'  => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'),
874                                 'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
875                                 'name' => new external_value(PARAM_RAW, 'The name of the custom field'),
876                                 'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'),
877                             )
878                         ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL),
879                     'preferences' => new external_multiple_structure(
880                         new external_single_structure(
881                             array(
882                                 'name'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the preferences'),
883                                 'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
884                             )
885                     ), 'Users preferences', VALUE_OPTIONAL)
886                 );
887         if (!empty($additionalfields)) {
888             $userfields = array_merge($userfields, $additionalfields);
889         }
890         return new external_single_structure($userfields);
891     }
895  /**
896  * Deprecated user external functions
897  *
898  * @package    core_user
899  * @copyright  2009 Petr Skodak
900  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
901  * @since Moodle 2.0
902  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
903  * @todo MDL-31194 This will be deleted in Moodle 2.5.
904  * @see core_user_external
905  */
906 class moodle_user_external extends external_api {
908     /**
909      * Returns description of method parameters
910      *
911      * @return external_function_parameters
912      * @since Moodle 2.0
913      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
914      * @todo MDL-31194 This will be deleted in Moodle 2.5.
915      * @see core_user_external::create_users_parameters()
916      */
917     public static function create_users_parameters() {
918         return core_user_external::create_users_parameters();
919     }
921     /**
922      * Create one or more users
923      *
924      * @param array $users  An array of users to create.
925      * @return array An array of arrays
926      * @since Moodle 2.0
927      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
928      * @todo MDL-31194 This will be deleted in Moodle 2.5.
929      * @see core_user_external::create_users()
930      */
931     public static function create_users($users) {
932         return core_user_external::create_users($users);
933     }
935    /**
936      * Returns description of method result value
937      *
938      * @return external_description
939      * @since Moodle 2.0
940      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
941      * @todo MDL-31194 This will be deleted in Moodle 2.5.
942      * @see core_user_external::create_users_returns()
943      */
944     public static function create_users_returns() {
945         return core_user_external::create_users_returns();
946     }
949     /**
950      * Returns description of method parameters
951      *
952      * @return external_function_parameters
953      * @since Moodle 2.0
954      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
955      * @todo MDL-31194 This will be deleted in Moodle 2.5.
956      * @see core_user_external::delete_users_parameters()
957      */
958     public static function delete_users_parameters() {
959         return core_user_external::delete_users_parameters();
960     }
962     /**
963      * Delete users
964      *
965      * @param array $userids
966      * @return null
967      * @since Moodle 2.0
968      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
969      * @todo MDL-31194 This will be deleted in Moodle 2.5.
970      * @see core_user_external::delete_users()
971      */
972     public static function delete_users($userids) {
973         return core_user_external::delete_users($userids);
974     }
976    /**
977      * Returns description of method result value
978      *
979      * @return null
980      * @since Moodle 2.0
981      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
982      * @todo MDL-31194 This will be deleted in Moodle 2.5.
983      * @see core_user_external::delete_users_returns()
984      */
985     public static function delete_users_returns() {
986         return core_user_external::delete_users_returns();
987     }
990     /**
991      * Returns description of method parameters
992      *
993      * @return external_function_parameters
994      * @since Moodle 2.0
995      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
996      * @todo MDL-31194 This will be deleted in Moodle 2.5.
997      * @see core_user_external::update_users_parameters()
998      */
999     public static function update_users_parameters() {
1000         return core_user_external::update_users_parameters();
1001     }
1003     /**
1004      * Update users
1005      *
1006      * @param array $users
1007      * @return null
1008      * @since Moodle 2.0
1009      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1010      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1011      * @see core_user_external::update_users()
1012      */
1013     public static function update_users($users) {
1014         return core_user_external::update_users($users);
1015     }
1017    /**
1018      * Returns description of method result value
1019      *
1020      * @return null
1021      * @since Moodle 2.0
1022      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1023      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1024      * @see core_user_external::update_users_returns()
1025      */
1026     public static function update_users_returns() {
1027         return core_user_external::update_users_returns();
1028     }
1030     /**
1031      * Returns description of method parameters
1032      *
1033      * @return external_function_parameters
1034      * @since Moodle 2.0
1035      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1036      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1037      * @see core_user_external::get_users_by_id_parameters()
1038      */
1039     public static function get_users_by_id_parameters() {
1040         return core_user_external::get_users_by_id_parameters();
1041     }
1043     /**
1044      * Get user information
1045      * - This function is matching the permissions of /user/profil.php
1046      * - It is also matching some permissions from /user/editadvanced.php for the following fields:
1047      *   auth, confirmed, idnumber, lang, theme, timezone, mailformat
1048      *
1049      * @param array $userids  array of user ids
1050      * @return array An array of arrays describing users
1051      * @since Moodle 2.0
1052      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1053      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1054      * @see core_user_external::get_users_by_id()
1055      */
1056     public static function get_users_by_id($userids) {
1057         return core_user_external::get_users_by_id($userids);
1058     }
1060     /**
1061      * Returns description of method result value
1062      *
1063      * @return external_description
1064      * @since Moodle 2.0
1065      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1066      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1067      * @see core_user_external::get_users_by_id_returns()
1068      */
1069     public static function get_users_by_id_returns() {
1070         $additionalfields = array (
1071             'enrolledcourses' => new external_multiple_structure(
1072                 new external_single_structure(
1073                         array(
1074                                 'id'  => new external_value(PARAM_INT, 'Id of the course'),
1075                                 'fullname'  => new external_value(PARAM_RAW, 'Fullname of the course'),
1076                                 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course')
1077                         )
1078                 ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL));
1079         return core_user_external::get_users_by_id_returns($additionalfields);
1080     }
1081     /**
1082      * Returns description of method parameters
1083      *
1084      * @return external_function_parameters
1085      * @since Moodle 2.1
1086      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1087      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1088      * @see core_user_external::get_course_user_profiles_parameters()
1089      */
1090     public static function get_course_participants_by_id_parameters() {
1091         return core_user_external::get_course_user_profiles_parameters();
1092     }
1094     /**
1095      * Get course participant's details
1096      *
1097      * @param array $userlist  array of user ids and according course ids
1098      * @return array An array of arrays describing course participants
1099      * @since Moodle 2.1
1100      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1101      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1102      * @see core_user_external::get_course_user_profiles()
1103      */
1104     public static function get_course_participants_by_id($userlist) {
1105         return core_user_external::get_course_user_profiles($userlist);
1106     }
1108     /**
1109      * Returns description of method result value
1110      *
1111      * @return external_description
1112      * @since Moodle 2.1
1113      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1114      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1115      * @see core_user_external::get_course_user_profiles_returns()
1116      */
1117     public static function get_course_participants_by_id_returns() {
1118         return core_user_external::get_course_user_profiles_returns();
1119     }
1121     /**
1122      * Returns description of method parameters
1123      *
1124      * @return external_function_parameters
1125      * @since Moodle 2.1
1126      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1127      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1128      * @see core_enrol_external::get_enrolled_users_parameters()
1129      */
1130     public static function get_users_by_courseid_parameters() {
1131         global $CFG;
1132         require_once($CFG->dirroot . '/enrol/externallib.php');
1133         return core_enrol_external::get_enrolled_users_parameters();
1134     }
1136     /**
1137      * Get course participants details
1138      *
1139      * @param int $courseid  course id
1140      * @param array $options options {
1141      *                                'name' => option name
1142      *                                'value' => option value
1143      *                               }
1144      * @return array An array of users
1145      * @since Moodle 2.1
1146      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1147      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1148      * @see core_enrol_external::get_enrolled_users()
1149      */
1150     public static function get_users_by_courseid($courseid, $options) {
1151         global $CFG;
1152         require_once($CFG->dirroot . '/enrol/externallib.php');
1153         return core_enrol_external::get_enrolled_users($courseid, $options);
1154     }
1155     /**
1156      * Returns description of method result value
1157      *
1158      * @return external_description
1159      * @since Moodle 2.1
1160      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
1161      * @todo MDL-31194 This will be deleted in Moodle 2.5.
1162      * @see core_enrol_external::get_enrolled_users_returns()
1163      */
1164     public static function get_users_by_courseid_returns() {
1165         global $CFG;
1166         require_once($CFG->dirroot . '/enrol/externallib.php');
1167         return core_enrol_external::get_enrolled_users_returns();
1168     }