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