[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |