MDL-45893 user_menu: fix to hide user_pictures from screen readers
[moodle.git] / user / lib.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * External user API
19  *
20  * @package   core_user
21  * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
26 /**
27  * Creates a user
28  *
29  * @throws moodle_exception
30  * @param stdClass $user user to create
31  * @param bool $updatepassword if true, authentication plugin will update password.
32  * @param bool $triggerevent set false if user_created event should not be triggred.
33  *             This will not affect user_password_updated event triggering.
34  * @return int id of the newly created user
35  */
36 function user_create_user($user, $updatepassword = true, $triggerevent = true) {
37     global $CFG, $DB;
39     // Set the timecreate field to the current time.
40     if (!is_object($user)) {
41         $user = (object) $user;
42     }
44     // Check username.
45     if ($user->username !== core_text::strtolower($user->username)) {
46         throw new moodle_exception('usernamelowercase');
47     } else {
48         if ($user->username !== clean_param($user->username, PARAM_USERNAME)) {
49             throw new moodle_exception('invalidusername');
50         }
51     }
53     // Save the password in a temp value for later.
54     if ($updatepassword && isset($user->password)) {
56         // Check password toward the password policy.
57         if (!check_password_policy($user->password, $errmsg)) {
58             throw new moodle_exception($errmsg);
59         }
61         $userpassword = $user->password;
62         unset($user->password);
63     }
65     // Make sure calendartype, if set, is valid.
66     if (!empty($user->calendartype)) {
67         $availablecalendartypes = \core_calendar\type_factory::get_list_of_calendar_types();
68         if (empty($availablecalendartypes[$user->calendartype])) {
69             $user->calendartype = $CFG->calendartype;
70         }
71     } else {
72         $user->calendartype = $CFG->calendartype;
73     }
75     // Apply default values for user preferences that are stored in users table.
76     if (!isset($user->maildisplay)) {
77         $user->maildisplay = $CFG->defaultpreference_maildisplay;
78     }
79     if (!isset($user->mailformat)) {
80         $user->mailformat = $CFG->defaultpreference_mailformat;
81     }
82     if (!isset($user->maildigest)) {
83         $user->maildigest = $CFG->defaultpreference_maildigest;
84     }
85     if (!isset($user->autosubscribe)) {
86         $user->autosubscribe = $CFG->defaultpreference_autosubscribe;
87     }
88     if (!isset($user->trackforums)) {
89         $user->trackforums = $CFG->defaultpreference_trackforums;
90     }
92     $user->timecreated = time();
93     $user->timemodified = $user->timecreated;
95     // Insert the user into the database.
96     $newuserid = $DB->insert_record('user', $user);
98     // Create USER context for this user.
99     $usercontext = context_user::instance($newuserid);
101     // Update user password if necessary.
102     if (isset($userpassword)) {
103         // Get full database user row, in case auth is default.
104         $newuser = $DB->get_record('user', array('id' => $newuserid));
105         $authplugin = get_auth_plugin($newuser->auth);
106         $authplugin->user_update_password($newuser, $userpassword);
107     }
109     // Trigger event If required.
110     if ($triggerevent) {
111         \core\event\user_created::create_from_userid($newuserid)->trigger();
112     }
114     return $newuserid;
117 /**
118  * Update a user with a user object (will compare against the ID)
119  *
120  * @throws moodle_exception
121  * @param stdClass $user the user to update
122  * @param bool $updatepassword if true, authentication plugin will update password.
123  * @param bool $triggerevent set false if user_updated event should not be triggred.
124  *             This will not affect user_password_updated event triggering.
125  */
126 function user_update_user($user, $updatepassword = true, $triggerevent = true) {
127     global $DB;
129     // Set the timecreate field to the current time.
130     if (!is_object($user)) {
131         $user = (object) $user;
132     }
134     // Check username.
135     if (isset($user->username)) {
136         if ($user->username !== core_text::strtolower($user->username)) {
137             throw new moodle_exception('usernamelowercase');
138         } else {
139             if ($user->username !== clean_param($user->username, PARAM_USERNAME)) {
140                 throw new moodle_exception('invalidusername');
141             }
142         }
143     }
145     // Unset password here, for updating later, if password update is required.
146     if ($updatepassword && isset($user->password)) {
148         // Check password toward the password policy.
149         if (!check_password_policy($user->password, $errmsg)) {
150             throw new moodle_exception($errmsg);
151         }
153         $passwd = $user->password;
154         unset($user->password);
155     }
157     // Make sure calendartype, if set, is valid.
158     if (!empty($user->calendartype)) {
159         $availablecalendartypes = \core_calendar\type_factory::get_list_of_calendar_types();
160         // If it doesn't exist, then unset this value, we do not want to update the user's value.
161         if (empty($availablecalendartypes[$user->calendartype])) {
162             unset($user->calendartype);
163         }
164     } else {
165         // Unset this variable, must be an empty string, which we do not want to update the calendartype to.
166         unset($user->calendartype);
167     }
169     $user->timemodified = time();
170     $DB->update_record('user', $user);
172     if ($updatepassword) {
173         // Get full user record.
174         $updateduser = $DB->get_record('user', array('id' => $user->id));
176         // If password was set, then update its hash.
177         if (isset($passwd)) {
178             $authplugin = get_auth_plugin($updateduser->auth);
179             if ($authplugin->can_change_password()) {
180                 $authplugin->user_update_password($updateduser, $passwd);
181             }
182         }
183     }
184     // Trigger event if required.
185     if ($triggerevent) {
186         \core\event\user_updated::create_from_userid($user->id)->trigger();
187     }
190 /**
191  * Marks user deleted in internal user database and notifies the auth plugin.
192  * Also unenrols user from all roles and does other cleanup.
193  *
194  * @todo Decide if this transaction is really needed (look for internal TODO:)
195  * @param object $user Userobject before delete    (without system magic quotes)
196  * @return boolean success
197  */
198 function user_delete_user($user) {
199     return delete_user($user);
202 /**
203  * Get users by id
204  *
205  * @param array $userids id of users to retrieve
206  * @return array
207  */
208 function user_get_users_by_id($userids) {
209     global $DB;
210     return $DB->get_records_list('user', 'id', $userids);
213 /**
214  * Returns the list of default 'displayable' fields
215  *
216  * Contains database field names but also names used to generate information, such as enrolledcourses
217  *
218  * @return array of user fields
219  */
220 function user_get_default_fields() {
221     return array( 'id', 'username', 'fullname', 'firstname', 'lastname', 'email',
222         'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo', 'aim', 'msn', 'department',
223         'institution', 'interests', 'firstaccess', 'lastaccess', 'auth', 'confirmed',
224         'idnumber', 'lang', 'theme', 'timezone', 'mailformat', 'description', 'descriptionformat',
225         'city', 'url', 'country', 'profileimageurlsmall', 'profileimageurl', 'customfields',
226         'groups', 'roles', 'preferences', 'enrolledcourses'
227     );
230 /**
231  *
232  * Give user record from mdl_user, build an array contains all user details.
233  *
234  * Warning: description file urls are 'webservice/pluginfile.php' is use.
235  *          it can be changed with $CFG->moodlewstextformatlinkstoimagesfile
236  *
237  * @throws moodle_exception
238  * @param stdClass $user user record from mdl_user
239  * @param stdClass $course moodle course
240  * @param array $userfields required fields
241  * @return array|null
242  */
243 function user_get_user_details($user, $course = null, array $userfields = array()) {
244     global $USER, $DB, $CFG;
245     require_once($CFG->dirroot . "/user/profile/lib.php"); // Custom field library.
246     require_once($CFG->dirroot . "/lib/filelib.php");      // File handling on description and friends.
248     $defaultfields = user_get_default_fields();
250     if (empty($userfields)) {
251         $userfields = $defaultfields;
252     }
254     foreach ($userfields as $thefield) {
255         if (!in_array($thefield, $defaultfields)) {
256             throw new moodle_exception('invaliduserfield', 'error', '', $thefield);
257         }
258     }
260     // Make sure id and fullname are included.
261     if (!in_array('id', $userfields)) {
262         $userfields[] = 'id';
263     }
265     if (!in_array('fullname', $userfields)) {
266         $userfields[] = 'fullname';
267     }
269     if (!empty($course)) {
270         $context = context_course::instance($course->id);
271         $usercontext = context_user::instance($user->id);
272         $canviewdetailscap = (has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext));
273     } else {
274         $context = context_user::instance($user->id);
275         $usercontext = $context;
276         $canviewdetailscap = has_capability('moodle/user:viewdetails', $usercontext);
277     }
279     $currentuser = ($user->id == $USER->id);
280     $isadmin = is_siteadmin($USER);
282     $showuseridentityfields = get_extra_user_fields($context);
284     if (!empty($course)) {
285         $canviewhiddenuserfields = has_capability('moodle/course:viewhiddenuserfields', $context);
286     } else {
287         $canviewhiddenuserfields = has_capability('moodle/user:viewhiddendetails', $context);
288     }
289     $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
290     if (!empty($course)) {
291         $canviewuseremail = has_capability('moodle/course:useremail', $context);
292     } else {
293         $canviewuseremail = false;
294     }
295     $cannotviewdescription   = !empty($CFG->profilesforenrolledusersonly) && !$currentuser && !$DB->record_exists('role_assignments', array('userid' => $user->id));
296     if (!empty($course)) {
297         $canaccessallgroups = has_capability('moodle/site:accessallgroups', $context);
298     } else {
299         $canaccessallgroups = false;
300     }
302     if (!$currentuser && !$canviewdetailscap && !has_coursecontact_role($user->id)) {
303         // Skip this user details.
304         return null;
305     }
307     $userdetails = array();
308     $userdetails['id'] = $user->id;
310     if (($isadmin or $currentuser) and in_array('username', $userfields)) {
311         $userdetails['username'] = $user->username;
312     }
313     if ($isadmin or $canviewfullnames) {
314         if (in_array('firstname', $userfields)) {
315             $userdetails['firstname'] = $user->firstname;
316         }
317         if (in_array('lastname', $userfields)) {
318             $userdetails['lastname'] = $user->lastname;
319         }
320     }
321     $userdetails['fullname'] = fullname($user);
323     if (in_array('customfields', $userfields)) {
324         $fields = $DB->get_recordset_sql("SELECT f.*
325                                             FROM {user_info_field} f
326                                             JOIN {user_info_category} c
327                                                  ON f.categoryid=c.id
328                                         ORDER BY c.sortorder ASC, f.sortorder ASC");
329         $userdetails['customfields'] = array();
330         foreach ($fields as $field) {
331             require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
332             $newfield = 'profile_field_'.$field->datatype;
333             $formfield = new $newfield($field->id, $user->id);
334             if ($formfield->is_visible() and !$formfield->is_empty()) {
335                 $userdetails['customfields'][] =
336                     array('name' => $formfield->field->name, 'value' => $formfield->data,
337                         'type' => $field->datatype, 'shortname' => $formfield->field->shortname);
338             }
339         }
340         $fields->close();
341         // Unset customfields if it's empty.
342         if (empty($userdetails['customfields'])) {
343             unset($userdetails['customfields']);
344         }
345     }
347     // Profile image.
348     if (in_array('profileimageurl', $userfields)) {
349         $profileimageurl = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', null, '/', 'f1');
350         $userdetails['profileimageurl'] = $profileimageurl->out(false);
351     }
352     if (in_array('profileimageurlsmall', $userfields)) {
353         $profileimageurlsmall = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', null, '/', 'f2');
354         $userdetails['profileimageurlsmall'] = $profileimageurlsmall->out(false);
355     }
357     // Hidden user field.
358     if ($canviewhiddenuserfields) {
359         $hiddenfields = array();
360         // Address, phone1 and phone2 not appears in hidden fields list but require viewhiddenfields capability
361         // according to user/profile.php.
362         if ($user->address && in_array('address', $userfields)) {
363             $userdetails['address'] = $user->address;
364         }
365     } else {
366         $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
367     }
369     if ($user->phone1 && in_array('phone1', $userfields) &&
370             (in_array('phone1', $showuseridentityfields) or $canviewhiddenuserfields)) {
371         $userdetails['phone1'] = $user->phone1;
372     }
373     if ($user->phone2 && in_array('phone2', $userfields) &&
374             (in_array('phone2', $showuseridentityfields) or $canviewhiddenuserfields)) {
375         $userdetails['phone2'] = $user->phone2;
376     }
378     if (isset($user->description) &&
379         ((!isset($hiddenfields['description']) && !$cannotviewdescription) or $isadmin)) {
380         if (in_array('description', $userfields)) {
381             // Always return the descriptionformat if description is requested.
382             list($userdetails['description'], $userdetails['descriptionformat']) =
383                     external_format_text($user->description, $user->descriptionformat,
384                             $usercontext->id, 'user', 'profile', null);
385         }
386     }
388     if (in_array('country', $userfields) && (!isset($hiddenfields['country']) or $isadmin) && $user->country) {
389         $userdetails['country'] = $user->country;
390     }
392     if (in_array('city', $userfields) && (!isset($hiddenfields['city']) or $isadmin) && $user->city) {
393         $userdetails['city'] = $user->city;
394     }
396     if (in_array('url', $userfields) && $user->url && (!isset($hiddenfields['webpage']) or $isadmin)) {
397         $url = $user->url;
398         if (strpos($user->url, '://') === false) {
399             $url = 'http://'. $url;
400         }
401         $user->url = clean_param($user->url, PARAM_URL);
402         $userdetails['url'] = $user->url;
403     }
405     if (in_array('icq', $userfields) && $user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) {
406         $userdetails['icq'] = $user->icq;
407     }
409     if (in_array('skype', $userfields) && $user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) {
410         $userdetails['skype'] = $user->skype;
411     }
412     if (in_array('yahoo', $userfields) && $user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) {
413         $userdetails['yahoo'] = $user->yahoo;
414     }
415     if (in_array('aim', $userfields) && $user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) {
416         $userdetails['aim'] = $user->aim;
417     }
418     if (in_array('msn', $userfields) && $user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) {
419         $userdetails['msn'] = $user->msn;
420     }
422     if (in_array('firstaccess', $userfields) && (!isset($hiddenfields['firstaccess']) or $isadmin)) {
423         if ($user->firstaccess) {
424             $userdetails['firstaccess'] = $user->firstaccess;
425         } else {
426             $userdetails['firstaccess'] = 0;
427         }
428     }
429     if (in_array('lastaccess', $userfields) && (!isset($hiddenfields['lastaccess']) or $isadmin)) {
430         if ($user->lastaccess) {
431             $userdetails['lastaccess'] = $user->lastaccess;
432         } else {
433             $userdetails['lastaccess'] = 0;
434         }
435     }
437     if (in_array('email', $userfields) && ($isadmin // The admin is allowed the users email.
438       or $currentuser // Of course the current user is as well.
439       or $canviewuseremail  // This is a capability in course context, it will be false in usercontext.
440       or in_array('email', $showuseridentityfields)
441       or $user->maildisplay == 1
442       or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER)))) {
443         $userdetails['email'] = $user->email;
444     }
446     if (in_array('interests', $userfields) && !empty($CFG->usetags)) {
447         require_once($CFG->dirroot . '/tag/lib.php');
448         if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) {
449             $userdetails['interests'] = $interests;
450         }
451     }
453     // Departement/Institution/Idnumber are not displayed on any profile, however you can get them from editing profile.
454     if ($isadmin or $currentuser or in_array('idnumber', $showuseridentityfields)) {
455         if (in_array('idnumber', $userfields) && $user->idnumber) {
456             $userdetails['idnumber'] = $user->idnumber;
457         }
458     }
459     if ($isadmin or $currentuser or in_array('institution', $showuseridentityfields)) {
460         if (in_array('institution', $userfields) && $user->institution) {
461             $userdetails['institution'] = $user->institution;
462         }
463     }
464     if ($isadmin or $currentuser or in_array('department', $showuseridentityfields)) {
465         if (in_array('department', $userfields) && isset($user->department)) { // Isset because it's ok to have department 0.
466             $userdetails['department'] = $user->department;
467         }
468     }
470     if (in_array('roles', $userfields) && !empty($course)) {
471         // Not a big secret.
472         $roles = get_user_roles($context, $user->id, false);
473         $userdetails['roles'] = array();
474         foreach ($roles as $role) {
475             $userdetails['roles'][] = array(
476                 'roleid'       => $role->roleid,
477                 'name'         => $role->name,
478                 'shortname'    => $role->shortname,
479                 'sortorder'    => $role->sortorder
480             );
481         }
482     }
484     // If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group.
485     if (in_array('groups', $userfields) && !empty($course) && $canaccessallgroups) {
486         $usergroups = groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid,
487                 'g.id, g.name,g.description,g.descriptionformat');
488         $userdetails['groups'] = array();
489         foreach ($usergroups as $group) {
490             list($group->description, $group->descriptionformat) =
491                 external_format_text($group->description, $group->descriptionformat,
492                         $context->id, 'group', 'description', $group->id);
493             $userdetails['groups'][] = array('id' => $group->id, 'name' => $group->name,
494                 'description' => $group->description, 'descriptionformat' => $group->descriptionformat);
495         }
496     }
497     // List of courses where the user is enrolled.
498     if (in_array('enrolledcourses', $userfields) && !isset($hiddenfields['mycourses'])) {
499         $enrolledcourses = array();
500         if ($mycourses = enrol_get_users_courses($user->id, true)) {
501             foreach ($mycourses as $mycourse) {
502                 if ($mycourse->category) {
503                     $coursecontext = context_course::instance($mycourse->id);
504                     $enrolledcourse = array();
505                     $enrolledcourse['id'] = $mycourse->id;
506                     $enrolledcourse['fullname'] = format_string($mycourse->fullname, true, array('context' => $coursecontext));
507                     $enrolledcourse['shortname'] = format_string($mycourse->shortname, true, array('context' => $coursecontext));
508                     $enrolledcourses[] = $enrolledcourse;
509                 }
510             }
511             $userdetails['enrolledcourses'] = $enrolledcourses;
512         }
513     }
515     // User preferences.
516     if (in_array('preferences', $userfields) && $currentuser) {
517         $preferences = array();
518         $userpreferences = get_user_preferences();
519         foreach ($userpreferences as $prefname => $prefvalue) {
520             $preferences[] = array('name' => $prefname, 'value' => $prefvalue);
521         }
522         $userdetails['preferences'] = $preferences;
523     }
525     return $userdetails;
528 /**
529  * Tries to obtain user details, either recurring directly to the user's system profile
530  * or through one of the user's course enrollments (course profile).
531  *
532  * @param stdClass $user The user.
533  * @return array if unsuccessful or the allowed user details.
534  */
535 function user_get_user_details_courses($user) {
536     global $USER;
537     $userdetails = null;
539     // Get the courses that the user is enrolled in (only active).
540     $courses = enrol_get_users_courses($user->id, true);
542     $systemprofile = false;
543     if (can_view_user_details_cap($user) || ($user->id == $USER->id) || has_coursecontact_role($user->id)) {
544         $systemprofile = true;
545     }
547     // Try using system profile.
548     if ($systemprofile) {
549         $userdetails = user_get_user_details($user, null);
550     } else {
551         // Try through course profile.
552         foreach ($courses as $course) {
553             if (can_view_user_details_cap($user, $course) || ($user->id == $USER->id) || has_coursecontact_role($user->id)) {
554                 $userdetails = user_get_user_details($user, $course);
555             }
556         }
557     }
559     return $userdetails;
562 /**
563  * Check if $USER have the necessary capabilities to obtain user details.
564  *
565  * @param stdClass $user
566  * @param stdClass $course if null then only consider system profile otherwise also consider the course's profile.
567  * @return bool true if $USER can view user details.
568  */
569 function can_view_user_details_cap($user, $course = null) {
570     // Check $USER has the capability to view the user details at user context.
571     $usercontext = context_user::instance($user->id);
572     $result = has_capability('moodle/user:viewdetails', $usercontext);
573     // Otherwise can $USER see them at course context.
574     if (!$result && !empty($course)) {
575         $context = context_course::instance($course->id);
576         $result = has_capability('moodle/user:viewdetails', $context);
577     }
578     return $result;
581 /**
582  * Return a list of page types
583  * @param string $pagetype current page type
584  * @param stdClass $parentcontext Block's parent context
585  * @param stdClass $currentcontext Current context of block
586  * @return array
587  */
588 function user_page_type_list($pagetype, $parentcontext, $currentcontext) {
589     return array('user-profile' => get_string('page-user-profile', 'pagetype'));
592 /**
593  * Count the number of failed login attempts for the given user, since last successful login.
594  *
595  * @param int|stdclass $user user id or object.
596  * @param bool $reset Resets failed login count, if set to true.
597  *
598  * @return int number of failed login attempts since the last successful login.
599  */
600 function user_count_login_failures($user, $reset = true) {
601     global $DB;
603     if (!is_object($user)) {
604         $user = $DB->get_record('user', array('id' => $user), '*', MUST_EXIST);
605     }
606     if ($user->deleted) {
607         // Deleted user, nothing to do.
608         return 0;
609     }
610     $count = get_user_preferences('login_failed_count_since_success', 0, $user);
611     if ($reset) {
612         set_user_preference('login_failed_count_since_success', 0, $user);
613     }
614     return $count;
617 /**
618  * Get a list of essential user navigation items.
619  *
620  * @param stdclass $user user object.
621  * @param moodle_page $page page object.
622  * @return stdClass $returnobj navigation information object, where:
623  *
624  *      $returnobj->navitems    array    array of links where each link is a
625  *                                       stdClass with fields url, title, and
626  *                                       pix
627  *      $returnobj->metadata    array    array of useful user metadata to be
628  *                                       used when constructing navigation;
629  *                                       fields include:
630  *
631  *          ROLE FIELDS
632  *          asotherrole    bool    whether viewing as another role
633  *          rolename       string  name of the role
634  *
635  *          USER FIELDS
636  *          These fields are for the currently-logged in user, or for
637  *          the user that the real user is currently logged in as.
638  *
639  *          userid         int        the id of the user in question
640  *          userfullname   string     the user's full name
641  *          userprofileurl moodle_url the url of the user's profile
642  *          useravatar     string     a HTML fragment - the rendered
643  *                                    user_picture for this user
644  *
645  *          "REAL USER" FIELDS
646  *          These fields are for when asotheruser is true, and
647  *          correspond to the underlying "real user".
648  *
649  *          asotheruser        bool    whether viewing as another user
650  *          realuserid         int        the id of the user in question
651  *          realuserfullname   string     the user's full name
652  *          realuserprofileurl moodle_url the url of the user's profile
653  *          realuseravatar     string     a HTML fragment - the rendered
654  *                                        user_picture for this user
655  *
656  *          MNET PROVIDER FIELDS
657  *          asmnetuser            bool   whether viewing as a user from an
658  *                                       MNet provider
659  *          mnetidprovidername    string name of the MNet provider
660  *          mnetidproviderwwwroot string URL of the MNet provider
661  */
662 function user_get_user_navigation_info($user, $page) {
663     global $OUTPUT, $DB;
665     $returnobject = new stdClass();
666     $returnobject->navitems = array();
667     $returnobject->metadata = array();
669     $course = $page->course;
671     // Query the environment.
672     $context = context_course::instance($course->id);
674     // Get basic user metadata.
675     $returnobject->metadata['userid'] = $user->id;
676     $returnobject->metadata['userfullname'] = fullname($user, true);
677     $returnobject->metadata['userprofileurl'] = new moodle_url('/user/profile.php', array(
678         'id' => $user->id
679     ));
680     $returnobject->metadata['useravatar'] = $OUTPUT->user_picture (
681         $user,
682         array(
683             'link' => false,
684             'visibletoscreenreaders' => false
685         )
686     );
687     if (isguestuser()) {
689         // Build a list of items for a guest.
690         $login = new stdClass();
691         $login->url = new moodle_url(get_login_url());
692         $login->title = get_string('login');
693         // TODO MDL-47457: we should be setting a login icon here.
694         $returnobject->navitems[] = $login;
696     } else {
697         // Build a list of items for a regular user.
699         // Query MNet status.
700         if ($returnobject->metadata['asmnetuser'] = is_mnet_remote_user($user)) {
701             $mnetidprovider = $DB->get_record('mnet_host', array('id' => $user->mnethostid));
702             $returnobject->metadata['mnetidprovidername'] = $mnetidprovider->name;
703             $returnobject->metadata['mnetidproviderwwwroot'] = $mnetidprovider->wwwroot;
704         }
706         // Links: My Profile.
707         $myprofile = new stdClass();
708         $myprofile->url = new moodle_url('/user/profile.php', array('id' => $user->id));
709         $myprofile->title = get_string('myprofile');
710         $myprofile->pix = "i/user";
711         $returnobject->navitems[] = $myprofile;
713         // Links: My Home.
714         $myhome = new stdClass();
715         $myhome->url = new moodle_url('/my/');
716         $myhome->title = get_string('mymoodle', 'admin');
717         $myhome->pix = "i/course";
718         $returnobject->navitems[] = $myhome;
720         // Links: Role-return or logout link.
721         $lastobj = null;
722         $buildlogout = true;
723         $returnobject->metadata['asotherrole'] = false;
724         if (is_role_switched($course->id)) {
725             if ($role = $DB->get_record('role', array('id' => $user->access['rsw'][$context->path]))) {
726                 // Build role-return link instead of logout link.
727                 $rolereturn = new stdClass();
728                 $rolereturn->url = new moodle_url('/course/switchrole.php', array(
729                     'id' => $course->id,
730                     'sesskey' => sesskey(),
731                     'switchrole' => 0,
732                     'returnurl' => $PAGE->url->out_as_local_url(false)
733                 ));
734                 $rolereturn->pix = "a/logout";
735                 $rolereturn->title = get_string('switchrolereturn');
736                 $lastobj = $rolereturn;
738                 $returnobject->metadata['asotherrole'] = true;
739                 $returnobject->metadata['rolename'] = role_get_name($role, $context);
741                 $buildlogout = false;
742             }
743         }
745         if ($returnobject->metadata['asotheruser'] = \core\session\manager::is_loggedinas()) {
746             $realuser = \core\session\manager::get_realuser();
748             // Save values for the real user, as $user will be full of data for the
749             // user the user is disguised as.
750             $returnobject->metadata['realuserid'] = $realuser->id;
751             $returnobject->metadata['realuserfullname'] = fullname($realuser, true);
752             $returnobject->metadata['realuserprofileurl'] = new moodle_url('/user/profile.php', array(
753                 'id' => $realuser->id
754             ));
755             $returnobject->metadata['realuseravatar'] = $OUTPUT->user_picture (
756                 $realuser,
757                 array(
758                     'link' => false,
759                     'visibletoscreenreaders' => false
760                 )
761             );
763             // Build a user-revert link.
764             $userrevert = new stdClass();
765             $userrevert->url = new moodle_url('/course/loginas.php', array(
766                 'id' => $course->id,
767                 'sesskey' => sesskey()
768             ));
769             $userrevert->pix = "a/logout";
770             $userrevert->title = get_string('userrevert');
771             $lastobj = $userrevert;
773             $buildlogout = false;
774         }
776         if ($buildlogout) {
777             // Build a logout link.
778             $logout = new stdClass();
779             $logout->url = new moodle_url('/login/logout.php', array('sesskey' => sesskey()));
780             $logout->pix = "a/logout";
781             $logout->title = get_string('logout');
782             $lastobj = $logout;
783         }
785         // Add the last item to the list.
786         if (!is_null($lastobj)) {
787             $returnobject->navitems[] = $lastobj;
788         }
789     }
791     return $returnobject;