[ Index ]

PHP Cross Reference of Unnamed Project

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1