weekly release 2.3dev
[moodle.git] / user / lib.php
CommitLineData
fb79269b 1<?php
2
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/>.
17
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 */
26
27
28/**
29 * Creates a user
adfb459c 30 *
fb79269b 31 * @param object $user user to create
32 * @return int id of the newly created user
33 */
34function user_create_user($user) {
35 global $DB;
36
adfb459c 37 // set the timecreate field to the current time
fb79269b 38 if (!is_object($user)) {
39 $user = (object)$user;
40 }
bd0f26bd 41
adfb459c
JM
42 // save the password in a temp value for later
43 if (isset($user->password)) {
44
45 //check password toward the password policy
46 if (!check_password_policy($user->password, $errmsg)) {
47 throw new moodle_exception($errmsg);
48 }
49
50 $userpassword = $user->password;
51 unset($user->password);
52 }
bd0f26bd 53
fb79269b 54 $user->timecreated = time();
bd0f26bd 55 $user->timemodified = $user->timecreated;
fb79269b 56
adfb459c 57 // insert the user into the database
fb79269b 58 $newuserid = $DB->insert_record('user', $user);
59
adfb459c 60 // trigger user_created event on the full database user row
b6dcb7d9 61 $newuser = $DB->get_record('user', array('id' => $newuserid));
b6dcb7d9 62
adfb459c 63 // create USER context for this user
a0760047 64 get_context_instance(CONTEXT_USER, $newuserid);
21c968b4 65
adfb459c
JM
66 // update user password if necessary
67 if (isset($userpassword)) {
68 $authplugin = get_auth_plugin($newuser->auth);
69 $authplugin->user_update_password($newuser, $userpassword);
70 }
71
72 events_trigger('user_created', $newuser);
73
74 add_to_log(SITEID, 'user', get_string('create'), '/view.php?id='.$newuser->id,
75 fullname($newuser));
76
fb79269b 77 return $newuserid;
bd0f26bd 78
fb79269b 79}
80
81/**
82 * Update a user with a user object (will compare against the ID)
adfb459c
JM
83 *
84 * @param object $user the user to update
fb79269b 85 */
86function user_update_user($user) {
87 global $DB;
bd0f26bd 88
adfb459c 89 // set the timecreate field to the current time
bd0f26bd 90 if (!is_object($user)) {
91 $user = (object)$user;
92 }
adfb459c
JM
93
94 // unset password here, for updating later
9e63c0ff 95 if (isset($user->password)) {
adfb459c
JM
96
97 //check password toward the password policy
98 if (!check_password_policy($user->password, $errmsg)) {
99 throw new moodle_exception($errmsg);
100 }
101
9e63c0ff
FS
102 $passwd = $user->password;
103 unset($user->password);
104 }
bd0f26bd 105
106 $user->timemodified = time();
fb79269b 107 $DB->update_record('user', $user);
b6dcb7d9 108
adfb459c 109 // trigger user_updated event on the full database user row
b6dcb7d9 110 $updateduser = $DB->get_record('user', array('id' => $user->id));
9e63c0ff 111
adfb459c
JM
112 // if password was set, then update its hash
113 if (isset($passwd)) {
114 $authplugin = get_auth_plugin($updateduser->auth);
115 if ($authplugin->can_change_password()) {
116 $authplugin->user_update_password($updateduser, $passwd);
117 }
118 }
9e63c0ff 119
b6dcb7d9
JM
120 events_trigger('user_updated', $updateduser);
121
adfb459c
JM
122 add_to_log(SITEID, 'user', get_string('update'), '/view.php?id='.$updateduser->id,
123 fullname($updateduser));
fb79269b 124
adfb459c 125}
fb79269b 126
127/**
128 * Marks user deleted in internal user database and notifies the auth plugin.
129 * Also unenrols user from all roles and does other cleanup.
130 *
131 * @todo Decide if this transaction is really needed (look for internal TODO:)
132 * @param object $user Userobject before delete (without system magic quotes)
133 * @return boolean success
134 */
135function user_delete_user($user) {
45fb2cf8 136 return delete_user($user);
fb79269b 137}
138
139/**
140 * Get users by id
141 * @param array $userids id of users to retrieve
142 *
143 */
144function user_get_users_by_id($userids) {
145 global $DB;
146 return $DB->get_records_list('user', 'id', $userids);
147}
b1627a92 148
01479290
DC
149
150/**
151 *
152 * Give user record from mdl_user, build an array conntains
153 * all user details
154 * @param stdClass $user user record from mdl_user
155 * @param stdClass $context context object
156 * @param stdClass $course moodle course
ad7612f5 157 * @param array $userfields required fields
01479290
DC
158 * @return array
159 */
ad7612f5 160function user_get_user_details($user, $course = null, array $userfields = array()) {
01479290
DC
161 global $USER, $DB, $CFG;
162 require_once($CFG->dirroot . "/user/profile/lib.php"); //custom field library
163 require_once($CFG->dirroot . "/lib/filelib.php"); // file handling on description and friends
164
ad7612f5
DC
165 $defaultfields = array( 'id', 'username', 'fullname', 'firstname', 'lastname', 'email',
166 'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo', 'aim', 'msn', 'department',
167 'institution', 'interests', 'firstaccess', 'lastaccess', 'auth', 'confirmed',
168 'idnumber', 'lang', 'theme', 'timezone', 'mailformat', 'description', 'descriptionformat',
169 'city', 'url', 'country', 'profileimageurlsmall', 'profileimageurl', 'customfields',
170 'groups', 'roles', 'preferences', 'enrolledcourses'
171 );
172
173 if (empty($userfields)) {
174 $userfields = $defaultfields;
175 }
176
177 foreach ($userfields as $thefield) {
178 if (!in_array($thefield, $defaultfields)) {
179 throw new moodle_exception('invaliduserfield', 'error', '', $thefield);
180 }
181 }
182
183
184 // Make sure id and fullname are included
185 if (!in_array('id', $userfields)) {
186 $userfields[] = 'id';
187 }
188
189 if (!in_array('fullname', $userfields)) {
190 $userfields[] = 'fullname';
191 }
192
01479290
DC
193 if (!empty($course)) {
194 $context = get_context_instance(CONTEXT_COURSE, $course->id);
195 $usercontext = get_context_instance(CONTEXT_USER, $user->id);
1e539f64 196 $canviewdetailscap = (has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext));
01479290
DC
197 } else {
198 $context = get_context_instance(CONTEXT_USER, $user->id);
199 $usercontext = $context;
1e539f64 200 $canviewdetailscap = has_capability('moodle/user:viewdetails', $usercontext);
01479290
DC
201 }
202
203 $currentuser = ($user->id == $USER->id);
204 $isadmin = is_siteadmin($USER);
205
206 if (!empty($course)) {
207 $canviewhiddenuserfields = has_capability('moodle/course:viewhiddenuserfields', $context);
208 } else {
209 $canviewhiddenuserfields = has_capability('moodle/user:viewhiddendetails', $context);
210 }
01479290
DC
211 $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
212 if (!empty($course)) {
213 $canviewuseremail = has_capability('moodle/course:useremail', $context);
214 } else {
215 $canviewuseremail = false;
216 }
217 $cannotviewdescription = !empty($CFG->profilesforenrolledusersonly) && !$currentuser && !$DB->record_exists('role_assignments', array('userid'=>$user->id));
218 if (!empty($course)) {
219 $canaccessallgroups = has_capability('moodle/site:accessallgroups', $context);
220 } else {
221 $canaccessallgroups = false;
222 }
223
224 if (!$currentuser && !$canviewdetailscap && !has_coursecontact_role($user->id)) {
225 // skip this user details
226 return null;
227 }
228
229 $userdetails = array();
230 $userdetails['id'] = $user->id;
231
ad7612f5 232 if (($isadmin or $currentuser) and in_array('username', $userfields)) {
01479290
DC
233 $userdetails['username'] = $user->username;
234 }
235 if ($isadmin or $canviewfullnames) {
ad7612f5
DC
236 if (in_array('firstname', $userfields)) {
237 $userdetails['firstname'] = $user->firstname;
238 }
239 if (in_array('lastname', $userfields)) {
240 $userdetails['lastname'] = $user->lastname;
241 }
01479290
DC
242 }
243 $userdetails['fullname'] = fullname($user);
244
ad7612f5
DC
245 if (in_array('customfields', $userfields)) {
246 $fields = $DB->get_recordset_sql("SELECT f.*
247 FROM {user_info_field} f
248 JOIN {user_info_category} c
249 ON f.categoryid=c.id
250 ORDER BY c.sortorder ASC, f.sortorder ASC");
251 $userdetails['customfields'] = array();
252 foreach ($fields as $field) {
253 require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
254 $newfield = 'profile_field_'.$field->datatype;
255 $formfield = new $newfield($field->id, $user->id);
256 if ($formfield->is_visible() and !$formfield->is_empty()) {
257 $userdetails['customfields'][] =
258 array('name' => $formfield->field->name, 'value' => $formfield->data,
259 'type' => $field->datatype, 'shortname' => $formfield->field->shortname);
260 }
261 }
262 $fields->close();
263 // unset customfields if it's empty
264 if (empty($userdetails['customfields'])) {
265 unset($userdetails['customfields']);
01479290 266 }
01479290
DC
267 }
268
269 // profile image
ad7612f5
DC
270 if (in_array('profileimageurl', $userfields)) {
271 $profileimageurl = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f1');
272 $userdetails['profileimageurl'] = $profileimageurl->out(false);
273 }
274 if (in_array('profileimageurlsmall', $userfields)) {
275 $profileimageurlsmall = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f2');
276 $userdetails['profileimageurlsmall'] = $profileimageurlsmall->out(false);
277 }
01479290
DC
278
279 //hidden user field
280 if ($canviewhiddenuserfields) {
281 $hiddenfields = array();
282 // address, phone1 and phone2 not appears in hidden fields list
283 // but require viewhiddenfields capability
284 // according to user/profile.php
ad7612f5 285 if ($user->address && in_array('address', $userfields)) {
01479290
DC
286 $userdetails['address'] = $user->address;
287 }
ad7612f5 288 if ($user->phone1 && in_array('phone1', $userfields)) {
01479290
DC
289 $userdetails['phone1'] = $user->phone1;
290 }
ad7612f5 291 if ($user->phone2 && in_array('phone2', $userfields)) {
01479290
DC
292 $userdetails['phone2'] = $user->phone2;
293 }
294 } else {
295 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
296 }
297
298 if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) {
299 if (!$cannotviewdescription) {
ad7612f5
DC
300
301 if (in_array('description', $userfields)) {
302 $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $usercontext->id, 'user', 'profile', null);
303 $userdetails['description'] = $user->description;
304 }
305 if (in_array('descriptionformat', $userfields)) {
306 $userdetails['descriptionformat'] = $user->descriptionformat;
307 }
01479290
DC
308 }
309 }
310
ad7612f5 311 if (in_array('country', $userfields) && (!isset($hiddenfields['country']) or $isadmin) && $user->country) {
01479290
DC
312 $userdetails['country'] = $user->country;
313 }
314
ad7612f5 315 if (in_array('city', $userfields) && (!isset($hiddenfields['city']) or $isadmin) && $user->city) {
01479290
DC
316 $userdetails['city'] = $user->city;
317 }
318
ad7612f5 319 if (in_array('url', $userfields) && $user->url && (!isset($hiddenfields['webpage']) or $isadmin)) {
01479290
DC
320 $url = $user->url;
321 if (strpos($user->url, '://') === false) {
322 $url = 'http://'. $url;
323 }
324 $user->url = clean_param($user->url, PARAM_URL);
325 $userdetails['url'] = $user->url;
326 }
327
ad7612f5 328 if (in_array('icq', $userfields) && $user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) {
01479290
DC
329 $userdetails['icq'] = $user->icq;
330 }
331
ad7612f5 332 if (in_array('skype', $userfields) && $user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) {
01479290
DC
333 $userdetails['skype'] = $user->skype;
334 }
ad7612f5 335 if (in_array('yahoo', $userfields) && $user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) {
01479290
DC
336 $userdetails['yahoo'] = $user->yahoo;
337 }
ad7612f5 338 if (in_array('aim', $userfields) && $user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) {
01479290
DC
339 $userdetails['aim'] = $user->aim;
340 }
ad7612f5 341 if (in_array('msn', $userfields) && $user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) {
01479290
DC
342 $userdetails['msn'] = $user->msn;
343 }
344
ad7612f5 345 if (in_array('firstaccess', $userfields) && (!isset($hiddenfields['firstaccess']) or $isadmin)) {
01479290
DC
346 if ($user->firstaccess) {
347 $userdetails['firstaccess'] = $user->firstaccess;
348 } else {
349 $userdetails['firstaccess'] = 0;
350 }
351 }
ad7612f5 352 if (in_array('lastaccess', $userfields) && (!isset($hiddenfields['lastaccess']) or $isadmin)) {
01479290
DC
353 if ($user->lastaccess) {
354 $userdetails['lastaccess'] = $user->lastaccess;
355 } else {
356 $userdetails['lastaccess'] = 0;
357 }
358 }
359
ad7612f5 360 if (in_array('email', $userfields) && ($currentuser
01479290
DC
361 or $canviewuseremail // this is a capability in course context, it will be false in usercontext
362 or $user->maildisplay == 1
ad7612f5 363 or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER)))) {
01479290
DC
364 $userdetails['email'] = $user->email;;
365 }
366
ad7612f5 367 if (in_array('interests', $userfields) && !empty($CFG->usetags)) {
01479290
DC
368 require_once($CFG->dirroot . '/tag/lib.php');
369 if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) {
370 $userdetails['interests'] = $interests;
371 }
372 }
373
374 //Departement/Institution are not displayed on any profile, however you can get them from editing profile.
375 if ($isadmin or $currentuser) {
ad7612f5 376 if (in_array('institution', $userfields) && $user->institution) {
01479290
DC
377 $userdetails['institution'] = $user->institution;
378 }
ad7612f5 379 if (in_array('department', $userfields) && isset($user->department)) { //isset because it's ok to have department 0
01479290
DC
380 $userdetails['department'] = $user->department;
381 }
382 }
383
ad7612f5 384 if (in_array('roles', $userfields) && !empty($course)) {
01479290
DC
385 // not a big secret
386 $roles = get_user_roles($context, $user->id, false);
387 $userdetails['roles'] = array();
388 foreach ($roles as $role) {
389 $userdetails['roles'][] = array(
390 'roleid' => $role->roleid,
391 'name' => $role->name,
392 'shortname' => $role->shortname,
393 'sortorder' => $role->sortorder
394 );
395 }
396 }
397
398 // If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group
ad7612f5 399 if (in_array('groups', $userfields) && !empty($course) && $canaccessallgroups) {
01479290
DC
400 $usergroups = groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid, 'g.id, g.name,g.description');
401 $userdetails['groups'] = array();
402 foreach ($usergroups as $group) {
403 $group->description = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group', 'description', $group->id);
404 $userdetails['groups'][] = array('id'=>$group->id, 'name'=>$group->name, 'description'=>$group->description);
405 }
406 }
407 //list of courses where the user is enrolled
ad7612f5 408 if (in_array('enrolledcourses', $userfields) && !isset($hiddenfields['mycourses'])) {
01479290
DC
409 $enrolledcourses = array();
410 if ($mycourses = enrol_get_users_courses($user->id, true)) {
411 foreach ($mycourses as $mycourse) {
412 if ($mycourse->category) {
8ebbb06a 413 $coursecontext = get_context_instance(CONTEXT_COURSE, $mycourse->id);
01479290
DC
414 $enrolledcourse = array();
415 $enrolledcourse['id'] = $mycourse->id;
91d284c1 416 $enrolledcourse['fullname'] = format_string($mycourse->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $mycourse->id)));
8ebbb06a 417 $enrolledcourse['shortname'] = format_string($mycourse->shortname, true, array('context' => $coursecontext));
01479290
DC
418 $enrolledcourses[] = $enrolledcourse;
419 }
420 }
421 $userdetails['enrolledcourses'] = $enrolledcourses;
422 }
423 }
424
425 //user preferences
ad7612f5 426 if (in_array('preferences', $userfields) && $currentuser) {
01479290
DC
427 $preferences = array();
428 $userpreferences = get_user_preferences();
429 foreach($userpreferences as $prefname => $prefvalue) {
430 $preferences[] = array('name' => $prefname, 'value' => $prefvalue);
431 }
432 $userdetails['preferences'] = $preferences;
433 }
ad7612f5 434
01479290
DC
435 return $userdetails;
436}
437
b1627a92
DC
438/**
439 * Return a list of page types
440 * @param string $pagetype current page type
441 * @param stdClass $parentcontext Block's parent context
442 * @param stdClass $currentcontext Current context of block
443 */
b38e2e28 444function user_page_type_list($pagetype, $parentcontext, $currentcontext) {
49ae1fdc 445 return array('user-profile'=>get_string('page-user-profile', 'pagetype'));
b1627a92 446}