Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
/user/ -> edit.php (source)

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   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  
  25  require_once('../config.php');
  26  require_once($CFG->libdir.'/gdlib.php');
  27  require_once($CFG->dirroot.'/user/edit_form.php');
  28  require_once($CFG->dirroot.'/user/editlib.php');
  29  require_once($CFG->dirroot.'/user/profile/lib.php');
  30  require_once($CFG->dirroot.'/user/lib.php');
  31  
  32  $userid = optional_param('id', $USER->id, PARAM_INT);    // User id.
  33  $course = optional_param('course', SITEID, PARAM_INT);   // Course id (defaults to Site).
  34  $returnto = optional_param('returnto', null, PARAM_ALPHA);  // Code determining where to return to after save.
  35  $cancelemailchange = optional_param('cancelemailchange', 0, PARAM_INT);   // Course id (defaults to Site).
  36  
  37  $PAGE->set_url('/user/edit.php', array('course' => $course, 'id' => $userid));
  38  
  39  if (!$course = $DB->get_record('course', array('id' => $course))) {
  40      throw new \moodle_exception('invalidcourseid');
  41  }
  42  
  43  if ($course->id != SITEID) {
  44      require_login($course);
  45  } else if (!isloggedin()) {
  46      if (empty($SESSION->wantsurl)) {
  47          $SESSION->wantsurl = $CFG->wwwroot.'/user/edit.php';
  48      }
  49      redirect(get_login_url());
  50  } else {
  51      $PAGE->set_context(context_system::instance());
  52  }
  53  
  54  // Guest can not edit.
  55  if (isguestuser()) {
  56      throw new \moodle_exception('guestnoeditprofile');
  57  }
  58  
  59  // The user profile we are editing.
  60  if (!$user = $DB->get_record('user', array('id' => $userid))) {
  61      throw new \moodle_exception('invaliduserid');
  62  }
  63  
  64  // Guest can not be edited.
  65  if (isguestuser($user)) {
  66      throw new \moodle_exception('guestnoeditprofile');
  67  }
  68  
  69  // User interests separated by commas.
  70  $user->interests = core_tag_tag::get_item_tags_array('core', 'user', $user->id);
  71  
  72  // Remote users cannot be edited. Note we have to perform the strict user_not_fully_set_up() check.
  73  // Otherwise the remote user could end up in endless loop between user/view.php and here.
  74  // Required custom fields are not supported in MNet environment anyway.
  75  if (is_mnet_remote_user($user)) {
  76      if (user_not_fully_set_up($user, true)) {
  77          $hostwwwroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $user->mnethostid));
  78          throw new \moodle_exception('usernotfullysetup', 'mnet', '', $hostwwwroot);
  79      }
  80      redirect($CFG->wwwroot . "/user/view.php?course={$course->id}");
  81  }
  82  
  83  // Load the appropriate auth plugin.
  84  $userauth = get_auth_plugin($user->auth);
  85  
  86  if (!$userauth->can_edit_profile()) {
  87      throw new \moodle_exception('noprofileedit', 'auth');
  88  }
  89  
  90  if ($editurl = $userauth->edit_profile_url()) {
  91      // This internal script not used.
  92      redirect($editurl);
  93  }
  94  
  95  if ($course->id == SITEID) {
  96      $coursecontext = context_system::instance();   // SYSTEM context.
  97  } else {
  98      $coursecontext = context_course::instance($course->id);   // Course context.
  99  }
 100  $systemcontext   = context_system::instance();
 101  $personalcontext = context_user::instance($user->id);
 102  
 103  // Check access control.
 104  if ($user->id == $USER->id) {
 105      // Editing own profile - require_login() MUST NOT be used here, it would result in infinite loop!
 106      if (!has_capability('moodle/user:editownprofile', $systemcontext)) {
 107          throw new \moodle_exception('cannotedityourprofile');
 108      }
 109  
 110  } else {
 111      // Teachers, parents, etc.
 112      require_capability('moodle/user:editprofile', $personalcontext);
 113      // No editing of guest user account.
 114      if (isguestuser($user->id)) {
 115          throw new \moodle_exception('guestnoeditprofileother');
 116      }
 117      // No editing of primary admin!
 118      if (is_siteadmin($user) and !is_siteadmin($USER)) {  // Only admins may edit other admins.
 119          throw new \moodle_exception('useradmineditadmin');
 120      }
 121  }
 122  
 123  if ($user->deleted) {
 124      echo $OUTPUT->header();
 125      echo $OUTPUT->heading(get_string('userdeleted'));
 126      echo $OUTPUT->footer();
 127      die;
 128  }
 129  
 130  $PAGE->set_pagelayout('admin');
 131  $PAGE->add_body_class('limitedwidth');
 132  $PAGE->set_context($personalcontext);
 133  if ($USER->id != $user->id) {
 134      $PAGE->navigation->extend_for_user($user);
 135  } else {
 136      if ($node = $PAGE->navigation->find('myprofile', navigation_node::TYPE_ROOTNODE)) {
 137          $node->force_open();
 138      }
 139  }
 140  
 141  // Process email change cancellation.
 142  if ($cancelemailchange) {
 143      cancel_email_update($user->id);
 144  }
 145  
 146  // Load user preferences.
 147  useredit_load_preferences($user);
 148  
 149  // Load custom profile fields data.
 150  profile_load_data($user);
 151  
 152  
 153  // Prepare the editor and create form.
 154  $editoroptions = array(
 155      'maxfiles'   => EDITOR_UNLIMITED_FILES,
 156      'maxbytes'   => $CFG->maxbytes,
 157      'trusttext'  => false,
 158      'forcehttps' => false,
 159      'context'    => $personalcontext
 160  );
 161  
 162  $user = file_prepare_standard_editor($user, 'description', $editoroptions, $personalcontext, 'user', 'profile', 0);
 163  // Prepare filemanager draft area.
 164  $draftitemid = 0;
 165  $filemanagercontext = $editoroptions['context'];
 166  $filemanageroptions = array('maxbytes'       => $CFG->maxbytes,
 167                               'subdirs'        => 0,
 168                               'maxfiles'       => 1,
 169                               'accepted_types' => 'optimised_image');
 170  file_prepare_draft_area($draftitemid, $filemanagercontext->id, 'user', 'newicon', 0, $filemanageroptions);
 171  $user->imagefile = $draftitemid;
 172  // Create form.
 173  $userform = new user_edit_form(new moodle_url($PAGE->url, array('returnto' => $returnto)), array(
 174      'editoroptions' => $editoroptions,
 175      'filemanageroptions' => $filemanageroptions,
 176      'user' => $user));
 177  
 178  $emailchanged = false;
 179  
 180  // Deciding where to send the user back in most cases.
 181  if ($returnto === 'profile') {
 182      if ($course->id != SITEID) {
 183          $returnurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id));
 184      } else {
 185          $returnurl = new moodle_url('/user/profile.php', array('id' => $user->id));
 186      }
 187  } else {
 188      $returnurl = new moodle_url('/user/preferences.php', array('userid' => $user->id));
 189  }
 190  
 191  if ($userform->is_cancelled()) {
 192      redirect($returnurl);
 193  } else if ($usernew = $userform->get_data()) {
 194  
 195      $emailchangedhtml = '';
 196  
 197      if ($CFG->emailchangeconfirmation) {
 198          // Users with 'moodle/user:update' can change their email address immediately.
 199          // Other users require a confirmation email.
 200          if (isset($usernew->email) and $user->email != $usernew->email && !has_capability('moodle/user:update', $systemcontext)) {
 201              $a = new stdClass();
 202              $emailchangedkey = random_string(20);
 203              set_user_preference('newemail', $usernew->email, $user->id);
 204              set_user_preference('newemailkey', $emailchangedkey, $user->id);
 205              set_user_preference('newemailattemptsleft', 3, $user->id);
 206  
 207              $a->newemail = $emailchanged = $usernew->email;
 208              $a->oldemail = $usernew->email = $user->email;
 209  
 210              $emailchangedhtml = $OUTPUT->box(get_string('auth_changingemailaddress', 'auth', $a), 'generalbox', 'notice');
 211              $emailchangedhtml .= $OUTPUT->continue_button($returnurl);
 212          }
 213      }
 214  
 215      $authplugin = get_auth_plugin($user->auth);
 216  
 217      $usernew->timemodified = time();
 218  
 219      // Description editor element may not exist!
 220      if (isset($usernew->description_editor) && isset($usernew->description_editor['format'])) {
 221          $usernew = file_postupdate_standard_editor($usernew, 'description', $editoroptions, $personalcontext, 'user', 'profile', 0);
 222      }
 223  
 224      // Pass a true old $user here.
 225      if (!$authplugin->user_update($user, $usernew)) {
 226          // Auth update failed.
 227          throw new \moodle_exception('cannotupdateprofile');
 228      }
 229  
 230      // Update user with new profile data.
 231      user_update_user($usernew, false, false);
 232  
 233      // Update preferences.
 234      useredit_update_user_preference($usernew);
 235  
 236      // Update interests.
 237      if (isset($usernew->interests)) {
 238          useredit_update_interests($usernew, $usernew->interests);
 239      }
 240  
 241      // Update user picture.
 242      if (empty($CFG->disableuserimages)) {
 243          core_user::update_picture($usernew, $filemanageroptions);
 244      }
 245  
 246      // Update mail bounces.
 247      useredit_update_bounces($user, $usernew);
 248  
 249      // Update forum track preference.
 250      useredit_update_trackforums($user, $usernew);
 251  
 252      // Save custom profile fields data.
 253      profile_save_data($usernew);
 254  
 255      // Trigger event.
 256      \core\event\user_updated::create_from_userid($user->id)->trigger();
 257  
 258      // If email was changed and confirmation is required, send confirmation email now to the new address.
 259      if ($emailchanged !== false && $CFG->emailchangeconfirmation) {
 260          $tempuser = $DB->get_record('user', array('id' => $user->id), '*', MUST_EXIST);
 261          $tempuser->email = $emailchanged;
 262  
 263          $a = new stdClass();
 264          $a->url = $CFG->wwwroot . '/user/emailupdate.php?key=' . $emailchangedkey . '&id=' . $user->id;
 265          $a->site = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
 266          $a->fullname = fullname($tempuser, true);
 267          $a->supportemail = $OUTPUT->supportemail();
 268  
 269          $emailupdatemessage = get_string('emailupdatemessage', 'auth', $a);
 270          $emailupdatetitle = get_string('emailupdatetitle', 'auth', $a);
 271  
 272          // Email confirmation directly rather than using messaging so they will definitely get an email.
 273          $noreplyuser = core_user::get_noreply_user();
 274          if (!$mailresults = email_to_user($tempuser, $noreplyuser, $emailupdatetitle, $emailupdatemessage)) {
 275              die("could not send email!");
 276          }
 277      }
 278  
 279      // Reload from db, we need new full name on this page if we do not redirect.
 280      $user = $DB->get_record('user', array('id' => $user->id), '*', MUST_EXIST);
 281  
 282      if ($USER->id == $user->id) {
 283          // Override old $USER session variable if needed.
 284          foreach ((array)$user as $variable => $value) {
 285              if ($variable === 'description' or $variable === 'password') {
 286                  // These are not set for security nad perf reasons.
 287                  continue;
 288              }
 289              $USER->$variable = $value;
 290          }
 291          // Preload custom fields.
 292          profile_load_custom_fields($USER);
 293      }
 294  
 295      if (is_siteadmin() and empty($SITE->shortname)) {
 296          // Fresh cli install - we need to finish site settings.
 297          redirect(new moodle_url('/admin/index.php'));
 298      }
 299  
 300      if (!$emailchanged || !$CFG->emailchangeconfirmation) {
 301          redirect($returnurl, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
 302      }
 303  }
 304  
 305  
 306  // Display page header.
 307  $streditmyprofile = get_string('editmyprofile');
 308  $strparticipants  = get_string('participants');
 309  $userfullname     = fullname($user, true);
 310  
 311  $PAGE->set_title("$course->shortname: $streditmyprofile");
 312  $PAGE->set_heading($userfullname);
 313  
 314  echo $OUTPUT->header();
 315  echo $OUTPUT->heading($userfullname);
 316  
 317  if ($emailchanged) {
 318      echo $emailchangedhtml;
 319  } else {
 320      // Finally display THE form.
 321      $userform->display();
 322  }
 323  
 324  // And proper footer.
 325  echo $OUTPUT->footer();