MDL-33869 user_get_user_details: add support for 'Show user identity' fields set...
[moodle.git] / user / lib.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * External user API
20  *
21  * @package    moodlecore
22  * @subpackage user
23  * @copyright  2009 Moodle Pty Ltd (http://moodle.com)
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
28 /**
29  * Creates a user
30  *
31  * @param object $user user to create
32  * @return int id of the newly created user
33  */
34 function user_create_user($user) {
35     global $DB;
37     // set the timecreate field to the current time
38     if (!is_object($user)) {
39             $user = (object)$user;
40     }
42     //check username
43     if ($user->username !== textlib::strtolower($user->username)) {
44         throw new moodle_exception('usernamelowercase');
45     } else {
46         if ($user->username !== clean_param($user->username, PARAM_USERNAME)) {
47             throw new moodle_exception('invalidusername');
48         }
49     }
51     // save the password in a temp value for later
52     if (isset($user->password)) {
54         //check password toward the password policy
55         if (!check_password_policy($user->password, $errmsg)) {
56             throw new moodle_exception($errmsg);
57         }
59         $userpassword = $user->password;
60         unset($user->password);
61     }
63     $user->timecreated = time();
64     $user->timemodified = $user->timecreated;
66     // insert the user into the database
67     $newuserid = $DB->insert_record('user', $user);
69     // trigger user_created event on the full database user row
70     $newuser = $DB->get_record('user', array('id' => $newuserid));
72     // create USER context for this user
73     get_context_instance(CONTEXT_USER, $newuserid);
75     // update user password if necessary
76     if (isset($userpassword)) {
77         $authplugin = get_auth_plugin($newuser->auth);
78         $authplugin->user_update_password($newuser, $userpassword);
79     }
81     events_trigger('user_created', $newuser);
83     add_to_log(SITEID, 'user', get_string('create'), '/view.php?id='.$newuser->id,
84         fullname($newuser));
86     return $newuserid;
88 }
90 /**
91  * Update a user with a user object (will compare against the ID)
92  *
93  * @param object $user the user to update
94  */
95 function user_update_user($user) {
96     global $DB;
98     // set the timecreate field to the current time
99     if (!is_object($user)) {
100             $user = (object)$user;
101     }
103     //check username
104     if (isset($user->username)) {
105         if ($user->username !== textlib::strtolower($user->username)) {
106             throw new moodle_exception('usernamelowercase');
107         } else {
108             if ($user->username !== clean_param($user->username, PARAM_USERNAME)) {
109                 throw new moodle_exception('invalidusername');
110             }
111         }
112     }
114     // unset password here, for updating later
115     if (isset($user->password)) {
117         //check password toward the password policy
118         if (!check_password_policy($user->password, $errmsg)) {
119             throw new moodle_exception($errmsg);
120         }
122         $passwd = $user->password;
123         unset($user->password);
124     }
126     $user->timemodified = time();
127     $DB->update_record('user', $user);
129     // trigger user_updated event on the full database user row
130     $updateduser = $DB->get_record('user', array('id' => $user->id));
132     // if password was set, then update its hash
133     if (isset($passwd)) {
134         $authplugin = get_auth_plugin($updateduser->auth);
135         if ($authplugin->can_change_password()) {
136             $authplugin->user_update_password($updateduser, $passwd);
137         }
138     }
140     events_trigger('user_updated', $updateduser);
142     add_to_log(SITEID, 'user', get_string('update'), '/view.php?id='.$updateduser->id,
143         fullname($updateduser));
147 /**
148  * Marks user deleted in internal user database and notifies the auth plugin.
149  * Also unenrols user from all roles and does other cleanup.
150  *
151  * @todo Decide if this transaction is really needed (look for internal TODO:)
152  * @param object $user Userobject before delete    (without system magic quotes)
153  * @return boolean success
154  */
155 function user_delete_user($user) {
156     return delete_user($user);
159 /**
160  * Get users by id
161  * @param array $userids id of users to retrieve
162  *
163  */
164 function user_get_users_by_id($userids) {
165     global $DB;
166     return $DB->get_records_list('user', 'id', $userids);
170 /**
171  *
172  * Give user record from mdl_user, build an array conntains
173  * all user details
174  *
175  * Warning: description file urls are 'webservice/pluginfile.php' is use.
176  *          it can be changed with $CFG->moodlewstextformatlinkstoimagesfile
177  *
178  * @param stdClass $user user record from mdl_user
179  * @param stdClass $context context object
180  * @param stdClass $course moodle course
181  * @param array $userfields required fields
182  * @return array
183  */
184 function user_get_user_details($user, $course = null, array $userfields = array()) {
185     global $USER, $DB, $CFG;
186     require_once($CFG->dirroot . "/user/profile/lib.php"); //custom field library
187     require_once($CFG->dirroot . "/lib/filelib.php");      // file handling on description and friends
189     $defaultfields = array( 'id', 'username', 'fullname', 'firstname', 'lastname', 'email',
190         'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo', 'aim', 'msn', 'department',
191         'institution', 'interests', 'firstaccess', 'lastaccess', 'auth', 'confirmed',
192         'idnumber', 'lang', 'theme', 'timezone', 'mailformat', 'description', 'descriptionformat',
193         'city', 'url', 'country', 'profileimageurlsmall', 'profileimageurl', 'customfields',
194         'groups', 'roles', 'preferences', 'enrolledcourses'
195     );
197     if (empty($userfields)) {
198         $userfields = $defaultfields;
199     }
201     foreach ($userfields as $thefield) {
202         if (!in_array($thefield, $defaultfields)) {
203             throw new moodle_exception('invaliduserfield', 'error', '', $thefield);
204         }
205     }
208     // Make sure id and fullname are included
209     if (!in_array('id', $userfields)) {
210         $userfields[] = 'id';
211     }
213     if (!in_array('fullname', $userfields)) {
214         $userfields[] = 'fullname';
215     }
217     if (!empty($course)) {
218         $context = get_context_instance(CONTEXT_COURSE, $course->id);
219         $usercontext = get_context_instance(CONTEXT_USER, $user->id);
220         $canviewdetailscap = (has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext));
221     } else {
222         $context = get_context_instance(CONTEXT_USER, $user->id);
223         $usercontext = $context;
224         $canviewdetailscap = has_capability('moodle/user:viewdetails', $usercontext);
225     }
227     $currentuser = ($user->id == $USER->id);
228     $isadmin = is_siteadmin($USER);
230     $showuseridentityfields = get_extra_user_fields($context);
232     if (!empty($course)) {
233         $canviewhiddenuserfields = has_capability('moodle/course:viewhiddenuserfields', $context);
234     } else {
235         $canviewhiddenuserfields = has_capability('moodle/user:viewhiddendetails', $context);
236     }
237     $canviewfullnames        = has_capability('moodle/site:viewfullnames', $context);
238     if (!empty($course)) {
239         $canviewuseremail = has_capability('moodle/course:useremail', $context);
240     } else {
241         $canviewuseremail = false;
242     }
243     $cannotviewdescription   = !empty($CFG->profilesforenrolledusersonly) && !$currentuser && !$DB->record_exists('role_assignments', array('userid'=>$user->id));
244     if (!empty($course)) {
245         $canaccessallgroups = has_capability('moodle/site:accessallgroups', $context);
246     } else {
247         $canaccessallgroups = false;
248     }
250     if (!$currentuser && !$canviewdetailscap && !has_coursecontact_role($user->id)) {
251         // skip this user details
252         return null;
253     }
255     $userdetails = array();
256     $userdetails['id'] = $user->id;
258     if (($isadmin or $currentuser) and in_array('username', $userfields)) {
259         $userdetails['username'] = $user->username;
260     }
261     if ($isadmin or $canviewfullnames) {
262         if (in_array('firstname', $userfields)) {
263             $userdetails['firstname'] = $user->firstname;
264         }
265         if (in_array('lastname', $userfields)) {
266             $userdetails['lastname'] = $user->lastname;
267         }
268     }
269     $userdetails['fullname'] = fullname($user);
271     if (in_array('customfields', $userfields)) {
272         $fields = $DB->get_recordset_sql("SELECT f.*
273                                             FROM {user_info_field} f
274                                             JOIN {user_info_category} c
275                                                  ON f.categoryid=c.id
276                                         ORDER BY c.sortorder ASC, f.sortorder ASC");
277         $userdetails['customfields'] = array();
278         foreach ($fields as $field) {
279             require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
280             $newfield = 'profile_field_'.$field->datatype;
281             $formfield = new $newfield($field->id, $user->id);
282             if ($formfield->is_visible() and !$formfield->is_empty()) {
283                 $userdetails['customfields'][] =
284                     array('name' => $formfield->field->name, 'value' => $formfield->data,
285                         'type' => $field->datatype, 'shortname' => $formfield->field->shortname);
286             }
287         }
288         $fields->close();
289         // unset customfields if it's empty
290         if (empty($userdetails['customfields'])) {
291             unset($userdetails['customfields']);
292         }
293     }
295     // profile image
296     if (in_array('profileimageurl', $userfields)) {
297         $profileimageurl = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f1');
298         $userdetails['profileimageurl'] = $profileimageurl->out(false);
299     }
300     if (in_array('profileimageurlsmall', $userfields)) {
301         $profileimageurlsmall = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f2');
302         $userdetails['profileimageurlsmall'] = $profileimageurlsmall->out(false);
303     }
305     //hidden user field
306     if ($canviewhiddenuserfields) {
307         $hiddenfields = array();
308         // address, phone1 and phone2 not appears in hidden fields list
309         // but require viewhiddenfields capability
310         // according to user/profile.php
311         if ($user->address && in_array('address', $userfields)) {
312             $userdetails['address'] = $user->address;
313         }
314     } else {
315         $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
316     }
318     if ($user->phone1 && in_array('phone1', $userfields) &&
319             (isset($showuseridentityfields['phone1']) or $canviewhiddenuserfields)) {
320         $userdetails['phone1'] = $user->phone1;
321     }
322     if ($user->phone2 && in_array('phone2', $userfields) &&
323             (isset($showuseridentityfields['phone2']) or $canviewhiddenuserfields)) {
324         $userdetails['phone2'] = $user->phone2;
325     }
327     if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) {
328         if (!$cannotviewdescription) {
330             if (in_array('description', $userfields)) {
331                 // Always return the descriptionformat if description is requested.
332                 list($userdetails['description'], $userdetails['descriptionformat']) =
333                         external_format_text($user->description, $user->descriptionformat,
334                                 $usercontext->id, 'user', 'profile', null);
335             }
336         }
337     }
339     if (in_array('country', $userfields) && (!isset($hiddenfields['country']) or $isadmin) && $user->country) {
340         $userdetails['country'] = $user->country;
341     }
343     if (in_array('city', $userfields) && (!isset($hiddenfields['city']) or $isadmin) && $user->city) {
344         $userdetails['city'] = $user->city;
345     }
347     if (in_array('url', $userfields) && $user->url && (!isset($hiddenfields['webpage']) or $isadmin)) {
348         $url = $user->url;
349         if (strpos($user->url, '://') === false) {
350             $url = 'http://'. $url;
351         }
352         $user->url = clean_param($user->url, PARAM_URL);
353         $userdetails['url'] = $user->url;
354     }
356     if (in_array('icq', $userfields) && $user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) {
357         $userdetails['icq'] = $user->icq;
358     }
360     if (in_array('skype', $userfields) && $user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) {
361         $userdetails['skype'] = $user->skype;
362     }
363     if (in_array('yahoo', $userfields) && $user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) {
364         $userdetails['yahoo'] = $user->yahoo;
365     }
366     if (in_array('aim', $userfields) && $user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) {
367         $userdetails['aim'] = $user->aim;
368     }
369     if (in_array('msn', $userfields) && $user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) {
370         $userdetails['msn'] = $user->msn;
371     }
373     if (in_array('firstaccess', $userfields) && (!isset($hiddenfields['firstaccess']) or $isadmin)) {
374         if ($user->firstaccess) {
375             $userdetails['firstaccess'] = $user->firstaccess;
376         } else {
377             $userdetails['firstaccess'] = 0;
378         }
379     }
380     if (in_array('lastaccess', $userfields) && (!isset($hiddenfields['lastaccess']) or $isadmin)) {
381         if ($user->lastaccess) {
382             $userdetails['lastaccess'] = $user->lastaccess;
383         } else {
384             $userdetails['lastaccess'] = 0;
385         }
386     }
388     if (in_array('email', $userfields) && ($isadmin // The admin is allowed the users email
389       or $currentuser // Of course the current user is as well
390       or $canviewuseremail  // this is a capability in course context, it will be false in usercontext
391       or isset($showuseridentityfields['email'])
392       or $user->maildisplay == 1
393       or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER)))) {
394         $userdetails['email'] = $user->email;
395     }
397     if (in_array('interests', $userfields) && !empty($CFG->usetags)) {
398         require_once($CFG->dirroot . '/tag/lib.php');
399         if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) {
400             $userdetails['interests'] = $interests;
401         }
402     }
404     //Departement/Institution/Idnumber are not displayed on any profile, however you can get them from editing profile.
405     if ($isadmin or $currentuser or isset($showuseridentityfields['idnumber'])) {
406         if (in_array('idnumber', $userfields) && $user->idnumber) {
407             $userdetails['idnumber'] = $user->idnumber;
408         }
409     }
410     if ($isadmin or $currentuser or isset($showuseridentityfields['institution'])) {
411         if (in_array('institution', $userfields) && $user->institution) {
412             $userdetails['institution'] = $user->institution;
413         }
414     }
415     if ($isadmin or $currentuser or isset($showuseridentityfields['department'])) {
416         if (in_array('department', $userfields) && isset($user->department)) { //isset because it's ok to have department 0
417             $userdetails['department'] = $user->department;
418         }
419     }
421     if (in_array('roles', $userfields) && !empty($course)) {
422         // not a big secret
423         $roles = get_user_roles($context, $user->id, false);
424         $userdetails['roles'] = array();
425         foreach ($roles as $role) {
426             $userdetails['roles'][] = array(
427                 'roleid'       => $role->roleid,
428                 'name'         => $role->name,
429                 'shortname'    => $role->shortname,
430                 'sortorder'    => $role->sortorder
431             );
432         }
433     }
435     // If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group
436     if (in_array('groups', $userfields) && !empty($course) && $canaccessallgroups) {
437         $usergroups = groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid,
438                 'g.id, g.name,g.description,g.descriptionformat');
439         $userdetails['groups'] = array();
440         foreach ($usergroups as $group) {
441             list($group->description, $group->descriptionformat) =
442                 external_format_text($group->description, $group->descriptionformat,
443                         $context->id, 'group', 'description', $group->id);
444             $userdetails['groups'][] = array('id'=>$group->id, 'name'=>$group->name,
445                 'description'=>$group->description, 'descriptionformat'=>$group->descriptionformat);
446         }
447     }
448     //list of courses where the user is enrolled
449     if (in_array('enrolledcourses', $userfields) && !isset($hiddenfields['mycourses'])) {
450         $enrolledcourses = array();
451         if ($mycourses = enrol_get_users_courses($user->id, true)) {
452             foreach ($mycourses as $mycourse) {
453                 if ($mycourse->category) {
454                     $coursecontext = get_context_instance(CONTEXT_COURSE, $mycourse->id);
455                     $enrolledcourse = array();
456                     $enrolledcourse['id'] = $mycourse->id;
457                     $enrolledcourse['fullname'] = format_string($mycourse->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $mycourse->id)));
458                     $enrolledcourse['shortname'] = format_string($mycourse->shortname, true, array('context' => $coursecontext));
459                     $enrolledcourses[] = $enrolledcourse;
460                 }
461             }
462             $userdetails['enrolledcourses'] = $enrolledcourses;
463         }
464     }
466     //user preferences
467     if (in_array('preferences', $userfields) && $currentuser) {
468         $preferences = array();
469         $userpreferences = get_user_preferences();
470          foreach($userpreferences as $prefname => $prefvalue) {
471             $preferences[] = array('name' => $prefname, 'value' => $prefvalue);
472          }
473          $userdetails['preferences'] = $preferences;
474     }
476     return $userdetails;
479 /**
480  * Return a list of page types
481  * @param string $pagetype current page type
482  * @param stdClass $parentcontext Block's parent context
483  * @param stdClass $currentcontext Current context of block
484  */
485 function user_page_type_list($pagetype, $parentcontext, $currentcontext) {
486     return array('user-profile'=>get_string('page-user-profile', 'pagetype'));