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/>.
16
17/**
18 * Allows you to edit a users profile
19 *
20 * @copyright 1999 Martin Dougiamas  http://dougiamas.com
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 * @package core_user
23 */
24
25require_once('../config.php');
26require_once($CFG->libdir.'/gdlib.php');
27require_once($CFG->libdir.'/adminlib.php');
28require_once($CFG->dirroot.'/user/editadvanced_form.php');
29require_once($CFG->dirroot.'/user/editlib.php');
30require_once($CFG->dirroot.'/user/profile/lib.php');
31require_once($CFG->dirroot.'/user/lib.php');
32require_once($CFG->dirroot.'/webservice/lib.php');
33
34$id     = optional_param('id', $USER->id, PARAM_INT);    // User id; -1 if creating new user.
35$course = optional_param('course', SITEID, PARAM_INT);   // Course id (defaults to Site).
36$returnto = optional_param('returnto', null, PARAM_ALPHA);  // Code determining where to return to after save.
37
38$PAGE->set_url('/user/editadvanced.php', array('course' => $course, 'id' => $id));
39
40$course = $DB->get_record('course', array('id' => $course), '*', MUST_EXIST);
41
42if (!empty($USER->newadminuser)) {
43    // Ignore double clicks, we must finish all operations before cancelling request.
44    ignore_user_abort(true);
45
46    $PAGE->set_course($SITE);
47    $PAGE->set_pagelayout('maintenance');
48} else {
49    if ($course->id == SITEID) {
50        require_login();
51        $PAGE->set_context(context_system::instance());
52    } else {
53        require_login($course);
54    }
55    $PAGE->set_pagelayout('admin');
56}
57
58if ($course->id == SITEID) {
59    $coursecontext = context_system::instance();   // SYSTEM context.
60} else {
61    $coursecontext = context_course::instance($course->id);   // Course context.
62}
63$systemcontext = context_system::instance();
64
65if ($id == -1) {
66    // Creating new user.
67    $user = new stdClass();
68    $user->id = -1;
69    $user->auth = 'manual';
70    $user->confirmed = 1;
71    $user->deleted = 0;
72    $user->timezone = '99';
73    require_capability('moodle/user:create', $systemcontext);
74    admin_externalpage_setup('addnewuser', '', array('id' => -1));
75} else {
76    // Editing existing user.
77    require_capability('moodle/user:update', $systemcontext);
78    $user = $DB->get_record('user', array('id' => $id), '*', MUST_EXIST);
79    $PAGE->set_context(context_user::instance($user->id));
80    $PAGE->navbar->includesettingsbase = true;
81    if ($user->id != $USER->id) {
82        $PAGE->navigation->extend_for_user($user);
83    } else {
84        if ($node = $PAGE->navigation->find('myprofile', navigation_node::TYPE_ROOTNODE)) {
85            $node->force_open();
86        }
87    }
88}
89
90// Remote users cannot be edited.
91if ($user->id != -1 and is_mnet_remote_user($user)) {
92    redirect($CFG->wwwroot . "/user/view.php?id=$id&course={$course->id}");
93}
94
95if ($user->id != $USER->id and is_siteadmin($user) and !is_siteadmin($USER)) {  // Only admins may edit other admins.
96    print_error('useradmineditadmin');
97}
98
99if (isguestuser($user->id)) { // The real guest user can not be edited.
100    print_error('guestnoeditprofileother');
101}
102
103if ($user->deleted) {
104    echo $OUTPUT->header();
105    echo $OUTPUT->heading(get_string('userdeleted'));
106    echo $OUTPUT->footer();
107    die;
108}
109
110// Load user preferences.
111useredit_load_preferences($user);
112
113// Load custom profile fields data.
114profile_load_data($user);
115
116// User interests.
117$user->interests = core_tag_tag::get_item_tags_array('core', 'user', $id);
118
119if ($user->id !== -1) {
120    $usercontext = context_user::instance($user->id);
121    $editoroptions = array(
122        'maxfiles'   => EDITOR_UNLIMITED_FILES,
123        'maxbytes'   => $CFG->maxbytes,
124        'trusttext'  => false,
125        'forcehttps' => false,
126        'context'    => $usercontext
127    );
128
129    $user = file_prepare_standard_editor($user, 'description', $editoroptions, $usercontext, 'user', 'profile', 0);
130} else {
131    $usercontext = null;
132    // This is a new user, we don't want to add files here.
133    $editoroptions = array(
134        'maxfiles' => 0,
135        'maxbytes' => 0,
136        'trusttext' => false,
137        'forcehttps' => false,
138        'context' => $coursecontext
139    );
140}
141
142// Prepare filemanager draft area.
143$draftitemid = 0;
144$filemanagercontext = $editoroptions['context'];
145$filemanageroptions = array('maxbytes'       => $CFG->maxbytes,
146                             'subdirs'        => 0,
147                             'maxfiles'       => 1,
148                             'accepted_types' => 'optimised_image');
149file_prepare_draft_area($draftitemid, $filemanagercontext->id, 'user', 'newicon', 0, $filemanageroptions);
150$user->imagefile = $draftitemid;
151// Create form.
152$userform = new user_editadvanced_form(new moodle_url($PAGE->url, array('returnto' => $returnto)), array(
153    'editoroptions' => $editoroptions,
154    'filemanageroptions' => $filemanageroptions,
155    'user' => $user));
156
157
158// Deciding where to send the user back in most cases.
159if ($returnto === 'profile') {
160    if ($course->id != SITEID) {
161        $returnurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id));
162    } else {
163        $returnurl = new moodle_url('/user/profile.php', array('id' => $user->id));
164    }
165} else {
166    $returnurl = new moodle_url('/user/preferences.php', array('userid' => $user->id));
167}
168
169if ($userform->is_cancelled()) {
170    redirect($returnurl);
171} else if ($usernew = $userform->get_data()) {
172    $usercreated = false;
173
174    if (empty($usernew->auth)) {
175        // User editing self.
176        $authplugin = get_auth_plugin($user->auth);
177        unset($usernew->auth); // Can not change/remove.
178    } else {
179        $authplugin = get_auth_plugin($usernew->auth);
180    }
181
182    $usernew->timemodified = time();
183    $createpassword = false;
184
185    if ($usernew->id == -1) {
186        unset($usernew->id);
187        $createpassword = !empty($usernew->createpassword);
188        unset($usernew->createpassword);
189        $usernew = file_postupdate_standard_editor($usernew, 'description', $editoroptions, null, 'user', 'profile', null);
190        $usernew->mnethostid = $CFG->mnet_localhost_id; // Always local user.
191        $usernew->confirmed  = 1;
192        $usernew->timecreated = time();
193        if ($authplugin->is_internal()) {
194            if ($createpassword or empty($usernew->newpassword)) {
195                $usernew->password = '';
196            } else {
197                $usernew->password = hash_internal_user_password($usernew->newpassword);
198            }
199        } else {
200            $usernew->password = AUTH_PASSWORD_NOT_CACHED;
201        }
202        $usernew->id = user_create_user($usernew, false, false);
203
204        if (!$authplugin->is_internal() and $authplugin->can_change_password() and !empty($usernew->newpassword)) {
205            if (!$authplugin->user_update_password($usernew, $usernew->newpassword)) {
206                // Do not stop here, we need to finish user creation.
207                debugging(get_string('cannotupdatepasswordonextauth', 'error', $usernew->auth), DEBUG_NONE);
208            }
209        }
210        $usercreated = true;
211    } else {
212        $usernew = file_postupdate_standard_editor($usernew, 'description', $editoroptions, $usercontext, 'user', 'profile', 0);
213        // Pass a true old $user here.
214        if (!$authplugin->user_update($user, $usernew)) {
215            // Auth update failed.
216            print_error('cannotupdateuseronexauth', '', '', $user->auth);
217        }
218        user_update_user($usernew, false, false);
219
220        // Set new password if specified.
221        if (!empty($usernew->newpassword)) {
222            if ($authplugin->can_change_password()) {
223                if (!$authplugin->user_update_password($usernew, $usernew->newpassword)) {
224                    print_error('cannotupdatepasswordonextauth', '', '', $usernew->auth);
225                }
226                unset_user_preference('create_password', $usernew); // Prevent cron from generating the password.
227
228                if (!empty($CFG->passwordchangelogout)) {
229                    // We can use SID of other user safely here because they are unique,
230                    // the problem here is we do not want to logout admin here when changing own password.
231                    \core\session\manager::kill_user_sessions($usernew->id, session_id());
232                }
233                if (!empty($usernew->signoutofotherservices)) {
234                    webservice::delete_user_ws_tokens($usernew->id);
235                }
236            }
237        }
238
239        // Force logout if user just suspended.
240        if (isset($usernew->suspended) and $usernew->suspended and !$user->suspended) {
241            \core\session\manager::kill_user_sessions($user->id);
242        }
243    }
244
245    $usercontext = context_user::instance($usernew->id);
246
247    // Update preferences.
248    useredit_update_user_preference($usernew);
249
250    // Update tags.
251    if (empty($USER->newadminuser) && isset($usernew->interests)) {
252        useredit_update_interests($usernew, $usernew->interests);
253    }
254
255    // Update user picture.
256    if (empty($USER->newadminuser)) {
257        core_user::update_picture($usernew, $filemanageroptions);
258    }
259
260    // Update mail bounces.
261    useredit_update_bounces($user, $usernew);
262
263    // Update forum track preference.
264    useredit_update_trackforums($user, $usernew);
265
266    // Save custom profile fields data.
267    profile_save_data($usernew);
268
269    // Reload from db.
270    $usernew = $DB->get_record('user', array('id' => $usernew->id));
271
272    if ($createpassword) {
273        setnew_password_and_mail($usernew);
274        unset_user_preference('create_password', $usernew);
275        set_user_preference('auth_forcepasswordchange', 1, $usernew);
276    }
277
278    // Trigger update/create event, after all fields are stored.
279    if ($usercreated) {
280        \core\event\user_created::create_from_userid($usernew->id)->trigger();
281    } else {
282        \core\event\user_updated::create_from_userid($usernew->id)->trigger();
283    }
284
285    if ($user->id == $USER->id) {
286        // Override old $USER session variable.
287        foreach ((array)$usernew as $variable => $value) {
288            if ($variable === 'description' or $variable === 'password') {
289                // These are not set for security nad perf reasons.
290                continue;
291            }
292            $USER->$variable = $value;
293        }
294        // Preload custom fields.
295        profile_load_custom_fields($USER);
296
297        if (!empty($USER->newadminuser)) {
298            unset($USER->newadminuser);
299            // Apply defaults again - some of them might depend on admin user info, backup, roles, etc.
300            admin_apply_default_settings(null, false);
301            // Admin account is fully configured - set flag here in case the redirect does not work.
302            unset_config('adminsetuppending');
303            // Redirect to admin/ to continue with installation.
304            redirect("$CFG->wwwroot/$CFG->admin/");
305        } else if (empty($SITE->fullname)) {
306            // Somebody double clicked when editing admin user during install.
307            redirect("$CFG->wwwroot/$CFG->admin/");
308        } else {
309            redirect($returnurl);
310        }
311    } else {
312        \core\session\manager::gc(); // Remove stale sessions.
313        redirect("$CFG->wwwroot/$CFG->admin/user.php");
314    }
315    // Never reached..
316}
317
318
319// Display page header.
320if ($user->id == -1 or ($user->id != $USER->id)) {
321    if ($user->id == -1) {
322        echo $OUTPUT->header();
323    } else {
324        $streditmyprofile = get_string('editmyprofile');
325        $userfullname = fullname($user, true);
326        $PAGE->set_heading($userfullname);
327        $PAGE->set_title("$course->shortname: $streditmyprofile - $userfullname");
328        echo $OUTPUT->header();
329        echo $OUTPUT->heading($userfullname);
330    }
331} else if (!empty($USER->newadminuser)) {
332    $strinstallation = get_string('installation', 'install');
333    $strprimaryadminsetup = get_string('primaryadminsetup');
334
335    $PAGE->navbar->add($strprimaryadminsetup);
336    $PAGE->set_title($strinstallation);
337    $PAGE->set_heading($strinstallation);
338    $PAGE->set_cacheable(false);
339
340    echo $OUTPUT->header();
341    echo $OUTPUT->box(get_string('configintroadmin', 'admin'), 'generalbox boxwidthnormal boxaligncenter');
342    echo '<br />';
343} else {
344    $streditmyprofile = get_string('editmyprofile');
345    $strparticipants  = get_string('participants');
346    $strnewuser       = get_string('newuser');
347    $userfullname     = fullname($user, true);
348
349    $PAGE->set_title("$course->shortname: $streditmyprofile");
350    $PAGE->set_heading($userfullname);
351
352    echo $OUTPUT->header();
353    echo $OUTPUT->heading($streditmyprofile);
354}
355
356// Finally display THE form.
357$userform->display();
358
359// And proper footer.
360echo $OUTPUT->footer();
361
362