Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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

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