[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/user/profile/ -> lib.php (source)

   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   * Profile field API library file.
  19   *
  20   * @package core_user
  21   * @copyright  2007 onwards Shane Elliot {@link http://pukunui.com}
  22   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  define ('PROFILE_VISIBLE_ALL',     '2'); // Only visible for users with moodle/user:update capability.
  26  define ('PROFILE_VISIBLE_PRIVATE', '1'); // Either we are viewing our own profile or we have moodle/user:update capability.
  27  define ('PROFILE_VISIBLE_NONE',    '0'); // Only visible for moodle/user:update capability.
  28  
  29  /**
  30   * Base class for the customisable profile fields.
  31   *
  32   * @package core_user
  33   * @copyright  2007 onwards Shane Elliot {@link http://pukunui.com}
  34   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class profile_field_base {
  37  
  38      // These 2 variables are really what we're interested in.
  39      // Everything else can be extracted from them.
  40  
  41      /** @var int */
  42      public $fieldid;
  43  
  44      /** @var int */
  45      public $userid;
  46  
  47      /** @var stdClass */
  48      public $field;
  49  
  50      /** @var string */
  51      public $inputname;
  52  
  53      /** @var mixed */
  54      public $data;
  55  
  56      /** @var string */
  57      public $dataformat;
  58  
  59      /**
  60       * Constructor method.
  61       * @param int $fieldid id of the profile from the user_info_field table
  62       * @param int $userid id of the user for whom we are displaying data
  63       */
  64      public function profile_field_base($fieldid=0, $userid=0) {
  65          global $USER;
  66  
  67          $this->set_fieldid($fieldid);
  68          $this->set_userid($userid);
  69          $this->load_data();
  70      }
  71  
  72      /**
  73       * Abstract method: Adds the profile field to the moodle form class
  74       * @abstract The following methods must be overwritten by child classes
  75       * @param moodleform $mform instance of the moodleform class
  76       */
  77      public function edit_field_add($mform) {
  78          print_error('mustbeoveride', 'debug', '', 'edit_field_add');
  79      }
  80  
  81      /**
  82       * Display the data for this field
  83       * @return string
  84       */
  85      public function display_data() {
  86          $options = new stdClass();
  87          $options->para = false;
  88          return format_text($this->data, FORMAT_MOODLE, $options);
  89      }
  90  
  91      /**
  92       * Print out the form field in the edit profile page
  93       * @param moodleform $mform instance of the moodleform class
  94       * @return bool
  95       */
  96      public function edit_field($mform) {
  97          if ($this->field->visible != PROFILE_VISIBLE_NONE
  98            or has_capability('moodle/user:update', context_system::instance())) {
  99  
 100              $this->edit_field_add($mform);
 101              $this->edit_field_set_default($mform);
 102              $this->edit_field_set_required($mform);
 103              return true;
 104          }
 105          return false;
 106      }
 107  
 108      /**
 109       * Tweaks the edit form
 110       * @param moodleform $mform instance of the moodleform class
 111       * @return bool
 112       */
 113      public function edit_after_data($mform) {
 114          if ($this->field->visible != PROFILE_VISIBLE_NONE
 115            or has_capability('moodle/user:update', context_system::instance())) {
 116              $this->edit_field_set_locked($mform);
 117              return true;
 118          }
 119          return false;
 120      }
 121  
 122      /**
 123       * Saves the data coming from form
 124       * @param stdClass $usernew data coming from the form
 125       * @return mixed returns data id if success of db insert/update, false on fail, 0 if not permitted
 126       */
 127      public function edit_save_data($usernew) {
 128          global $DB;
 129  
 130          if (!isset($usernew->{$this->inputname})) {
 131              // Field not present in form, probably locked and invisible - skip it.
 132              return;
 133          }
 134  
 135          $data = new stdClass();
 136  
 137          $usernew->{$this->inputname} = $this->edit_save_data_preprocess($usernew->{$this->inputname}, $data);
 138  
 139          $data->userid  = $usernew->id;
 140          $data->fieldid = $this->field->id;
 141          $data->data    = $usernew->{$this->inputname};
 142  
 143          if ($dataid = $DB->get_field('user_info_data', 'id', array('userid' => $data->userid, 'fieldid' => $data->fieldid))) {
 144              $data->id = $dataid;
 145              $DB->update_record('user_info_data', $data);
 146          } else {
 147              $DB->insert_record('user_info_data', $data);
 148          }
 149      }
 150  
 151      /**
 152       * Validate the form field from profile page
 153       *
 154       * @param stdClass $usernew
 155       * @return  string  contains error message otherwise null
 156       */
 157      public function edit_validate_field($usernew) {
 158          global $DB;
 159  
 160          $errors = array();
 161          // Get input value.
 162          if (isset($usernew->{$this->inputname})) {
 163              if (is_array($usernew->{$this->inputname}) && isset($usernew->{$this->inputname}['text'])) {
 164                  $value = $usernew->{$this->inputname}['text'];
 165              } else {
 166                  $value = $usernew->{$this->inputname};
 167              }
 168          } else {
 169              $value = '';
 170          }
 171  
 172          // Check for uniqueness of data if required.
 173          if ($this->is_unique() && (($value !== '') || $this->is_required())) {
 174              $data = $DB->get_records_sql('
 175                      SELECT id, userid
 176                        FROM {user_info_data}
 177                       WHERE fieldid = ?
 178                         AND ' . $DB->sql_compare_text('data', 255) . ' = ' . $DB->sql_compare_text('?', 255),
 179                      array($this->field->id, $value));
 180              if ($data) {
 181                  $existing = false;
 182                  foreach ($data as $v) {
 183                      if ($v->userid == $usernew->id) {
 184                          $existing = true;
 185                          break;
 186                      }
 187                  }
 188                  if (!$existing) {
 189                      $errors[$this->inputname] = get_string('valuealreadyused');
 190                  }
 191              }
 192          }
 193          return $errors;
 194      }
 195  
 196      /**
 197       * Sets the default data for the field in the form object
 198       * @param  moodleform $mform instance of the moodleform class
 199       */
 200      public function edit_field_set_default($mform) {
 201          if (!empty($default)) {
 202              $mform->setDefault($this->inputname, $this->field->defaultdata);
 203          }
 204      }
 205  
 206      /**
 207       * Sets the required flag for the field in the form object
 208       *
 209       * @param moodleform $mform instance of the moodleform class
 210       */
 211      public function edit_field_set_required($mform) {
 212          global $USER;
 213          if ($this->is_required() && ($this->userid == $USER->id)) {
 214              $mform->addRule($this->inputname, get_string('required'), 'required', null, 'client');
 215          }
 216      }
 217  
 218      /**
 219       * HardFreeze the field if locked.
 220       * @param moodleform $mform instance of the moodleform class
 221       */
 222      public function edit_field_set_locked($mform) {
 223          if (!$mform->elementExists($this->inputname)) {
 224              return;
 225          }
 226          if ($this->is_locked() and !has_capability('moodle/user:update', context_system::instance())) {
 227              $mform->hardFreeze($this->inputname);
 228              $mform->setConstant($this->inputname, $this->data);
 229          }
 230      }
 231  
 232      /**
 233       * Hook for child classess to process the data before it gets saved in database
 234       * @param stdClass $data
 235       * @param stdClass $datarecord The object that will be used to save the record
 236       * @return  mixed
 237       */
 238      public function edit_save_data_preprocess($data, $datarecord) {
 239          return $data;
 240      }
 241  
 242      /**
 243       * Loads a user object with data for this field ready for the edit profile
 244       * form
 245       * @param stdClass $user a user object
 246       */
 247      public function edit_load_user_data($user) {
 248          if ($this->data !== null) {
 249              $user->{$this->inputname} = $this->data;
 250          }
 251      }
 252  
 253      /**
 254       * Check if the field data should be loaded into the user object
 255       * By default it is, but for field types where the data may be potentially
 256       * large, the child class should override this and return false
 257       * @return bool
 258       */
 259      public function is_user_object_data() {
 260          return true;
 261      }
 262  
 263      /**
 264       * Accessor method: set the userid for this instance
 265       * @internal This method should not generally be overwritten by child classes.
 266       * @param integer $userid id from the user table
 267       */
 268      public function set_userid($userid) {
 269          $this->userid = $userid;
 270      }
 271  
 272      /**
 273       * Accessor method: set the fieldid for this instance
 274       * @internal This method should not generally be overwritten by child classes.
 275       * @param integer $fieldid id from the user_info_field table
 276       */
 277      public function set_fieldid($fieldid) {
 278          $this->fieldid = $fieldid;
 279      }
 280  
 281      /**
 282       * Accessor method: Load the field record and user data associated with the
 283       * object's fieldid and userid
 284       * @internal This method should not generally be overwritten by child classes.
 285       */
 286      public function load_data() {
 287          global $DB;
 288  
 289          // Load the field object.
 290          if (($this->fieldid == 0) or (!($field = $DB->get_record('user_info_field', array('id' => $this->fieldid))))) {
 291              $this->field = null;
 292              $this->inputname = '';
 293          } else {
 294              $this->field = $field;
 295              $this->inputname = 'profile_field_'.$field->shortname;
 296          }
 297  
 298          if (!empty($this->field)) {
 299              $params = array('userid' => $this->userid, 'fieldid' => $this->fieldid);
 300              if ($data = $DB->get_record('user_info_data', $params, 'data, dataformat')) {
 301                  $this->data = $data->data;
 302                  $this->dataformat = $data->dataformat;
 303              } else {
 304                  $this->data = $this->field->defaultdata;
 305                  $this->dataformat = FORMAT_HTML;
 306              }
 307          } else {
 308              $this->data = null;
 309          }
 310      }
 311  
 312      /**
 313       * Check if the field data is visible to the current user
 314       * @internal This method should not generally be overwritten by child classes.
 315       * @return bool
 316       */
 317      public function is_visible() {
 318          global $USER;
 319  
 320          switch ($this->field->visible) {
 321              case PROFILE_VISIBLE_ALL:
 322                  return true;
 323              case PROFILE_VISIBLE_PRIVATE:
 324                  if ($this->userid == $USER->id) {
 325                      return true;
 326                  } else {
 327                      return has_capability('moodle/user:viewalldetails',
 328                              context_user::instance($this->userid));
 329                  }
 330              default:
 331                  return has_capability('moodle/user:viewalldetails',
 332                          context_user::instance($this->userid));
 333          }
 334      }
 335  
 336      /**
 337       * Check if the field data is considered empty
 338       * @internal This method should not generally be overwritten by child classes.
 339       * @return boolean
 340       */
 341      public function is_empty() {
 342          return ( ($this->data != '0') and empty($this->data));
 343      }
 344  
 345      /**
 346       * Check if the field is required on the edit profile page
 347       * @internal This method should not generally be overwritten by child classes.
 348       * @return bool
 349       */
 350      public function is_required() {
 351          return (boolean)$this->field->required;
 352      }
 353  
 354      /**
 355       * Check if the field is locked on the edit profile page
 356       * @internal This method should not generally be overwritten by child classes.
 357       * @return bool
 358       */
 359      public function is_locked() {
 360          return (boolean)$this->field->locked;
 361      }
 362  
 363      /**
 364       * Check if the field data should be unique
 365       * @internal This method should not generally be overwritten by child classes.
 366       * @return bool
 367       */
 368      public function is_unique() {
 369          return (boolean)$this->field->forceunique;
 370      }
 371  
 372      /**
 373       * Check if the field should appear on the signup page
 374       * @internal This method should not generally be overwritten by child classes.
 375       * @return bool
 376       */
 377      public function is_signup_field() {
 378          return (boolean)$this->field->signup;
 379      }
 380  }
 381  
 382  /**
 383   * Loads user profile field data into the user object.
 384   * @param stdClass $user
 385   */
 386  function profile_load_data($user) {
 387      global $CFG, $DB;
 388  
 389      if ($fields = $DB->get_records('user_info_field')) {
 390          foreach ($fields as $field) {
 391              require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 392              $newfield = 'profile_field_'.$field->datatype;
 393              $formfield = new $newfield($field->id, $user->id);
 394              $formfield->edit_load_user_data($user);
 395          }
 396      }
 397  }
 398  
 399  /**
 400   * Print out the customisable categories and fields for a users profile
 401   *
 402   * @param moodleform $mform instance of the moodleform class
 403   * @param int $userid id of user whose profile is being edited.
 404   */
 405  function profile_definition($mform, $userid = 0) {
 406      global $CFG, $DB;
 407  
 408      // If user is "admin" fields are displayed regardless.
 409      $update = has_capability('moodle/user:update', context_system::instance());
 410  
 411      if ($categories = $DB->get_records('user_info_category', null, 'sortorder ASC')) {
 412          foreach ($categories as $category) {
 413              if ($fields = $DB->get_records('user_info_field', array('categoryid' => $category->id), 'sortorder ASC')) {
 414  
 415                  // Check first if *any* fields will be displayed.
 416                  $display = false;
 417                  foreach ($fields as $field) {
 418                      if ($field->visible != PROFILE_VISIBLE_NONE) {
 419                          $display = true;
 420                      }
 421                  }
 422  
 423                  // Display the header and the fields.
 424                  if ($display or $update) {
 425                      $mform->addElement('header', 'category_'.$category->id, format_string($category->name));
 426                      foreach ($fields as $field) {
 427                          require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 428                          $newfield = 'profile_field_'.$field->datatype;
 429                          $formfield = new $newfield($field->id, $userid);
 430                          $formfield->edit_field($mform);
 431                      }
 432                  }
 433              }
 434          }
 435      }
 436  }
 437  
 438  /**
 439   * Adds profile fields to user edit forms.
 440   * @param moodleform $mform
 441   * @param int $userid
 442   */
 443  function profile_definition_after_data($mform, $userid) {
 444      global $CFG, $DB;
 445  
 446      $userid = ($userid < 0) ? 0 : (int)$userid;
 447  
 448      if ($fields = $DB->get_records('user_info_field')) {
 449          foreach ($fields as $field) {
 450              require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 451              $newfield = 'profile_field_'.$field->datatype;
 452              $formfield = new $newfield($field->id, $userid);
 453              $formfield->edit_after_data($mform);
 454          }
 455      }
 456  }
 457  
 458  /**
 459   * Validates profile data.
 460   * @param stdClass $usernew
 461   * @param array $files
 462   * @return array
 463   */
 464  function profile_validation($usernew, $files) {
 465      global $CFG, $DB;
 466  
 467      $err = array();
 468      if ($fields = $DB->get_records('user_info_field')) {
 469          foreach ($fields as $field) {
 470              require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 471              $newfield = 'profile_field_'.$field->datatype;
 472              $formfield = new $newfield($field->id, $usernew->id);
 473              $err += $formfield->edit_validate_field($usernew, $files);
 474          }
 475      }
 476      return $err;
 477  }
 478  
 479  /**
 480   * Saves profile data for a user.
 481   * @param stdClass $usernew
 482   */
 483  function profile_save_data($usernew) {
 484      global $CFG, $DB;
 485  
 486      if ($fields = $DB->get_records('user_info_field')) {
 487          foreach ($fields as $field) {
 488              require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 489              $newfield = 'profile_field_'.$field->datatype;
 490              $formfield = new $newfield($field->id, $usernew->id);
 491              $formfield->edit_save_data($usernew);
 492          }
 493      }
 494  }
 495  
 496  /**
 497   * Display profile fields.
 498   * @param int $userid
 499   */
 500  function profile_display_fields($userid) {
 501      global $CFG, $USER, $DB;
 502  
 503      if ($categories = $DB->get_records('user_info_category', null, 'sortorder ASC')) {
 504          foreach ($categories as $category) {
 505              if ($fields = $DB->get_records('user_info_field', array('categoryid' => $category->id), 'sortorder ASC')) {
 506                  foreach ($fields as $field) {
 507                      require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 508                      $newfield = 'profile_field_'.$field->datatype;
 509                      $formfield = new $newfield($field->id, $userid);
 510                      if ($formfield->is_visible() and !$formfield->is_empty()) {
 511                          echo html_writer::tag('dt', format_string($formfield->field->name));
 512                          echo html_writer::tag('dd', $formfield->display_data());
 513                      }
 514                  }
 515              }
 516          }
 517      }
 518  }
 519  
 520  /**
 521   * Adds code snippet to a moodle form object for custom profile fields that
 522   * should appear on the signup page
 523   * @param moodleform $mform moodle form object
 524   */
 525  function profile_signup_fields($mform) {
 526      global $CFG, $DB;
 527  
 528      // Only retrieve required custom fields (with category information)
 529      // results are sort by categories, then by fields.
 530      $sql = "SELECT uf.id as fieldid, ic.id as categoryid, ic.name as categoryname, uf.datatype
 531                  FROM {user_info_field} uf
 532                  JOIN {user_info_category} ic
 533                  ON uf.categoryid = ic.id AND uf.signup = 1 AND uf.visible<>0
 534                  ORDER BY ic.sortorder ASC, uf.sortorder ASC";
 535  
 536      if ( $fields = $DB->get_records_sql($sql)) {
 537          foreach ($fields as $field) {
 538              // Check if we change the categories.
 539              if (!isset($currentcat) || $currentcat != $field->categoryid) {
 540                   $currentcat = $field->categoryid;
 541                   $mform->addElement('header', 'category_'.$field->categoryid, format_string($field->categoryname));
 542              }
 543              require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 544              $newfield = 'profile_field_'.$field->datatype;
 545              $formfield = new $newfield($field->fieldid);
 546              $formfield->edit_field($mform);
 547          }
 548      }
 549  }
 550  
 551  /**
 552   * Returns an object with the custom profile fields set for the given user
 553   * @param integer $userid
 554   * @return stdClass
 555   */
 556  function profile_user_record($userid) {
 557      global $CFG, $DB;
 558  
 559      $usercustomfields = new stdClass();
 560  
 561      if ($fields = $DB->get_records('user_info_field')) {
 562          foreach ($fields as $field) {
 563              require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
 564              $newfield = 'profile_field_'.$field->datatype;
 565              $formfield = new $newfield($field->id, $userid);
 566              if ($formfield->is_user_object_data()) {
 567                  $usercustomfields->{$field->shortname} = $formfield->data;
 568              }
 569          }
 570      }
 571  
 572      return $usercustomfields;
 573  }
 574  
 575  /**
 576   * Obtains a list of all available custom profile fields, indexed by id.
 577   *
 578   * Some profile fields are not included in the user object data (see
 579   * profile_user_record function above). Optionally, you can obtain only those
 580   * fields that are included in the user object.
 581   *
 582   * To be clear, this function returns the available fields, and does not
 583   * return the field values for a particular user.
 584   *
 585   * @param bool $onlyinuserobject True if you only want the ones in $USER
 586   * @return array Array of field objects from database (indexed by id)
 587   * @since Moodle 2.7.1
 588   */
 589  function profile_get_custom_fields($onlyinuserobject = false) {
 590      global $DB, $CFG;
 591  
 592      // Get all the fields.
 593      $fields = $DB->get_records('user_info_field', null, 'id ASC');
 594  
 595      // If only doing the user object ones, unset the rest.
 596      if ($onlyinuserobject) {
 597          foreach ($fields as $id => $field) {
 598              require_once($CFG->dirroot . '/user/profile/field/' .
 599                      $field->datatype . '/field.class.php');
 600              $newfield = 'profile_field_' . $field->datatype;
 601              $formfield = new $newfield();
 602              if (!$formfield->is_user_object_data()) {
 603                  unset($fields[$id]);
 604              }
 605          }
 606      }
 607  
 608      return $fields;
 609  }
 610  
 611  /**
 612   * Load custom profile fields into user object
 613   *
 614   * Please note originally in 1.9 we were using the custom field names directly,
 615   * but it was causing unexpected collisions when adding new fields to user table,
 616   * so instead we now use 'profile_' prefix.
 617   *
 618   * @param stdClass $user user object
 619   */
 620  function profile_load_custom_fields($user) {
 621      $user->profile = (array)profile_user_record($user->id);
 622  }
 623  
 624  


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1