diff --git a/admin/settings/users.php b/admin/settings/users.php
index 2f265ee7efd..aa602290f6e 100644
--- a/admin/settings/users.php
+++ b/admin/settings/users.php
@@ -213,7 +213,8 @@ if ($hassiteconfig
new lang_string('showuseridentity', 'admin'),
new lang_string('showuseridentity_desc', 'admin'), ['email' => 1],
function() {
- global $DB;
+ global $CFG;
+ require_once($CFG->dirroot.'/user/profile/lib.php');
// Basic fields available in user table.
$fields = [
@@ -229,10 +230,10 @@ if ($hassiteconfig
];
// Custom profile fields.
- $profilefields = $DB->get_records('user_info_field', ['datatype' => 'text'], 'sortorder ASC');
- foreach ($profilefields as $key => $field) {
- // Only reasonable-length fields can be used as identity fields.
- if ($field->param2 > 255) {
+ $profilefields = profile_get_custom_fields();
+ foreach ($profilefields as $field) {
+ // Only reasonable-length text fields can be used as identity fields.
+ if ($field->param2 > 255 || $field->datatype != 'text') {
continue;
}
$fields['profile_field_' . $field->shortname] = $field->name . ' *';
diff --git a/admin/tool/uploaduser/classes/process.php b/admin/tool/uploaduser/classes/process.php
index cb56918a276..300f5e754b2 100644
--- a/admin/tool/uploaduser/classes/process.php
+++ b/admin/tool/uploaduser/classes/process.php
@@ -60,7 +60,7 @@ class process {
protected $standardfields = [];
/** @var array */
protected $profilefields = [];
- /** @var array */
+ /** @var \profile_field_base[] */
protected $allprofilefields = [];
/** @var string|\uu_progress_tracker|null */
protected $progresstrackerclass = null;
@@ -161,12 +161,13 @@ class process {
* Profile fields
*/
protected function find_profile_fields(): void {
- global $DB;
- $this->allprofilefields = $DB->get_records('user_info_field');
+ global $CFG;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
+ $this->allprofilefields = profile_get_user_fields_with_data(0);
$this->profilefields = [];
if ($proffields = $this->allprofilefields) {
foreach ($proffields as $key => $proffield) {
- $profilefieldname = 'profile_field_'.$proffield->shortname;
+ $profilefieldname = 'profile_field_'.$proffield->get_shortname();
$this->profilefields[] = $profilefieldname;
// Re-index $proffields with key as shortname. This will be
// used while checking if profile data is key and needs to be converted (eg. menu profile field).
@@ -528,8 +529,7 @@ class process {
}
}
}
- $proffields = $this->allprofilefields;
- foreach ($this->profilefields as $field) {
+ foreach ($this->allprofilefields as $field => $profilefield) {
if (isset($user->$field)) {
continue;
}
@@ -539,9 +539,6 @@ class process {
// Form contains key and later code expects value.
// Convert key to value for required profile fields.
- require_once($CFG->dirroot.'/user/profile/field/'.$proffields[$field]->datatype.'/field.class.php');
- $profilefieldclass = 'profile_field_'.$proffields[$field]->datatype;
- $profilefield = new $profilefieldclass($proffields[$field]->id);
if (method_exists($profilefield, 'convert_external_data')) {
$user->$field = $profilefield->edit_save_data_preprocess($user->$field, null);
}
diff --git a/admin/tool/uploaduser/locallib.php b/admin/tool/uploaduser/locallib.php
index 68481c77221..88f020c2041 100644
--- a/admin/tool/uploaduser/locallib.php
+++ b/admin/tool/uploaduser/locallib.php
@@ -415,17 +415,17 @@ function uu_allowed_sysroles_cache() {
* @return stdClass pre-processed custom profile data
*/
function uu_pre_process_custom_profile_data($data) {
- global $CFG, $DB;
+ global $CFG;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
+ $fields = profile_get_user_fields_with_data(0);
+
// find custom profile fields and check if data needs to converted.
foreach ($data as $key => $value) {
if (preg_match('/^profile_field_/', $key)) {
$shortname = str_replace('profile_field_', '', $key);
- if ($fields = $DB->get_records('user_info_field', array('shortname' => $shortname))) {
- foreach ($fields as $field) {
- require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
- $newfield = 'profile_field_'.$field->datatype;
- $formfield = new $newfield($field->id, $data->id);
- if (method_exists($formfield, 'convert_external_data')) {
+ if ($fields) {
+ foreach ($fields as $formfield) {
+ if ($formfield->get_shortname() === $shortname && method_exists($formfield, 'convert_external_data')) {
$data->$key = $formfield->convert_external_data($value);
}
}
@@ -443,7 +443,9 @@ function uu_pre_process_custom_profile_data($data) {
* @return bool true if no error else false
*/
function uu_check_custom_profile_data(&$data) {
- global $CFG, $DB;
+ global $CFG;
+ require_once($CFG->dirroot.'/user/profile/lib.php');
+
$noerror = true;
$testuserid = null;
@@ -452,15 +454,13 @@ function uu_check_custom_profile_data(&$data) {
$testuserid = $result[1];
}
}
+ $profilefields = profile_get_user_fields_with_data(0);
// Find custom profile fields and check if data needs to converted.
foreach ($data as $key => $value) {
if (preg_match('/^profile_field_/', $key)) {
$shortname = str_replace('profile_field_', '', $key);
- if ($fields = $DB->get_records('user_info_field', array('shortname' => $shortname))) {
- foreach ($fields as $field) {
- require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
- $newfield = 'profile_field_'.$field->datatype;
- $formfield = new $newfield($field->id, 0);
+ foreach ($profilefields as $formfield) {
+ if ($formfield->get_shortname() === $shortname) {
if (method_exists($formfield, 'convert_external_data') &&
is_null($formfield->convert_external_data($value))) {
$data['status'][] = get_string('invaliduserfield', 'error', $shortname);
diff --git a/admin/tool/uploaduser/tests/behat/upload_users.feature b/admin/tool/uploaduser/tests/behat/upload_users.feature
index 4cdfbd29b0f..04fb69b7898 100644
--- a/admin/tool/uploaduser/tests/behat/upload_users.feature
+++ b/admin/tool/uploaduser/tests/behat/upload_users.feature
@@ -69,7 +69,8 @@ Feature: Upload users
# Create user profile field.
Given I log in as "admin"
And I navigate to "Users > Accounts > User profile fields" in site administration
- And I set the field "datatype" to "Text area"
+ And I click on "Create a new profile field" "link"
+ And I click on "Text area" "link"
And I set the following fields to these values:
| Short name | superfield |
| Name | Super field |
diff --git a/admin/tool/uploaduser/tests/cli_test.php b/admin/tool/uploaduser/tests/cli_test.php
index a13c047a841..d2af41ce849 100644
--- a/admin/tool/uploaduser/tests/cli_test.php
+++ b/admin/tool/uploaduser/tests/cli_test.php
@@ -126,14 +126,13 @@ class tool_uploaduser_cli_testcase extends advanced_testcase {
* User upload with user profile fields
*/
public function test_upload_with_profile_fields() {
- global $DB, $CFG;
+ global $CFG;
$this->resetAfterTest();
set_config('passwordpolicy', 0);
$this->setAdminUser();
- $categoryid = $DB->insert_record('user_info_category', ['name' => 'Cat 1', 'sortorder' => 1]);
- $this->field1 = $DB->insert_record('user_info_field', [
- 'shortname' => 'superfield', 'name' => 'Super field', 'categoryid' => $categoryid,
+ $this->field1 = $this->getDataGenerator()->create_custom_profile_field([
+ 'shortname' => 'superfield', 'name' => 'Super field',
'datatype' => 'text', 'signup' => 1, 'visible' => 1, 'required' => 1, 'sortorder' => 1]);
$filepath = $CFG->dirroot.'/lib/tests/fixtures/upload_users_profile.csv';
diff --git a/admin/user/user_bulk_download.php b/admin/user/user_bulk_download.php
index ffa3f2335b1..79f3b34c4ca 100644
--- a/admin/user/user_bulk_download.php
+++ b/admin/user/user_bulk_download.php
@@ -50,11 +50,9 @@ if ($dataformat) {
'city' => 'city',
'country' => 'country');
- if ($extrafields = $DB->get_records('user_info_field')) {
- foreach ($extrafields as $n => $field) {
- $fields['profile_field_'.$field->shortname] = 'profile_field_'.$field->shortname;
- require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
- }
+ $extrafields = profile_get_user_fields_with_data(0);
+ foreach ($extrafields as $formfield) {
+ $fields['profile_field_'.$formfield->get_shortname()] = 'profile_field_'.$formfield->get_shortname();
}
$filename = clean_filename(get_string('users'));
@@ -68,11 +66,7 @@ if ($dataformat) {
if (!$user = $DB->get_record('user', array('id' => $userid))) {
return null;
}
- foreach ($extrafields as $field) {
- $newfield = 'profile_field_'.$field->datatype;
- $formfield = new $newfield($field->id, $user->id);
- $formfield->edit_load_user_data($user);
- }
+ profile_load_data($user);
$userprofiledata = array();
foreach ($fields as $field => $unused) {
// Custom user profile textarea fields come in an array
diff --git a/auth/db/tests/db_test.php b/auth/db/tests/db_test.php
index 1de432c3f17..ce163583dc2 100644
--- a/auth/db/tests/db_test.php
+++ b/auth/db/tests/db_test.php
@@ -139,8 +139,7 @@ class auth_db_testcase extends advanced_testcase {
set_config('field_lock_email', 'unlocked', 'auth_db');
// Create a user profile field and add mapping to it.
- $DB->insert_record('user_info_field', ['shortname' => 'pet', 'name' => 'Pet', 'required' => 0,
- 'visible' => 1, 'locked' => 0, 'categoryid' => 1, 'datatype' => 'text']);
+ $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'pet', 'name' => 'Pet', 'datatype' => 'text']);
set_config('field_map_profile_field_pet', 'animal', 'auth_db');
set_config('field_updatelocal_profile_field_pet', 'oncreate', 'auth_db');
diff --git a/auth/email/tests/external_test.php b/auth/email/tests/external_test.php
index ed1900a6dfd..c04a76a8032 100644
--- a/auth/email/tests/external_test.php
+++ b/auth/email/tests/external_test.php
@@ -44,18 +44,17 @@ class auth_email_external_testcase extends externallib_advanced_testcase {
* Set up for every test
*/
public function setUp(): void {
- global $CFG, $DB;
+ global $CFG;
$this->resetAfterTest(true);
$CFG->registerauth = 'email';
- $categoryid = $DB->insert_record('user_info_category', array('name' => 'Cat 1', 'sortorder' => 1));
- $this->field1 = $DB->insert_record('user_info_field', array(
- 'shortname' => 'frogname', 'name' => 'Name of frog', 'categoryid' => $categoryid,
- 'datatype' => 'text', 'signup' => 1, 'visible' => 1, 'required' => 1, 'sortorder' => 1));
- $this->field2 = $DB->insert_record('user_info_field', array(
- 'shortname' => 'sometext', 'name' => 'Some text in textarea', 'categoryid' => $categoryid,
- 'datatype' => 'textarea', 'signup' => 1, 'visible' => 1, 'required' => 1, 'sortorder' => 2));
+ $this->field1 = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'frogname', 'name' => 'Name of frog',
+ 'datatype' => 'text', 'signup' => 1, 'visible' => 1, 'required' => 1, 'sortorder' => 1))->id;
+ $this->field2 = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'sometext', 'name' => 'Some text in textarea',
+ 'datatype' => 'textarea', 'signup' => 1, 'visible' => 1, 'required' => 1, 'sortorder' => 2))->id;
}
public function test_get_signup_settings() {
@@ -109,8 +108,8 @@ class auth_email_external_testcase extends externallib_advanced_testcase {
// Create category with MathJax and a new field with MathJax.
$categoryname = 'Cat $$(a+b)=2$$';
$fieldname = 'Some text $$(a+b)=2$$';
- $categoryid = $DB->insert_record('user_info_category', array('name' => $categoryname, 'sortorder' => 1));
- $field3 = $DB->insert_record('user_info_field', array(
+ $categoryid = $this->getDataGenerator()->create_custom_profile_field_category(['name' => $categoryname])->id;
+ $this->getDataGenerator()->create_custom_profile_field(array(
'shortname' => 'mathjaxname', 'name' => $fieldname, 'categoryid' => $categoryid,
'datatype' => 'textarea', 'signup' => 1, 'visible' => 1, 'required' => 1, 'sortorder' => 2));
diff --git a/availability/condition/profile/tests/behat/availability_profile.feature b/availability/condition/profile/tests/behat/availability_profile.feature
index 816e1fe73a8..690bcd8dc27 100644
--- a/availability/condition/profile/tests/behat/availability_profile.feature
+++ b/availability/condition/profile/tests/behat/availability_profile.feature
@@ -65,7 +65,8 @@ Feature: availability_profile
# Add custom field.
Given I log in as "admin"
And I navigate to "Users > Accounts > User profile fields" in site administration
- And I set the field "datatype" to "Text input"
+ And I click on "Create a new profile field" "link"
+ And I click on "Text input" "link"
And I set the following fields to these values:
| Short name | superfield |
| Name | Super field |
diff --git a/availability/condition/profile/tests/condition_test.php b/availability/condition/profile/tests/condition_test.php
index 7e3074c7906..12d44772e57 100644
--- a/availability/condition/profile/tests/condition_test.php
+++ b/availability/condition/profile/tests/condition_test.php
@@ -50,14 +50,10 @@ class availability_profile_condition_testcase extends advanced_testcase {
$this->resetAfterTest();
- // Add a custom profile field type. The API for doing this is indescribably
- // horrid and tightly intertwined with the form UI, so it's best to add
- // it directly in database.
- $DB->insert_record('user_info_field', array(
- 'shortname' => 'frogtype', 'name' => 'Type of frog', 'categoryid' => 1,
+ // Add a custom profile field type.
+ $this->profilefield = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'frogtype', 'name' => 'Type of frog',
'datatype' => 'text'));
- $this->profilefield = $DB->get_record('user_info_field',
- array('shortname' => 'frogtype'));
// Clear static cache.
\availability_profile\condition::wipe_static_cache();
@@ -333,11 +329,9 @@ class availability_profile_condition_testcase extends advanced_testcase {
$info = new \core_availability\mock_info();
// Add custom textarea type.
- $DB->insert_record('user_info_field', array(
- 'shortname' => 'longtext', 'name' => 'Long text', 'categoryid' => 1,
+ $customfield = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'longtext', 'name' => 'Long text',
'datatype' => 'textarea'));
- $customfield = $DB->get_record('user_info_field',
- array('shortname' => 'longtext'));
// The list of fields should include the text field added in setUp(),
// but should not include the textarea field added just now.
@@ -465,11 +459,9 @@ class availability_profile_condition_testcase extends advanced_testcase {
condition::wipe_static_cache();
// For testing, make another info field with default value.
- $DB->insert_record('user_info_field', array(
- 'shortname' => 'tonguestyle', 'name' => 'Tongue style', 'categoryid' => 1,
+ $otherprofilefield = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'tonguestyle', 'name' => 'Tongue style',
'datatype' => 'text', 'defaultdata' => 'Slimy'));
- $otherprofilefield = $DB->get_record('user_info_field',
- array('shortname' => 'tonguestyle'));
// Make a test course and some users.
$generator = $this->getDataGenerator();
diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php
index 7e51a1f9d85..abbc17983d2 100644
--- a/backup/moodle2/restore_stepslib.php
+++ b/backup/moodle2/restore_stepslib.php
@@ -1691,7 +1691,9 @@ class restore_section_structure_step extends restore_structure_step {
* @param stdClass $data Record data
*/
public function process_availability_field($data) {
- global $DB;
+ global $DB, $CFG;
+ require_once($CFG->dirroot.'/user/profile/lib.php');
+
$data = (object)$data;
// Mark it is as passed by default
$passed = true;
@@ -1704,9 +1706,8 @@ class restore_section_structure_step extends restore_structure_step {
// If one is null but the other isn't something clearly went wrong and we'll skip this condition.
$passed = false;
} else if (!is_null($data->customfield)) {
- $params = array('shortname' => $data->customfield, 'datatype' => $data->customfieldtype);
- $customfieldid = $DB->get_field('user_info_field', 'id', $params);
- $passed = ($customfieldid !== false);
+ $field = profile_get_custom_field_data_by_shortname($data->customfield);
+ $passed = $field && $field->datatype == $data->customfieldtype;
}
if ($passed) {
@@ -4534,7 +4535,9 @@ class restore_module_structure_step extends restore_structure_step {
* @param stdClass $data Record data
*/
protected function process_availability_field($data) {
- global $DB;
+ global $DB, $CFG;
+ require_once($CFG->dirroot.'/user/profile/lib.php');
+
$data = (object)$data;
// Mark it is as passed by default
$passed = true;
@@ -4547,9 +4550,8 @@ class restore_module_structure_step extends restore_structure_step {
// If one is null but the other isn't something clearly went wrong and we'll skip this condition.
$passed = false;
} else if (!empty($data->customfield)) {
- $params = array('shortname' => $data->customfield, 'datatype' => $data->customfieldtype);
- $customfieldid = $DB->get_field('user_info_field', 'id', $params);
- $passed = ($customfieldid !== false);
+ $field = profile_get_custom_field_data_by_shortname($data->customfield);
+ $passed = $field && $field->datatype == $data->customfieldtype;
}
if ($passed) {
diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php
index 3da5cfe1b3c..91be3c13619 100644
--- a/backup/util/dbops/restore_dbops.class.php
+++ b/backup/util/dbops/restore_dbops.class.php
@@ -1151,6 +1151,7 @@ abstract class restore_dbops {
public static function create_included_users($basepath, $restoreid, $userid,
\core\progress\base $progress) {
global $CFG, $DB;
+ require_once($CFG->dirroot.'/user/profile/lib.php');
$progress->start_progress('Creating included users');
$authcache = array(); // Cache to get some bits from authentication plugins
@@ -1257,8 +1258,9 @@ abstract class restore_dbops {
$udata = (object)$udata;
// If the profile field has data and the profile shortname-datatype is defined in server
if ($udata->field_data) {
- if ($field = $DB->get_record('user_info_field', array('shortname'=>$udata->field_name, 'datatype'=>$udata->field_type))) {
- /// Insert the user_custom_profile_field
+ $field = profile_get_custom_field_data_by_shortname($udata->field_name);
+ if ($field && $field->datatype === $udata->field_type) {
+ // Insert the user_custom_profile_field.
$rec = new stdClass();
$rec->userid = $newuserid;
$rec->fieldid = $field->id;
diff --git a/badges/criteria/award_criteria_profile.php b/badges/criteria/award_criteria_profile.php
index 9c02a19c6f4..b014cf5a92b 100644
--- a/badges/criteria/award_criteria_profile.php
+++ b/badges/criteria/award_criteria_profile.php
@@ -44,7 +44,8 @@ class award_criteria_profile extends award_criteria {
*
*/
public function get_options(&$mform) {
- global $DB;
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
$none = true;
$existing = array();
@@ -54,17 +55,11 @@ class award_criteria_profile extends award_criteria {
$dfields = array('firstname', 'lastname', 'email', 'address', 'phone1', 'phone2',
'department', 'institution', 'description', 'picture', 'city', 'country');
- $sql = "SELECT uf.id as fieldid, uf.name as name, ic.id as categoryid, ic.name as categoryname, uf.datatype
- FROM {user_info_field} uf
- JOIN {user_info_category} ic
- ON uf.categoryid = ic.id AND uf.visible <> 0
- ORDER BY ic.sortorder ASC, uf.sortorder ASC";
-
// Get custom fields.
- $cfields = $DB->get_records_sql($sql);
- $cfids = array_map(function($o) {
- return $o->fieldid;
- }, $cfields);
+ $cfields = array_filter(profile_get_custom_fields(), function($field) {
+ return $field->visible <> 0;
+ });
+ $cfids = array_keys($cfields);
if ($this->id !== 0) {
$existing = array_keys($this->params);
@@ -98,13 +93,14 @@ class award_criteria_profile extends award_criteria {
foreach ($cfields as $field) {
if (!isset($currentcat) || $currentcat != $field->categoryid) {
$currentcat = $field->categoryid;
- $mform->addElement('header', 'category_' . $currentcat, format_string($field->categoryname));
+ $categoryname = $DB->get_field('user_info_category', 'name', ['id' => $field->categoryid]);
+ $mform->addElement('header', 'category_' . $currentcat, format_string($categoryname));
}
$checked = false;
- if (in_array($field->fieldid, $existing)) {
+ if (in_array($field->id, $existing)) {
$checked = true;
}
- $this->config_options($mform, array('id' => $field->fieldid, 'checked' => $checked, 'name' => $field->name, 'error' => false));
+ $this->config_options($mform, array('id' => $field->id, 'checked' => $checked, 'name' => $field->name, 'error' => false));
$none = false;
}
}
@@ -133,11 +129,16 @@ class award_criteria_profile extends award_criteria {
* @return string
*/
public function get_details($short = '') {
- global $DB, $OUTPUT;
+ global $OUTPUT, $CFG;
+ require_once($CFG->dirroot.'/user/profile/lib.php');
+
$output = array();
foreach ($this->params as $p) {
if (is_numeric($p['field'])) {
- $str = $DB->get_field('user_info_field', 'name', array('id' => $p['field']));
+ $fields = profile_get_custom_fields();
+ // Get formatted field name if such field exists.
+ $str = isset($fields[$p['field']]->name) ?
+ format_string($fields[$p['field']]->name) : null;
} else {
$str = \core_user\fields::get_display_name($p['field']);
}
diff --git a/badges/tests/badgeslib_test.php b/badges/tests/badgeslib_test.php
index b44d2f59a52..2be62c01178 100644
--- a/badges/tests/badgeslib_test.php
+++ b/badges/tests/badgeslib_test.php
@@ -592,9 +592,9 @@ class badgeslib_test extends advanced_testcase {
require_once($CFG->dirroot.'/user/profile/lib.php');
// Add a custom field of textarea type.
- $customprofileid = $DB->insert_record('user_info_field', array(
- 'shortname' => 'newfield', 'name' => 'Description of new field', 'categoryid' => 1,
- 'datatype' => 'textarea'));
+ $customprofileid = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'newfield', 'name' => 'Description of new field',
+ 'datatype' => 'textarea'))->id;
$this->preventResetByRollback(); // Messaging is not compatible with transactions.
$badge = new badge($this->coursebadge);
diff --git a/calendar/tests/calendartype_test.php b/calendar/tests/calendartype_test.php
index 487010b2869..4e6e5dfc08c 100644
--- a/calendar/tests/calendartype_test.php
+++ b/calendar/tests/calendartype_test.php
@@ -36,7 +36,6 @@ require_once($CFG->libdir . '/form/datetimeselector.php');
// Used to test the user datetime profile field.
require_once($CFG->dirroot . '/user/profile/lib.php');
require_once($CFG->dirroot . '/user/profile/definelib.php');
-require_once($CFG->dirroot . '/user/profile/index_field_form.php');
/**
* Unit tests for the calendar type system.
@@ -273,12 +272,13 @@ class core_calendar_type_testcase extends advanced_testcase {
$formdata['name'] = 'Name';
$formdata['param1'] = $date['inputminyear'];
$formdata['param2'] = $date['inputmaxyear'];
+ $formdata['datatype'] = 'datetime';
// Mock submitting this.
- field_form::mock_submit($formdata);
+ \core_user\form\profile_field_form::mock_submit($formdata);
// Create the user datetime form.
- $form = new field_form(null, 'datetime');
+ $form = new \core_user\form\profile_field_form();
// Get the data from the submission.
$submissiondata = $form->get_data();
diff --git a/grade/lib.php b/grade/lib.php
index 2e8c8d33d1b..0ae85d9b9af 100644
--- a/grade/lib.php
+++ b/grade/lib.php
@@ -3330,14 +3330,10 @@ abstract class grade_helper {
// Sets the list of custom profile fields
$customprofilefields = array_map('trim', explode(',', $CFG->grade_export_customprofilefields));
if ($includecustomfields && !empty($customprofilefields)) {
- list($wherefields, $whereparams) = $DB->get_in_or_equal($customprofilefields);
- $customfields = $DB->get_records_sql("SELECT f.*
- FROM {user_info_field} f
- JOIN {user_info_category} c ON f.categoryid=c.id
- WHERE f.shortname $wherefields
- ORDER BY c.sortorder ASC, f.sortorder ASC", $whereparams);
+ $customfields = profile_get_user_fields_with_data(0);
- foreach ($customfields as $field) {
+ foreach ($customfields as $fieldobj) {
+ $field = (object)$fieldobj->get_field_config_for_external();
// Make sure we can display this custom field
if (!in_array($field->shortname, $customprofilefields)) {
continue;
diff --git a/lang/en/admin.php b/lang/en/admin.php
index ae5cb2f0d63..9f2e48fe760 100644
--- a/lang/en/admin.php
+++ b/lang/en/admin.php
@@ -989,7 +989,7 @@ $string['profilecommonsettings'] = 'Common settings';
$string['profileconfirmcategorydeletion'] = 'There is/are {$a} field/s in this category which will be moved into the category above (or below if in the top category).
Do you still wish to delete this category?';
$string['profileconfirmfielddeletion'] = 'There is/are {$a} user record/s for this field which will be deleted.
Do you still wish to delete this field?';
$string['profilecreatecategory'] = 'Create a new profile category';
-$string['profilecreatefield'] = 'Create a new profile field:';
+$string['profilecreatefield'] = 'Create a new profile field';
$string['profilecreatenewcategory'] = 'Creating a new category';
$string['profilecreatenewfield'] = 'Creating a new \'{$a}\' profile field';
$string['profiledefaultcategory'] = 'Other fields';
diff --git a/lib/authlib.php b/lib/authlib.php
index b81c6ab4b5e..057bd81f02d 100644
--- a/lib/authlib.php
+++ b/lib/authlib.php
@@ -598,14 +598,16 @@ class auth_plugin_base {
* @return array list of custom fields.
*/
public function get_custom_user_profile_fields() {
- global $DB;
+ global $CFG;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
+
// If already retrieved then return.
if (!is_null($this->customfields)) {
return $this->customfields;
}
$this->customfields = array();
- if ($proffields = $DB->get_records('user_info_field')) {
+ if ($proffields = profile_get_custom_fields()) {
foreach ($proffields as $proffield) {
$this->customfields[] = 'profile_field_'.$proffield->shortname;
}
@@ -1159,7 +1161,8 @@ function signup_is_enabled() {
* @since Moodle 3.3
*/
function display_auth_lock_options($settings, $auth, $userfields, $helptext, $mapremotefields, $updateremotefields, $customfields = array()) {
- global $DB;
+ global $CFG;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
// Introductory explanation and help text.
if ($mapremotefields) {
@@ -1180,7 +1183,8 @@ function display_auth_lock_options($settings, $auth, $userfields, $helptext, $ma
// Generate the list of profile fields to allow updates / lock.
if (!empty($customfields)) {
$userfields = array_merge($userfields, $customfields);
- $customfieldname = $DB->get_records('user_info_field', null, '', 'shortname, name');
+ $allcustomfields = profile_get_custom_fields();
+ $customfieldname = array_combine(array_column($allcustomfields, 'shortname'), $allcustomfields);
}
foreach ($userfields as $field) {
diff --git a/lib/testing/generator/data_generator.php b/lib/testing/generator/data_generator.php
index 29c81681464..9eb9914009c 100644
--- a/lib/testing/generator/data_generator.php
+++ b/lib/testing/generator/data_generator.php
@@ -1289,7 +1289,7 @@ EOD;
'defaultdata' => 0
]
];
- foreach ($typedefaults[$data['datatype']] as $field => $value) {
+ foreach ($typedefaults[$data['datatype']] ?? [] as $field => $value) {
$defaults[$field] = $value;
}
diff --git a/lib/tests/behat/showuseridentity.feature b/lib/tests/behat/showuseridentity.feature
index a475ec67f19..53446924a3d 100644
--- a/lib/tests/behat/showuseridentity.feature
+++ b/lib/tests/behat/showuseridentity.feature
@@ -22,7 +22,7 @@ Feature: Select user identity fields
| user1 | C1 | manager |
| user2 | C1 | manager |
- Scenario: The admin settings screen should show text custom fields (and let you choose them)
+ Scenario: The admin settings screen should show text custom fields of certain length (and let you choose them)
When I log in as "admin"
And I navigate to "Users > Permissions > User policies" in site administration
Then I should see "Speciality" in the "#admin-showuseridentity" "css_element"
diff --git a/lib/tests/event_profile_field_test.php b/lib/tests/event_profile_field_test.php
index 82154e7dcae..d2b5b42b6c8 100644
--- a/lib/tests/event_profile_field_test.php
+++ b/lib/tests/event_profile_field_test.php
@@ -50,13 +50,8 @@ class core_event_profile_field_testcase extends advanced_testcase {
* Test that triggering the user_info_category_created event works as expected.
*/
public function test_user_info_category_created_event() {
- global $DB;
-
// Create a new profile category.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Trigger the event.
$sink = $this->redirectEvents();
@@ -81,15 +76,8 @@ class core_event_profile_field_testcase extends advanced_testcase {
global $DB;
// Create new profile categories.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
-
- $cat2 = new stdClass();
- $cat2->name = 'Example category 2';
- $cat2->sortorder = $DB->count_records('user_info_category') + 1;
- $cat2->id = $DB->insert_record('user_info_category', $cat2);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
+ $cat2 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category 2']);
// Trigger the events.
$sink = $this->redirectEvents();
@@ -116,18 +104,9 @@ class core_event_profile_field_testcase extends advanced_testcase {
* Test that deleting a user info category triggers a delete event.
*/
public function test_user_info_category_deleted_event() {
- global $DB;
-
// Create new profile categories.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
-
- $cat2 = new stdClass();
- $cat2->name = 'Example category 2';
- $cat2->sortorder = $DB->count_records('user_info_category') + 1;
- $cat2->id = $DB->insert_record('user_info_category', $cat2);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
+ $cat2 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category 2']);
// Trigger the event.
$sink = $this->redirectEvents();
@@ -152,10 +131,7 @@ class core_event_profile_field_testcase extends advanced_testcase {
global $DB;
// Create a new profile category.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
$data = new stdClass();
@@ -196,27 +172,17 @@ class core_event_profile_field_testcase extends advanced_testcase {
* Test that updating a user info field triggers an update event.
*/
public function test_user_info_field_updated_event() {
- global $DB;
-
// Create a new profile category.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
- $data = new stdClass();
- $data->datatype = 'text';
- $data->shortname = 'example';
- $data->name = 'Example field';
- $data->description = 'Hello this is an example.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $cat1->id;
- $data->id = $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => 'text',
+ 'shortname' => 'example',
+ 'name' => 'Example field',
+ 'description' => 'Hello this is an example.',
+ 'categoryid' => $cat1->id,
+ ]);
// Trigger the event.
$sink = $this->redirectEvents();
@@ -241,36 +207,25 @@ class core_event_profile_field_testcase extends advanced_testcase {
* Test that moving a field triggers update events.
*/
public function test_user_info_field_updated_event_move_field() {
- global $DB;
-
// Create a new profile category.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
- $field1 = new stdClass();
- $field1->datatype = 'text';
- $field1->shortname = 'example';
- $field1->name = 'Example field';
- $field1->description = 'Hello this is an example.';
- $field1->required = false;
- $field1->locked = false;
- $field1->forceunique = false;
- $field1->signup = false;
- $field1->visible = '0';
- $field1->categoryid = $cat1->id;
- $field1->sortorder = $DB->count_records('user_info_field') + 1;
- $field1->id = $DB->insert_record('user_info_field', $field1);
+ $field1 = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => 'text',
+ 'shortname' => 'example',
+ 'name' => 'Example field',
+ 'description' => 'Hello this is an example.',
+ 'categoryid' => $cat1->id,
+ ]);
// Create another that we will be moving.
- $field2 = clone $field1;
- $field2->datatype = 'text';
- $field2->shortname = 'example2';
- $field2->name = 'Example field 2';
- $field2->sortorder = $DB->count_records('user_info_field') + 1;
- $field2->id = $DB->insert_record('user_info_field', $field2);
+ $field2 = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => 'text',
+ 'shortname' => 'example2',
+ 'name' => 'Example field 2',
+ 'categoryid' => $cat1->id,
+ ]);
// Trigger the events.
$sink = $this->redirectEvents();
@@ -302,32 +257,18 @@ class core_event_profile_field_testcase extends advanced_testcase {
* another category triggers an update event.
*/
public function test_user_info_field_updated_event_delete_category() {
- global $DB;
-
- // Create a new profile category.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
-
- $cat2 = new stdClass();
- $cat2->name = 'Example category';
- $cat2->sortorder = $DB->count_records('user_info_category') + 1;
- $cat2->id = $DB->insert_record('user_info_category', $cat2);
+ // Create profile categories.
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
+ $cat2 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
- $field = new stdClass();
- $field->datatype = 'text';
- $field->shortname = 'example';
- $field->name = 'Example field';
- $field->description = 'Hello this is an example.';
- $field->required = false;
- $field->locked = false;
- $field->forceunique = false;
- $field->signup = false;
- $field->visible = '0';
- $field->categoryid = $cat1->id;
- $field->id = $DB->insert_record('user_info_field', $field);
+ $field = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => 'text',
+ 'shortname' => 'example',
+ 'name' => 'Example field',
+ 'description' => 'Hello this is an example.',
+ 'categoryid' => $cat1->id,
+ ]);
// Trigger the event.
$sink = $this->redirectEvents();
@@ -351,27 +292,17 @@ class core_event_profile_field_testcase extends advanced_testcase {
* Test that deleting a user info field triggers a delete event.
*/
public function test_user_info_field_deleted_event() {
- global $DB;
-
// Create a new profile category.
- $cat1 = new stdClass();
- $cat1->name = 'Example category';
- $cat1->sortorder = $DB->count_records('user_info_category') + 1;
- $cat1->id = $DB->insert_record('user_info_category', $cat1);
+ $cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
- $data = new stdClass();
- $data->datatype = 'text';
- $data->shortname = 'delete';
- $data->name = 'Example field for delete';
- $data->description = 'Hello this is an example.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $cat1->id;
- $data->id = $DB->insert_record('user_info_field', $data, true);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => 'text',
+ 'shortname' => 'delete',
+ 'name' => 'Example field for delete',
+ 'description' => 'Hello this is an example.',
+ 'categoryid' => $cat1->id,
+ ]);
// Trigger the event.
$sink = $this->redirectEvents();
diff --git a/user/amd/build/edit_profile_fields.min.js b/user/amd/build/edit_profile_fields.min.js
new file mode 100644
index 00000000000..50d9ec4d57b
--- /dev/null
+++ b/user/amd/build/edit_profile_fields.min.js
@@ -0,0 +1,2 @@
+define ("core_user/edit_profile_fields",["exports","core_form/modalform","core/str"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var d={actions:{editCategory:"[data-action=\"editcategory\"]",editField:"[data-action=\"editfield\"]",createField:"[data-action=\"createfield\"]"}};a.init=function init(){document.addEventListener("click",function(a){var e=a.target.closest(d.actions.editCategory);if(e){a.preventDefault();var f=e.getAttribute("data-id")?(0,c.get_string)("profileeditcategory","admin",e.getAttribute("data-name")):(0,c.get_string)("profilecreatenewcategory","admin"),g=new b.default({formClass:"core_user\\form\\profile_category_form",args:{id:e.getAttribute("data-id")},modalConfig:{title:f},returnFocus:e});g.addEventListener(g.events.FORM_SUBMITTED,function(){return window.location.reload()});g.show()}e=a.target.closest(d.actions.editField);if(e){a.preventDefault();var h=new b.default({formClass:"core_user\\form\\profile_field_form",args:{id:e.getAttribute("data-id")},modalConfig:{title:(0,c.get_string)("profileeditfield","admin",e.getAttribute("data-name"))},returnFocus:e});h.addEventListener(h.events.FORM_SUBMITTED,function(){return window.location.reload()});h.show()}e=a.target.closest(d.actions.createField);if(e){a.preventDefault();var i=new b.default({formClass:"core_user\\form\\profile_field_form",args:{datatype:e.getAttribute("data-datatype"),categoryid:e.getAttribute("data-categoryid")},modalConfig:{title:(0,c.get_string)("profilecreatenewfield","admin",e.getAttribute("data-datatypename"))},returnFocus:e});i.addEventListener(i.events.FORM_SUBMITTED,function(){return window.location.reload()});i.show()}})}});
+//# sourceMappingURL=edit_profile_fields.min.js.map
diff --git a/user/amd/build/edit_profile_fields.min.js.map b/user/amd/build/edit_profile_fields.min.js.map
new file mode 100644
index 00000000000..1140d959d1a
--- /dev/null
+++ b/user/amd/build/edit_profile_fields.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/edit_profile_fields.js"],"names":["Selectors","actions","editCategory","editField","createField","init","document","addEventListener","e","element","target","closest","preventDefault","title","getAttribute","form","ModalForm","formClass","args","id","modalConfig","returnFocus","events","FORM_SUBMITTED","window","location","reload","show","datatype","categoryid"],"mappings":"iLAeA,uD,GAYMA,CAAAA,CAAS,CAAG,CACdC,OAAO,CAAE,CACLC,YAAY,CAAE,gCADT,CAELC,SAAS,CAAE,6BAFN,CAGLC,WAAW,CAAE,+BAHR,CADK,C,QAQE,QAAPC,CAAAA,IAAO,EAAM,CACtBC,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAASC,CAAT,CAAY,CAC3C,GAAIC,CAAAA,CAAO,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBX,CAAS,CAACC,OAAV,CAAkBC,YAAnC,CAAd,CACA,GAAIO,CAAJ,CAAa,CACTD,CAAC,CAACI,cAAF,GADS,GAEHC,CAAAA,CAAK,CAAGJ,CAAO,CAACK,YAAR,CAAqB,SAArB,EACV,iBAAU,qBAAV,CAAiC,OAAjC,CAA0CL,CAAO,CAACK,YAAR,CAAqB,WAArB,CAA1C,CADU,CAEV,iBAAU,0BAAV,CAAsC,OAAtC,CAJK,CAKHC,CAAI,CAAG,GAAIC,UAAJ,CAAc,CACvBC,SAAS,CAAE,wCADY,CAEvBC,IAAI,CAAE,CAACC,EAAE,CAAEV,CAAO,CAACK,YAAR,CAAqB,SAArB,CAAL,CAFiB,CAGvBM,WAAW,CAAE,CAACP,KAAK,CAALA,CAAD,CAHU,CAIvBQ,WAAW,CAAEZ,CAJU,CAAd,CALJ,CAWTM,CAAI,CAACR,gBAAL,CAAsBQ,CAAI,CAACO,MAAL,CAAYC,cAAlC,CAAkD,iBAAMC,CAAAA,MAAM,CAACC,QAAP,CAAgBC,MAAhB,EAAN,CAAlD,EACAX,CAAI,CAACY,IAAL,EACH,CAEDlB,CAAO,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBX,CAAS,CAACC,OAAV,CAAkBE,SAAnC,CAAV,CACA,GAAIM,CAAJ,CAAa,CACTD,CAAC,CAACI,cAAF,GACA,GAAMG,CAAAA,CAAI,CAAG,GAAIC,UAAJ,CAAc,CACvBC,SAAS,CAAE,qCADY,CAEvBC,IAAI,CAAE,CAACC,EAAE,CAAEV,CAAO,CAACK,YAAR,CAAqB,SAArB,CAAL,CAFiB,CAGvBM,WAAW,CAAE,CAACP,KAAK,CAAE,iBAAU,kBAAV,CAA8B,OAA9B,CAAuCJ,CAAO,CAACK,YAAR,CAAqB,WAArB,CAAvC,CAAR,CAHU,CAIvBO,WAAW,CAAEZ,CAJU,CAAd,CAAb,CAMAM,CAAI,CAACR,gBAAL,CAAsBQ,CAAI,CAACO,MAAL,CAAYC,cAAlC,CAAkD,iBAAMC,CAAAA,MAAM,CAACC,QAAP,CAAgBC,MAAhB,EAAN,CAAlD,EACAX,CAAI,CAACY,IAAL,EACH,CAEDlB,CAAO,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBX,CAAS,CAACC,OAAV,CAAkBG,WAAnC,CAAV,CACA,GAAIK,CAAJ,CAAa,CACTD,CAAC,CAACI,cAAF,GACA,GAAMG,CAAAA,CAAI,CAAG,GAAIC,UAAJ,CAAc,CACvBC,SAAS,CAAE,qCADY,CAEvBC,IAAI,CAAE,CAACU,QAAQ,CAAEnB,CAAO,CAACK,YAAR,CAAqB,eAArB,CAAX,CAAkDe,UAAU,CAAEpB,CAAO,CAACK,YAAR,CAAqB,iBAArB,CAA9D,CAFiB,CAGvBM,WAAW,CAAE,CAACP,KAAK,CAAE,iBAAU,uBAAV,CAAmC,OAAnC,CAA4CJ,CAAO,CAACK,YAAR,CAAqB,mBAArB,CAA5C,CAAR,CAHU,CAIvBO,WAAW,CAAEZ,CAJU,CAAd,CAAb,CAMAM,CAAI,CAACR,gBAAL,CAAsBQ,CAAI,CAACO,MAAL,CAAYC,cAAlC,CAAkD,iBAAMC,CAAAA,MAAM,CAACC,QAAP,CAAgBC,MAAhB,EAAN,CAAlD,EACAX,CAAI,CAACY,IAAL,EACH,CACJ,CA1CD,CA2CH,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\n\n/**\n * User profile fields editor\n *\n * @module core_user/edit_profile_fields\n * @package core_user\n * @copyright 2021 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst Selectors = {\n actions: {\n editCategory: '[data-action=\"editcategory\"]',\n editField: '[data-action=\"editfield\"]',\n createField: '[data-action=\"createfield\"]',\n },\n};\n\nexport const init = () => {\n document.addEventListener('click', function(e) {\n let element = e.target.closest(Selectors.actions.editCategory);\n if (element) {\n e.preventDefault();\n const title = element.getAttribute('data-id') ?\n getString('profileeditcategory', 'admin', element.getAttribute('data-name')) :\n getString('profilecreatenewcategory', 'admin');\n const form = new ModalForm({\n formClass: 'core_user\\\\form\\\\profile_category_form',\n args: {id: element.getAttribute('data-id')},\n modalConfig: {title},\n returnFocus: element,\n });\n form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());\n form.show();\n }\n\n element = e.target.closest(Selectors.actions.editField);\n if (element) {\n e.preventDefault();\n const form = new ModalForm({\n formClass: 'core_user\\\\form\\\\profile_field_form',\n args: {id: element.getAttribute('data-id')},\n modalConfig: {title: getString('profileeditfield', 'admin', element.getAttribute('data-name'))},\n returnFocus: element,\n });\n form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());\n form.show();\n }\n\n element = e.target.closest(Selectors.actions.createField);\n if (element) {\n e.preventDefault();\n const form = new ModalForm({\n formClass: 'core_user\\\\form\\\\profile_field_form',\n args: {datatype: element.getAttribute('data-datatype'), categoryid: element.getAttribute('data-categoryid')},\n modalConfig: {title: getString('profilecreatenewfield', 'admin', element.getAttribute('data-datatypename'))},\n returnFocus: element,\n });\n form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());\n form.show();\n }\n });\n};"],"file":"edit_profile_fields.min.js"}
\ No newline at end of file
diff --git a/user/amd/src/edit_profile_fields.js b/user/amd/src/edit_profile_fields.js
new file mode 100644
index 00000000000..04916db4825
--- /dev/null
+++ b/user/amd/src/edit_profile_fields.js
@@ -0,0 +1,80 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see .
+
+import ModalForm from 'core_form/modalform';
+import {get_string as getString} from 'core/str';
+
+/**
+ * User profile fields editor
+ *
+ * @module core_user/edit_profile_fields
+ * @package core_user
+ * @copyright 2021 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+const Selectors = {
+ actions: {
+ editCategory: '[data-action="editcategory"]',
+ editField: '[data-action="editfield"]',
+ createField: '[data-action="createfield"]',
+ },
+};
+
+export const init = () => {
+ document.addEventListener('click', function(e) {
+ let element = e.target.closest(Selectors.actions.editCategory);
+ if (element) {
+ e.preventDefault();
+ const title = element.getAttribute('data-id') ?
+ getString('profileeditcategory', 'admin', element.getAttribute('data-name')) :
+ getString('profilecreatenewcategory', 'admin');
+ const form = new ModalForm({
+ formClass: 'core_user\\form\\profile_category_form',
+ args: {id: element.getAttribute('data-id')},
+ modalConfig: {title},
+ returnFocus: element,
+ });
+ form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());
+ form.show();
+ }
+
+ element = e.target.closest(Selectors.actions.editField);
+ if (element) {
+ e.preventDefault();
+ const form = new ModalForm({
+ formClass: 'core_user\\form\\profile_field_form',
+ args: {id: element.getAttribute('data-id')},
+ modalConfig: {title: getString('profileeditfield', 'admin', element.getAttribute('data-name'))},
+ returnFocus: element,
+ });
+ form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());
+ form.show();
+ }
+
+ element = e.target.closest(Selectors.actions.createField);
+ if (element) {
+ e.preventDefault();
+ const form = new ModalForm({
+ formClass: 'core_user\\form\\profile_field_form',
+ args: {datatype: element.getAttribute('data-datatype'), categoryid: element.getAttribute('data-categoryid')},
+ modalConfig: {title: getString('profilecreatenewfield', 'admin', element.getAttribute('data-datatypename'))},
+ returnFocus: element,
+ });
+ form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());
+ form.show();
+ }
+ });
+};
\ No newline at end of file
diff --git a/user/classes/fields.php b/user/classes/fields.php
index d5621957d02..4e5dbfe9e80 100644
--- a/user/classes/fields.php
+++ b/user/classes/fields.php
@@ -371,10 +371,11 @@ class fields {
// or if the user doesn't have access to see them).
foreach ($extra as $key => $field) {
if (preg_match(self::PROFILE_FIELD_REGEX, $field, $matches)) {
+ $allowed = false;
if ($allowcustom) {
require_once($CFG->dirroot . '/user/profile/lib.php');
$fieldinfo = profile_get_custom_field_data_by_shortname($matches[1]);
- switch ($fieldinfo['visible']) {
+ switch ($fieldinfo->visible ?? -1) {
case PROFILE_VISIBLE_NONE:
case PROFILE_VISIBLE_PRIVATE:
$allowed = !$context || has_capability('moodle/user:viewalldetails', $context);
@@ -383,8 +384,6 @@ class fields {
$allowed = true;
break;
}
- } else {
- $allowed = false;
}
if (!$allowed) {
unset($extra[$key]);
@@ -586,7 +585,7 @@ class fields {
require_once($CFG->dirroot . '/user/profile/lib.php');
$fieldinfo = profile_get_custom_field_data_by_shortname($matches[1]);
// Use format_string so it can be translated with multilang filter if necessary.
- return format_string($fieldinfo['name']);
+ return $fieldinfo ? format_string($fieldinfo->name) : $field;
}
// Some fields have language strings which are not the same as field name.
diff --git a/user/classes/form/profile_category_form.php b/user/classes/form/profile_category_form.php
new file mode 100644
index 00000000000..e69695fa03f
--- /dev/null
+++ b/user/classes/form/profile_category_form.php
@@ -0,0 +1,125 @@
+.
+
+namespace core_user\form;
+
+use context;
+use core_form\dynamic_form;
+use moodle_url;
+
+/**
+ * Modal form to edit profile category
+ *
+ * @package core_user
+ * @copyright 2021 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class profile_category_form extends dynamic_form {
+
+ /**
+ * Form definition
+ */
+ protected function definition() {
+ $mform = $this->_form;
+
+ $strrequired = get_string('required');
+
+ // Add some extra hidden fields.
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+ $mform->addElement('hidden', 'action', 'editcategory');
+ $mform->setType('action', PARAM_ALPHANUMEXT);
+
+ $mform->addElement('text', 'name', get_string('profilecategoryname', 'admin'), 'maxlength="255" size="30"');
+ $mform->setType('name', PARAM_TEXT);
+ $mform->addRule('name', $strrequired, 'required', null, 'client');
+ }
+
+ /**
+ * Perform some moodle validation.
+ *
+ * @param array $data
+ * @param array $files
+ * @return array
+ */
+ public function validation($data, $files) {
+ global $DB;
+ $errors = parent::validation($data, $files);
+
+ $duplicate = $DB->get_field('user_info_category', 'id', ['name' => $data['name']]);
+
+ // Check the name is unique.
+ if (!empty($data['id'])) { // We are editing an existing record.
+ $olddata = $DB->get_record('user_info_category', ['id' => $data['id']]);
+ // Name has changed, new name in use, new name in use by another record.
+ $dupfound = (($olddata->name !== $data['name']) && $duplicate && ($data['id'] != $duplicate));
+ } else { // New profile category.
+ $dupfound = $duplicate;
+ }
+
+ if ($dupfound ) {
+ $errors['name'] = get_string('profilecategorynamenotunique', 'admin');
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Returns context where this form is used
+ *
+ * @return context
+ */
+ protected function get_context_for_dynamic_submission(): context {
+ return \context_system::instance();
+ }
+
+ /**
+ * Checks if current user has access to this form, otherwise throws exception
+ */
+ protected function check_access_for_dynamic_submission(): void {
+ require_capability('moodle/site:config', $this->get_context_for_dynamic_submission());
+ }
+
+ /**
+ * Process the form submission, used if form was submitted via AJAX
+ */
+ public function process_dynamic_submission() {
+ global $CFG;
+ require_once($CFG->dirroot.'/user/profile/definelib.php');
+ profile_save_category($this->get_data());
+ }
+
+ /**
+ * Load in existing data as form defaults
+ */
+ public function set_data_for_dynamic_submission(): void {
+ global $DB;
+ if ($id = $this->optional_param('id', 0, PARAM_INT)) {
+ $this->set_data($DB->get_record('user_info_category', ['id' => $id], '*', MUST_EXIST));
+ }
+ }
+
+ /**
+ * Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX
+ *
+ * @return moodle_url
+ */
+ protected function get_page_url_for_dynamic_submission(): moodle_url {
+ $id = $this->optional_param('id', 0, PARAM_INT);
+ return new moodle_url('/user/profile/index.php',
+ ['action' => 'editcategory', 'id' => $id]);
+ }
+}
\ No newline at end of file
diff --git a/user/classes/form/profile_field_form.php b/user/classes/form/profile_field_form.php
new file mode 100644
index 00000000000..4dd6017bf58
--- /dev/null
+++ b/user/classes/form/profile_field_form.php
@@ -0,0 +1,183 @@
+.
+
+namespace core_user\form;
+
+use context;
+use core_form\dynamic_form;
+use moodle_url;
+use profile_define_base;
+
+/**
+ * Class field_form used for profile fields.
+ *
+ * @package core_user
+ * @copyright 2007 onwards Shane Elliot {@link http://pukunui.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class profile_field_form extends dynamic_form {
+
+ /** @var profile_define_base $field */
+ public $field;
+ /** @var \stdClass */
+ protected $fieldrecord;
+
+ /**
+ * Define the form
+ */
+ public function definition () {
+ global $CFG;
+ require_once($CFG->dirroot.'/user/profile/definelib.php');
+
+ $mform = $this->_form;
+
+ // Everything else is dependant on the data type.
+ $datatype = $this->get_field_record()->datatype;
+ require_once($CFG->dirroot.'/user/profile/field/'.$datatype.'/define.class.php');
+ $newfield = 'profile_define_'.$datatype;
+ $this->field = new $newfield();
+
+ // Add some extra hidden fields.
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+ $mform->addElement('hidden', 'action', 'editfield');
+ $mform->setType('action', PARAM_ALPHANUMEXT);
+ $mform->addElement('hidden', 'datatype', $datatype);
+ $mform->setType('datatype', PARAM_ALPHA);
+
+ $this->field->define_form($mform);
+ }
+
+
+ /**
+ * Alter definition based on existing or submitted data
+ */
+ public function definition_after_data () {
+ $mform = $this->_form;
+ $this->field->define_after_data($mform);
+ }
+
+
+ /**
+ * Perform some moodle validation.
+ * @param array $data
+ * @param array $files
+ * @return array
+ */
+ public function validation($data, $files) {
+ return $this->field->define_validate($data, $files);
+ }
+
+ /**
+ * Returns the defined editors for the field.
+ * @return array
+ */
+ public function editors(): array {
+ $editors = $this->field->define_editors();
+ return is_array($editors) ? $editors : [];
+ }
+
+ /**
+ * Returns context where this form is used
+ *
+ * @return context
+ */
+ protected function get_context_for_dynamic_submission(): context {
+ return \context_system::instance();
+ }
+
+ /**
+ * Checks if current user has access to this form, otherwise throws exception
+ */
+ protected function check_access_for_dynamic_submission(): void {
+ require_capability('moodle/site:config', $this->get_context_for_dynamic_submission());
+ }
+
+ /**
+ * Process the form submission, used if form was submitted via AJAX
+ */
+ public function process_dynamic_submission() {
+ global $CFG;
+ require_once($CFG->dirroot.'/user/profile/definelib.php');
+ profile_save_field($this->get_data(), $this->editors());
+ }
+
+ /**
+ * Load in existing data as form defaults
+ */
+ public function set_data_for_dynamic_submission(): void {
+ $field = $this->get_field_record();
+
+ // Clean and prepare description for the editor.
+ $description = clean_text($field->description, $field->descriptionformat);
+ $field->description = ['text' => $description, 'format' => $field->descriptionformat, 'itemid' => 0];
+ // Convert the data format for.
+ if (is_array($this->editors())) {
+ foreach ($this->editors() as $editor) {
+ if (isset($field->$editor)) {
+ $editordesc = clean_text($field->$editor, $field->{$editor.'format'});
+ $field->$editor = ['text' => $editordesc, 'format' => $field->{$editor.'format'}, 'itemid' => 0];
+ }
+ }
+ }
+
+ $this->set_data($field);
+ }
+
+ /**
+ * Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX
+ *
+ * @return moodle_url
+ */
+ protected function get_page_url_for_dynamic_submission(): moodle_url {
+ $id = $this->optional_param('id', 0, PARAM_INT);
+ $datatype = $this->optional_param('datatype', 'text', PARAM_PLUGIN);
+ return new moodle_url('/user/profile/index.php',
+ ['action' => 'editfield', 'id' => $id, 'datatype' => $id ? null : $datatype]);
+ }
+
+ /**
+ * Record for the field from the database (or generic record for a new field)
+ *
+ * @return false|mixed|\stdClass
+ * @throws \coding_exception
+ * @throws \dml_exception
+ */
+ public function get_field_record() {
+ global $DB;
+
+ if (!$this->fieldrecord) {
+ $id = $this->optional_param('id', 0, PARAM_INT);
+ if (!$id || !($this->fieldrecord = $DB->get_record('user_info_field', ['id' => $id]))) {
+ $datatype = $this->optional_param('datatype', 'text', PARAM_PLUGIN);
+ $this->fieldrecord = new \stdClass();
+ $this->fieldrecord->datatype = $datatype;
+ $this->fieldrecord->description = '';
+ $this->fieldrecord->descriptionformat = FORMAT_HTML;
+ $this->fieldrecord->defaultdata = '';
+ $this->fieldrecord->defaultdataformat = FORMAT_HTML;
+ $this->fieldrecord->categoryid = $this->optional_param('categoryid', 0, PARAM_INT);
+ }
+ if (!\core_component::get_component_directory('profilefield_'.$this->fieldrecord->datatype)) {
+ throw new \moodle_exception('fieldnotfound', 'customfield');
+ }
+ }
+
+ return $this->fieldrecord;
+ }
+}
+
+
diff --git a/user/filters/profilefield.php b/user/filters/profilefield.php
index a46030e05cf..328ad70c0bc 100644
--- a/user/filters/profilefield.php
+++ b/user/filters/profilefield.php
@@ -73,11 +73,12 @@ class user_filter_profilefield extends user_filter_type {
* @return array of profile fields
*/
public function get_profile_fields() {
- global $DB;
- $order = $DB->sql_order_by_text('name');
- if (!$fields = $DB->get_records_menu('user_info_field', null, $order, 'id, name')) {
- return null;
- }
+ global $CFG;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
+
+ $fieldrecords = profile_get_custom_fields();
+ $fields = array_combine(array_keys($fieldrecords), array_column($fieldrecords, 'name'));
+ core_collator::asort($fields);
$res = array(0 => get_string('anyfield', 'filters'));
return $res + $fields;
diff --git a/user/profile/definelib.php b/user/profile/definelib.php
index 22d37ee2011..bf57b78b743 100644
--- a/user/profile/definelib.php
+++ b/user/profile/definelib.php
@@ -32,7 +32,7 @@ class profile_define_base {
/**
* Prints out the form snippet for creating or editing a profile field
- * @param moodleform $form instance of the moodleform class
+ * @param MoodleQuickForm $form instance of the moodleform class
*/
public function define_form(&$form) {
$form->addElement('header', '_commonsettings', get_string('profilecommonsettings', 'admin'));
@@ -45,7 +45,7 @@ class profile_define_base {
/**
* Prints out the form snippet for the part of creating or editing a profile field common to all data types.
*
- * @param moodleform $form instance of the moodleform class
+ * @param MoodleQuickForm $form instance of the moodleform class
*/
public function define_form_common(&$form) {
@@ -88,7 +88,7 @@ class profile_define_base {
/**
* Prints out the form snippet for the part of creating or editing a profile field specific to the current data type.
- * @param moodleform $form instance of the moodleform class
+ * @param MoodleQuickForm $form instance of the moodleform class
*/
public function define_form_specific($form) {
// Do nothing - overwrite if necessary.
@@ -138,7 +138,7 @@ class profile_define_base {
$err['shortname'] = get_string('profileshortnameinvalid', 'admin');
} else {
// Fetch field-record from DB.
- $field = $DB->get_record('user_info_field', array('shortname' => $data->shortname));
+ $field = profile_get_custom_field_data_by_shortname($data->shortname);
// Check the shortname is unique.
if ($field and $field->id <> $data->id) {
$err['shortname'] = get_string('profileshortnamenotunique', 'admin');
@@ -166,7 +166,7 @@ class profile_define_base {
/**
* Alter form based on submitted or existing data
- * @param moodleform $mform
+ * @param MoodleQuickForm $mform
*/
public function define_after_data(&$mform) {
// Do nothing - overwrite if necessary.
@@ -204,6 +204,7 @@ class profile_define_base {
} else {
\core\event\user_info_field_created::create_from_field($field)->trigger();
}
+ profile_purge_user_fields_cache();
}
/**
@@ -251,6 +252,7 @@ function profile_reorder_fields() {
}
}
}
+ profile_purge_user_fields_cache();
}
}
@@ -268,6 +270,7 @@ function profile_reorder_categories() {
$c->sortorder = $i++;
$DB->update_record('user_info_category', $c);
}
+ profile_purge_user_fields_cache();
}
}
@@ -326,6 +329,7 @@ function profile_delete_category($id) {
profile_reorder_categories();
\core\event\user_info_category_deleted::create_from_category($category)->trigger();
+ profile_purge_user_fields_cache();
return true;
}
@@ -355,6 +359,7 @@ function profile_delete_field($id) {
$DB->delete_records('user_info_field', array('id' => $id));
\core\event\user_info_field_deleted::create_from_field($field)->trigger();
+ profile_purge_user_fields_cache();
// Reorder the remaining fields in the same category.
profile_reorder_fields();
@@ -445,6 +450,7 @@ function profile_move_category($id, $move) {
\core\event\user_info_category_updated::create_from_category($category)->trigger();
\core\event\user_info_category_updated::create_from_category($swapcategory)->trigger();
+ profile_purge_user_fields_cache();
return true;
}
@@ -478,18 +484,48 @@ function profile_list_categories() {
return array_map('format_string', $categories);
}
+/**
+ * Create or update a profile category
+ *
+ * @param stdClass $data
+ */
+function profile_save_category(stdClass $data): void {
+ global $DB;
+
+ if (empty($data->id)) {
+ unset($data->id);
+ $data->sortorder = $DB->count_records('user_info_category') + 1;
+ $data->id = $DB->insert_record('user_info_category', $data, true);
+
+ $createdcategory = $DB->get_record('user_info_category', array('id' => $data->id));
+ \core\event\user_info_category_created::create_from_category($createdcategory)->trigger();
+ } else {
+ $DB->update_record('user_info_category', $data);
+
+ $updatedcateogry = $DB->get_record('user_info_category', array('id' => $data->id));
+ \core\event\user_info_category_updated::create_from_category($updatedcateogry)->trigger();
+ }
+ profile_reorder_categories();
+ profile_purge_user_fields_cache();
+}
/**
* Edit a category
*
+ * @deprecated since Moodle 3.11 MDL-71051 - please do not use this function any more.
+ * @todo MDL-71413 This will be deleted in Moodle 4.3.
+ * @see profile_save_category()
+ *
* @param int $id
* @param string $redirect
*/
function profile_edit_category($id, $redirect) {
global $DB, $OUTPUT, $CFG;
- require_once($CFG->dirroot.'/user/profile/index_category_form.php');
- $categoryform = new category_form();
+ debugging('Function profile_edit_category() is deprecated without replacement, see also profile_save_category()',
+ DEBUG_DEVELOPER);
+
+ $categoryform = new \core_user\form\profile_category_form();
if ($category = $DB->get_record('user_info_category', array('id' => $id))) {
$categoryform->set_data($category);
@@ -499,22 +535,8 @@ function profile_edit_category($id, $redirect) {
redirect($redirect);
} else {
if ($data = $categoryform->get_data()) {
- if (empty($data->id)) {
- unset($data->id);
- $data->sortorder = $DB->count_records('user_info_category') + 1;
- $data->id = $DB->insert_record('user_info_category', $data, true);
-
- $createdcategory = $DB->get_record('user_info_category', array('id' => $data->id));
- \core\event\user_info_category_created::create_from_category($createdcategory)->trigger();
- } else {
- $DB->update_record('user_info_category', $data);
-
- $updatedcateogry = $DB->get_record('user_info_category', array('id' => $data->id));
- \core\event\user_info_category_updated::create_from_category($updatedcateogry)->trigger();
- }
- profile_reorder_categories();
+ profile_save_category($data);
redirect($redirect);
-
}
if (empty($id)) {
@@ -533,78 +555,73 @@ function profile_edit_category($id, $redirect) {
}
+/**
+ * Save updated field definition or create a new field
+ *
+ * @param stdClass $data data from the form profile_field_form
+ * @param array $editors editors for this form field type
+ */
+function profile_save_field(stdClass $data, array $editors): void {
+ global $CFG;
+
+ require_once($CFG->dirroot.'/user/profile/field/'.$data->datatype.'/define.class.php');
+ $newfield = 'profile_define_'.$data->datatype;
+ /** @var profile_define_base $formfield */
+ $formfield = new $newfield();
+
+ // Collect the description and format back into the proper data structure from the editor.
+ // Note: This field will ALWAYS be an editor.
+ $data->descriptionformat = $data->description['format'];
+ $data->description = $data->description['text'];
+
+ // Check whether the default data is an editor, this is (currently) only the textarea field type.
+ if (is_array($data->defaultdata) && array_key_exists('text', $data->defaultdata)) {
+ // Collect the default data and format back into the proper data structure from the editor.
+ $data->defaultdataformat = $data->defaultdata['format'];
+ $data->defaultdata = $data->defaultdata['text'];
+ }
+
+ // Convert the data format for.
+ if (is_array($editors)) {
+ foreach ($editors as $editor) {
+ if (isset($field->$editor)) {
+ $field->{$editor.'format'} = $field->{$editor}['format'];
+ $field->$editor = $field->{$editor}['text'];
+ }
+ }
+ }
+
+ $formfield->define_save($data);
+ profile_reorder_fields();
+ profile_reorder_categories();
+}
+
/**
* Edit a profile field.
*
+ * @deprecated since Moodle 3.11 MDL-71051 - please do not use this function any more.
+ * @todo MDL-71413 This will be deleted in Moodle 4.3.
+ * @see profile_save_field()
+ *
* @param int $id
* @param string $datatype
* @param string $redirect
*/
function profile_edit_field($id, $datatype, $redirect) {
- global $CFG, $DB, $OUTPUT, $PAGE;
+ global $OUTPUT, $PAGE;
- if (!$field = $DB->get_record('user_info_field', array('id' => $id))) {
- $field = new stdClass();
- $field->datatype = $datatype;
- $field->description = '';
- $field->descriptionformat = FORMAT_HTML;
- $field->defaultdata = '';
- $field->defaultdataformat = FORMAT_HTML;
- }
+ debugging('Function profile_edit_field() is deprecated without replacement, see also profile_save_field()',
+ DEBUG_DEVELOPER);
- // Clean and prepare description for the editor.
- $field->description = clean_text($field->description, $field->descriptionformat);
- $field->description = array('text' => $field->description, 'format' => $field->descriptionformat, 'itemid' => 0);
-
- require_once($CFG->dirroot.'/user/profile/index_field_form.php');
- $fieldform = new field_form(null, $field->datatype);
-
- // Convert the data format for.
- if (is_array($fieldform->editors())) {
- foreach ($fieldform->editors() as $editor) {
- if (isset($field->$editor)) {
- $field->$editor = clean_text($field->$editor, $field->{$editor.'format'});
- $field->$editor = array('text' => $field->$editor, 'format' => $field->{$editor.'format'}, 'itemid' => 0);
- }
- }
- }
-
- $fieldform->set_data($field);
+ $fieldform = new \core_user\form\profile_field_form();
+ $fieldform->set_data_for_dynamic_submission();
if ($fieldform->is_cancelled()) {
redirect($redirect);
} else {
if ($data = $fieldform->get_data()) {
- require_once($CFG->dirroot.'/user/profile/field/'.$datatype.'/define.class.php');
- $newfield = 'profile_define_'.$datatype;
- $formfield = new $newfield();
-
- // Collect the description and format back into the proper data structure from the editor.
- // Note: This field will ALWAYS be an editor.
- $data->descriptionformat = $data->description['format'];
- $data->description = $data->description['text'];
-
- // Check whether the default data is an editor, this is (currently) only the textarea field type.
- if (is_array($data->defaultdata) && array_key_exists('text', $data->defaultdata)) {
- // Collect the default data and format back into the proper data structure from the editor.
- $data->defaultdataformat = $data->defaultdata['format'];
- $data->defaultdata = $data->defaultdata['text'];
- }
-
- // Convert the data format for.
- if (is_array($fieldform->editors())) {
- foreach ($fieldform->editors() as $editor) {
- if (isset($field->$editor)) {
- $field->{$editor.'format'} = $field->{$editor}['format'];
- $field->$editor = $field->{$editor}['text'];
- }
- }
- }
-
- $formfield->define_save($data);
- profile_reorder_fields();
- profile_reorder_categories();
+ profile_save_field($data, $fieldform->editors());
redirect($redirect);
}
@@ -613,7 +630,7 @@ function profile_edit_field($id, $datatype, $redirect) {
if (empty($id)) {
$strheading = get_string('profilecreatenewfield', 'admin', $datatypes[$datatype]);
} else {
- $strheading = get_string('profileeditfield', 'admin', format_string($field->name));
+ $strheading = get_string('profileeditfield', 'admin', format_string($fieldform->get_field_record()->name));
}
// Print the page.
@@ -626,4 +643,11 @@ function profile_edit_field($id, $datatype, $redirect) {
}
}
-
+/**
+ * Purge the cache for the user profile fields
+ */
+function profile_purge_user_fields_cache() {
+ $cache = \cache::make_from_params(cache_store::MODE_REQUEST, 'core_profile', 'customfields',
+ [], ['simplekeys' => true, 'simpledata' => true]);
+ $cache->purge();
+}
diff --git a/user/profile/field/checkbox/tests/privacy_test.php b/user/profile/field/checkbox/tests/privacy_test.php
index 9f4862e84bb..17d618c9767 100644
--- a/user/profile/field/checkbox/tests/privacy_test.php
+++ b/user/profile/field/checkbox/tests/privacy_test.php
@@ -276,13 +276,8 @@ class profilefield_checkbox_testcase extends provider_testcase {
* @return int The ID of the profile category
*/
private function add_profile_category() {
- global $DB;
- // Create a new profile category.
- $cat = new stdClass();
- $cat->name = 'Test category';
- $cat->sortorder = 1;
-
- return $DB->insert_record('user_info_category', $cat);
+ $cat = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Test category']);
+ return $cat->id;
}
/**
@@ -293,20 +288,13 @@ class profilefield_checkbox_testcase extends provider_testcase {
* @return int The ID of the profile field
*/
private function add_profile_field($categoryid, $datatype) {
- global $DB;
- // Create a new profile field.
- $data = new stdClass();
- $data->datatype = $datatype;
- $data->shortname = 'tstField';
- $data->name = 'Test field';
- $data->description = 'This is a test.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $categoryid;
-
- return $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => $datatype,
+ 'shortname' => 'tstField',
+ 'name' => 'Test field',
+ 'description' => 'This is a test.',
+ 'categoryid' => $categoryid,
+ ]);
+ return $data->id;
}
}
diff --git a/user/profile/field/datetime/tests/privacy_test.php b/user/profile/field/datetime/tests/privacy_test.php
index d18026e044a..eaa1921495a 100644
--- a/user/profile/field/datetime/tests/privacy_test.php
+++ b/user/profile/field/datetime/tests/privacy_test.php
@@ -280,13 +280,8 @@ class profilefield_datetime_testcase extends provider_testcase {
* @return int The ID of the profile category
*/
private function add_profile_category() {
- global $DB;
- // Create a new profile category.
- $cat = new stdClass();
- $cat->name = 'Test category';
- $cat->sortorder = 1;
-
- return $DB->insert_record('user_info_category', $cat);
+ $cat = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Test category']);
+ return $cat->id;
}
/**
@@ -297,20 +292,13 @@ class profilefield_datetime_testcase extends provider_testcase {
* @return int The ID of the profile field
*/
private function add_profile_field($categoryid, $datatype) {
- global $DB;
- // Create a new profile field.
- $data = new stdClass();
- $data->datatype = $datatype;
- $data->shortname = 'tstField';
- $data->name = 'Test field';
- $data->description = 'This is a test.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $categoryid;
-
- return $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => $datatype,
+ 'shortname' => 'tstField',
+ 'name' => 'Test field',
+ 'description' => 'This is a test.',
+ 'categoryid' => $categoryid,
+ ]);
+ return $data->id;
}
}
diff --git a/user/profile/field/menu/tests/privacy_test.php b/user/profile/field/menu/tests/privacy_test.php
index ff399ebb7d6..647f40fe13f 100644
--- a/user/profile/field/menu/tests/privacy_test.php
+++ b/user/profile/field/menu/tests/privacy_test.php
@@ -277,13 +277,8 @@ class profilefield_menu_testcase extends provider_testcase {
* @return int The ID of the profile category
*/
private function add_profile_category() {
- global $DB;
- // Create a new profile category.
- $cat = new stdClass();
- $cat->name = 'Test category';
- $cat->sortorder = 1;
-
- return $DB->insert_record('user_info_category', $cat);
+ $cat = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Test category']);
+ return $cat->id;
}
/**
@@ -294,20 +289,13 @@ class profilefield_menu_testcase extends provider_testcase {
* @return int The ID of the profile field
*/
private function add_profile_field($categoryid, $datatype) {
- global $DB;
- // Create a new profile field.
- $data = new stdClass();
- $data->datatype = $datatype;
- $data->shortname = 'tstField';
- $data->name = 'Test field';
- $data->description = 'This is a test.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $categoryid;
-
- return $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => $datatype,
+ 'shortname' => 'tstField',
+ 'name' => 'Test field',
+ 'description' => 'This is a test.',
+ 'categoryid' => $categoryid,
+ ]);
+ return $data->id;
}
}
diff --git a/user/profile/field/social/tests/behat/social_profile_field.feature b/user/profile/field/social/tests/behat/social_profile_field.feature
index 8abf51d8cc5..572cf386566 100644
--- a/user/profile/field/social/tests/behat/social_profile_field.feature
+++ b/user/profile/field/social/tests/behat/social_profile_field.feature
@@ -8,14 +8,16 @@ Feature: Social profile fields can not have a duplicate shortname.
Scenario: Verify you can edit social profile fields.
Given I log in as "admin"
When I navigate to "Users > Accounts > User profile fields" in site administration
- And I set the field "datatype" to "Social"
+ And I click on "Create a new profile field" "link"
+ And I click on "Social" "link"
And I set the following fields to these values:
- | Short name | yahoo |
| Networktype | Yahoo ID |
+ | Short name | yahoo |
And I click on "Save changes" "button"
- And I set the field "datatype" to "Social"
+ And I click on "Create a new profile field" "link"
+ And I click on "Social" "link"
And I set the following fields to these values:
- | Short name | yahoo |
| Networktype | Yahoo ID |
+ | Short name | yahoo |
And I click on "Save changes" "button"
Then I should see "This short name is already in use"
diff --git a/user/profile/field/social/tests/privacy_test.php b/user/profile/field/social/tests/privacy_test.php
index 4c336f04b32..38bd287fa42 100644
--- a/user/profile/field/social/tests/privacy_test.php
+++ b/user/profile/field/social/tests/privacy_test.php
@@ -276,13 +276,8 @@ class profilefield_social_testcase extends provider_testcase {
* @return int The ID of the profile category
*/
private function add_profile_category() {
- global $DB;
- // Create a new profile category.
- $cat = new stdClass();
- $cat->name = 'Test category';
- $cat->sortorder = 1;
-
- return $DB->insert_record('user_info_category', $cat);
+ $cat = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Test category']);
+ return $cat->id;
}
/**
@@ -293,20 +288,13 @@ class profilefield_social_testcase extends provider_testcase {
* @return int The ID of the profile field
*/
private function add_profile_field($categoryid, $datatype) {
- global $DB;
- // Create a new profile field.
- $data = new stdClass();
- $data->datatype = $datatype;
- $data->shortname = 'icq';
- $data->name = 'icq';
- $data->description = '';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $categoryid;
-
- return $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => $datatype,
+ 'shortname' => 'icq',
+ 'name' => 'icq',
+ 'description' => '',
+ 'categoryid' => $categoryid,
+ ]);
+ return $data->id;
}
}
diff --git a/user/profile/field/text/tests/privacy_test.php b/user/profile/field/text/tests/privacy_test.php
index a5c35d5ff1c..a3e2bcc60be 100644
--- a/user/profile/field/text/tests/privacy_test.php
+++ b/user/profile/field/text/tests/privacy_test.php
@@ -277,13 +277,8 @@ class profilefield_text_testcase extends provider_testcase {
* @return int The ID of the profile category
*/
private function add_profile_category() {
- global $DB;
- // Create a new profile category.
- $cat = new stdClass();
- $cat->name = 'Test category';
- $cat->sortorder = 1;
-
- return $DB->insert_record('user_info_category', $cat);
+ $cat = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Test category']);
+ return $cat->id;
}
/**
@@ -294,20 +289,13 @@ class profilefield_text_testcase extends provider_testcase {
* @return int The ID of the profile field
*/
private function add_profile_field($categoryid, $datatype) {
- global $DB;
- // Create a new profile field.
- $data = new stdClass();
- $data->datatype = $datatype;
- $data->shortname = 'tstField';
- $data->name = 'Test field';
- $data->description = 'This is a test.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $categoryid;
-
- return $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => $datatype,
+ 'shortname' => 'tstField',
+ 'name' => 'Test field',
+ 'description' => 'This is a test.',
+ 'categoryid' => $categoryid,
+ ]);
+ return $data->id;
}
}
diff --git a/user/profile/field/textarea/tests/privacy_test.php b/user/profile/field/textarea/tests/privacy_test.php
index 5ed8bb49b61..1e47d57cb3e 100644
--- a/user/profile/field/textarea/tests/privacy_test.php
+++ b/user/profile/field/textarea/tests/privacy_test.php
@@ -276,13 +276,8 @@ class profilefield_textarea_testcase extends provider_testcase {
* @return int The ID of the profile category
*/
private function add_profile_category() {
- global $DB;
- // Create a new profile category.
- $cat = new stdClass();
- $cat->name = 'Test category';
- $cat->sortorder = 1;
-
- return $DB->insert_record('user_info_category', $cat);
+ $cat = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Test category']);
+ return $cat->id;
}
/**
@@ -293,20 +288,13 @@ class profilefield_textarea_testcase extends provider_testcase {
* @return int The ID of the profile field
*/
private function add_profile_field($categoryid, $datatype) {
- global $DB;
- // Create a new profile field.
- $data = new stdClass();
- $data->datatype = $datatype;
- $data->shortname = 'tstField';
- $data->name = 'Test field';
- $data->description = 'This is a test.';
- $data->required = false;
- $data->locked = false;
- $data->forceunique = false;
- $data->signup = false;
- $data->visible = '0';
- $data->categoryid = $categoryid;
-
- return $DB->insert_record('user_info_field', $data);
+ $data = $this->getDataGenerator()->create_custom_profile_field([
+ 'datatype' => $datatype,
+ 'shortname' => 'tstField',
+ 'name' => 'Test field',
+ 'description' => 'This is a test.',
+ 'categoryid' => $categoryid,
+ ]);
+ return $data->id;
}
}
diff --git a/user/profile/index.php b/user/profile/index.php
index ae55294ed12..c2806e64fbf 100644
--- a/user/profile/index.php
+++ b/user/profile/index.php
@@ -32,10 +32,7 @@ $action = optional_param('action', '', PARAM_ALPHA);
$redirect = $CFG->wwwroot.'/user/profile/index.php';
-$strchangessaved = get_string('changessaved');
-$strcancelled = get_string('cancelled');
$strdefaultcategory = get_string('profiledefaultcategory', 'admin');
-$strnofields = get_string('profilenofieldsdefined', 'admin');
$strcreatefield = get_string('profilecreatefield', 'admin');
@@ -91,19 +88,6 @@ switch ($action) {
echo $OUTPUT->footer();
die;
break;
- case 'editfield':
- $id = optional_param('id', 0, PARAM_INT);
- $datatype = optional_param('datatype', '', PARAM_ALPHA);
-
- profile_edit_field($id, $datatype, $redirect);
- die;
- break;
- case 'editcategory':
- $id = optional_param('id', 0, PARAM_INT);
-
- profile_edit_category($id, $redirect);
- die;
- break;
default:
// Normal form.
}
@@ -124,14 +108,12 @@ if (empty($categories)) {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('profilefields', 'admin'));
-foreach ($categories as $category) {
- $table = new html_table();
- $table->head = array(get_string('profilefield', 'admin'), get_string('edit'));
- $table->align = array('left', 'right');
- $table->width = '95%';
- $table->attributes['class'] = 'generaltable profilefield';
- $table->data = array();
+$outputcategories = [];
+$options = profile_list_datatypes();
+foreach ($categories as $category) {
+ // Category fields.
+ $outputfields = [];
if ($fields = $DB->get_records('user_info_field', array('categoryid' => $category->id), 'sortorder ASC')) {
foreach ($fields as $field) {
$fieldname = format_string($field->name);
@@ -140,139 +122,46 @@ foreach ($categories as $category) {
if (class_exists($classname) && method_exists($classname, 'get_fieldname')) {
$fieldname = $classname::get_fieldname($field->name);
}
- $table->data[] = array($fieldname, profile_field_icons($field));
+ $outputfields[] = [
+ 'id' => $field->id,
+ 'shortname' => $field->shortname,
+ 'datatype' => $field->datatype,
+ 'name' => $fieldname,
+ 'isfirst' => !count($outputfields),
+ 'islast' => count($outputfields) == count($fields) - 1,
+ ];
}
}
- echo $OUTPUT->heading(format_string($category->name) .' '.profile_category_icons($category));
- if (count($table->data)) {
- echo html_writer::table($table);
- } else {
- echo $OUTPUT->notification($strnofields);
+ // Add new field menu.
+ $menu = new \action_menu();
+ $menu->set_alignment(\action_menu::BL, \action_menu::BL);
+ $menu->set_menu_trigger($strcreatefield);
+ foreach ($options as $type => $fieldname) {
+ $action = new \action_menu_link_secondary(new \moodle_url('#'), null, $fieldname,
+ ['data-action' => 'createfield', 'data-categoryid' => $category->id, 'data-datatype' => $type,
+ 'data-datatypename' => $fieldname]);
+ $menu->add($action);
}
+ $menu->attributes['class'] .= ' float-left mr-1';
-} // End of $categories foreach.
+ // Add category information to the template.
+ $outputcategories[] = [
+ 'id' => $category->id,
+ 'name' => format_string($category->name),
+ 'fields' => $outputfields,
+ 'hasfields' => count($outputfields),
+ 'isfirst' => !count($outputcategories),
+ 'islast' => count($outputcategories) == count($categories) - 1,
+ 'candelete' => count($categories) > 1,
+ 'addfieldmenu' => $menu->export_for_template($OUTPUT),
+ ];
+}
-echo '
';
-echo '';
-
-// Create a new field link.
-$options = profile_list_datatypes();
-$popupurl = new moodle_url('/user/profile/index.php?id=0&action=editfield');
-echo $OUTPUT->single_select($popupurl, 'datatype', $options, '', array('' => get_string('choosedots')), 'newfieldform', array('label' => $strcreatefield));
-
-// Add a div with a class so themers can hide, style or reposition the text.
-html_writer::start_tag('div', array('class' => 'adminuseractionhint'));
-echo get_string('or', 'lesson');
-html_writer::end_tag('div');
-
-// Create a new category link.
-$options = array('action' => 'editcategory');
-echo $OUTPUT->single_button(new moodle_url('index.php', $options), get_string('profilecreatecategory', 'admin'));
-
-echo '
';
+echo $OUTPUT->render_from_template('core_user/edit_profile_fields', [
+ 'categories' => $outputcategories,
+ 'sesskey' => sesskey(),
+ 'baseurl' => (new moodle_url('/user/profile/index.php'))->out(false)
+]);
echo $OUTPUT->footer();
-die;
-
-
-/***** Some functions relevant to this script *****/
-
-/**
- * Create a string containing the editing icons for the user profile categories
- * @param stdClass $category the category object
- * @return string the icon string
- */
-function profile_category_icons($category) {
- global $CFG, $USER, $DB, $OUTPUT;
-
- $strdelete = get_string('delete');
- $strmoveup = get_string('moveup');
- $strmovedown = get_string('movedown');
- $stredit = get_string('edit');
-
- $categorycount = $DB->count_records('user_info_category');
- $fieldcount = $DB->count_records('user_info_field', array('categoryid' => $category->id));
-
- // Edit.
- $editstr = '' .
- $OUTPUT->pix_icon('t/edit', $stredit) .' ';
-
- // Delete.
- // Can only delete the last category if there are no fields in it.
- if (($categorycount > 1) or ($fieldcount == 0)) {
- $editstr .= 'id.'&action=deletecategory&sesskey='.sesskey() . '">';
- $editstr .= $OUTPUT->pix_icon('t/delete', $strdelete).' ';
- } else {
- $editstr .= $OUTPUT->spacer() . ' ';
- }
-
- // Move up.
- if ($category->sortorder > 1) {
- $editstr .= 'id.'&action=movecategory&dir=up&sesskey='.sesskey().'">';
- $editstr .= $OUTPUT->pix_icon('t/up', $strmoveup) . ' ';
- } else {
- $editstr .= $OUTPUT->spacer() . ' ';
- }
-
- // Move down.
- if ($category->sortorder < $categorycount) {
- $editstr .= 'id.'&action=movecategory&dir=down&sesskey='.sesskey().'">';
- $editstr .= $OUTPUT->pix_icon('t/down', $strmovedown) . ' ';
- } else {
- $editstr .= $OUTPUT->spacer() . ' ';
- }
-
- return $editstr;
-}
-
-/**
- * Create a string containing the editing icons for the user profile fields
- * @param stdClass $field the field object
- * @return string the icon string
- */
-function profile_field_icons($field) {
- global $CFG, $USER, $DB, $OUTPUT;
-
- $strdelete = get_string('delete');
- $strmoveup = get_string('moveup');
- $strmovedown = get_string('movedown');
- $stredit = get_string('edit');
-
- $fieldcount = $DB->count_records('user_info_field', array('categoryid' => $field->categoryid));
- $datacount = $DB->count_records('user_info_data', array('fieldid' => $field->id));
-
- // Edit.
- $editstr = '';
- $editstr .= $OUTPUT->pix_icon('t/edit', $stredit) . ' ';
-
- // Delete.
- $editstr .= '';
- $editstr .= $OUTPUT->pix_icon('t/delete', $strdelete) . ' ';
-
- // Move up.
- if ($field->sortorder > 1) {
- $editstr .= 'id.'&action=movefield&dir=up&sesskey='.sesskey().'">';
- $editstr .= $OUTPUT->pix_icon('t/up', $strmoveup) . ' ';
- } else {
- $editstr .= $OUTPUT->spacer() . ' ';
- }
-
- // Move down.
- if ($field->sortorder < $fieldcount) {
- $editstr .= 'id.'&action=movefield&dir=down&sesskey='.sesskey().'">';
- $editstr .= $OUTPUT->pix_icon('t/down', $strmovedown) . ' ';
- } else {
- $editstr .= $OUTPUT->spacer() . ' ';
- }
-
- return $editstr;
-}
-
-
-
diff --git a/user/profile/index_category_form.php b/user/profile/index_category_form.php
deleted file mode 100644
index 551e7fb2879..00000000000
--- a/user/profile/index_category_form.php
+++ /dev/null
@@ -1,95 +0,0 @@
-.
-
-/**
- * This file contains the profile field category form.
- *
- * @package core_user
- * @copyright 2007 onwards Shane Elliot {@link http://pukunui.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-if (!defined('MOODLE_INTERNAL')) {
- die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
-}
-
-require_once($CFG->dirroot.'/lib/formslib.php');
-
-/**
- * Class category_form
- *
- * @copyright 2007 onwards Shane Elliot {@link http://pukunui.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class category_form extends moodleform {
-
- /**
- * Define the form.
- */
- public function definition () {
- global $USER, $CFG;
-
- $mform = $this->_form;
-
- $strrequired = get_string('required');
-
- // Add some extra hidden fields.
- $mform->addElement('hidden', 'id');
- $mform->setType('id', PARAM_INT);
- $mform->addElement('hidden', 'action', 'editcategory');
- $mform->setType('action', PARAM_ALPHANUMEXT);
-
- $mform->addElement('text', 'name', get_string('profilecategoryname', 'admin'), 'maxlength="255" size="30"');
- $mform->setType('name', PARAM_TEXT);
- $mform->addRule('name', $strrequired, 'required', null, 'client');
-
- $this->add_action_buttons(true);
-
- }
-
- /**
- * Perform some moodle validation.
- *
- * @param array $data
- * @param array $files
- * @return array
- */
- public function validation($data, $files) {
- global $CFG, $DB;
- $errors = parent::validation($data, $files);
-
- $data = (object)$data;
-
- $duplicate = $DB->get_field('user_info_category', 'id', array('name' => $data->name));
-
- // Check the name is unique.
- if (!empty($data->id)) { // We are editing an existing record.
- $olddata = $DB->get_record('user_info_category', array('id' => $data->id));
- // Name has changed, new name in use, new name in use by another record.
- $dupfound = (($olddata->name !== $data->name) && $duplicate && ($data->id != $duplicate));
- } else { // New profile category.
- $dupfound = $duplicate;
- }
-
- if ($dupfound ) {
- $errors['name'] = get_string('profilecategorynamenotunique', 'admin');
- }
-
- return $errors;
- }
-}
-
-
diff --git a/user/profile/index_field_form.php b/user/profile/index_field_form.php
deleted file mode 100644
index 39d168c07f3..00000000000
--- a/user/profile/index_field_form.php
+++ /dev/null
@@ -1,100 +0,0 @@
-.
-
-/**
- * This file contains the Field Form used for profile fields.
- *
- * @package core_user
- * @copyright 2007 onwards Shane Elliot {@link http://pukunui.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-if (!defined('MOODLE_INTERNAL')) {
- die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
-}
-
-require_once($CFG->dirroot.'/lib/formslib.php');
-
-/**
- * Class field_form
- *
- * @copyright 2007 onwards Shane Elliot {@link http://pukunui.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class field_form extends moodleform {
-
- /** @var profile_define_base $field */
- public $field;
-
- /**
- * Define the form
- */
- public function definition () {
- global $CFG;
-
- $mform = $this->_form;
-
- // Everything else is dependant on the data type.
- $datatype = $this->_customdata;
- require_once($CFG->dirroot.'/user/profile/field/'.$datatype.'/define.class.php');
- $newfield = 'profile_define_'.$datatype;
- $this->field = new $newfield();
-
- $strrequired = get_string('required');
-
- // Add some extra hidden fields.
- $mform->addElement('hidden', 'id');
- $mform->setType('id', PARAM_INT);
- $mform->addElement('hidden', 'action', 'editfield');
- $mform->setType('action', PARAM_ALPHANUMEXT);
- $mform->addElement('hidden', 'datatype', $datatype);
- $mform->setType('datatype', PARAM_ALPHA);
-
- $this->field->define_form($mform);
-
- $this->add_action_buttons(true);
- }
-
-
- /**
- * Alter definition based on existing or submitted data
- */
- public function definition_after_data () {
- $mform = $this->_form;
- $this->field->define_after_data($mform);
- }
-
-
- /**
- * Perform some moodle validation.
- * @param array $data
- * @param array $files
- * @return array
- */
- public function validation($data, $files) {
- return $this->field->define_validate($data, $files);
- }
-
- /**
- * Returns the defined editors for the field.
- * @return mixed
- */
- public function editors() {
- return $this->field->define_editors();
- }
-}
-
-
diff --git a/user/profile/lib.php b/user/profile/lib.php
index cd74a4d35a2..d4b59d44e86 100644
--- a/user/profile/lib.php
+++ b/user/profile/lib.php
@@ -84,7 +84,7 @@ class profile_field_base {
* Constructor method.
* @param int $fieldid id of the profile from the user_info_field table
* @param int $userid id of the user for whom we are displaying data
- * @param object $fielddata optional data for the field object plus additional fields 'hasuserdata', 'data' and 'dataformat'
+ * @param stdClass $fielddata optional data for the field object plus additional fields 'hasuserdata', 'data' and 'dataformat'
* with user data. (If $fielddata->hasuserdata is empty, user data is not available and we should use default data).
* If this parameter is passed, constructor will not call load_data() at all.
*/
@@ -130,7 +130,7 @@ class profile_field_base {
/**
* Abstract method: Adds the profile field to the moodle form class
* @abstract The following methods must be overwritten by child classes
- * @param moodleform $mform instance of the moodleform class
+ * @param MoodleQuickForm $mform instance of the moodleform class
*/
public function edit_field_add($mform) {
print_error('mustbeoveride', 'debug', '', 'edit_field_add');
@@ -148,7 +148,7 @@ class profile_field_base {
/**
* Print out the form field in the edit profile page
- * @param moodleform $mform instance of the moodleform class
+ * @param MoodleQuickForm $mform instance of the moodleform class
* @return bool
*/
public function edit_field($mform) {
@@ -164,7 +164,7 @@ class profile_field_base {
/**
* Tweaks the edit form
- * @param moodleform $mform instance of the moodleform class
+ * @param MoodleQuickForm $mform instance of the moodleform class
* @return bool
*/
public function edit_after_data($mform) {
@@ -179,7 +179,6 @@ class profile_field_base {
/**
* Saves the data coming from form
* @param stdClass $usernew data coming from the form
- * @return mixed returns data id if success of db insert/update, false on fail, 0 if not permitted
*/
public function edit_save_data($usernew) {
global $DB;
@@ -213,7 +212,7 @@ class profile_field_base {
* Validate the form field from profile page
*
* @param stdClass $usernew
- * @return string contains error message otherwise null
+ * @return array error messages for the form validation
*/
public function edit_validate_field($usernew) {
global $DB;
@@ -256,7 +255,7 @@ class profile_field_base {
/**
* Sets the default data for the field in the form object
- * @param moodleform $mform instance of the moodleform class
+ * @param MoodleQuickForm $mform instance of the moodleform class
*/
public function edit_field_set_default($mform) {
if (!empty($this->field->defaultdata)) {
@@ -267,7 +266,7 @@ class profile_field_base {
/**
* Sets the required flag for the field in the form object
*
- * @param moodleform $mform instance of the moodleform class
+ * @param MoodleQuickForm $mform instance of the moodleform class
*/
public function edit_field_set_required($mform) {
global $USER;
@@ -278,7 +277,7 @@ class profile_field_base {
/**
* HardFreeze the field if locked.
- * @param moodleform $mform instance of the moodleform class
+ * @param MoodleQuickForm $mform instance of the moodleform class
*/
public function edit_field_set_locked($mform) {
if (!$mform->elementExists($this->inputname)) {
@@ -389,6 +388,15 @@ class profile_field_base {
$this->categoryname = $categoryname;
}
+ /**
+ * Return field short name
+ *
+ * @return string
+ */
+ public function get_shortname(): string {
+ return $this->field->shortname;
+ }
+
/**
* Returns the name of the profile category where this field is
*
@@ -567,7 +575,7 @@ class profile_field_base {
* @param int $userid
* @return profile_field_base[]
*/
-function profile_get_user_fields_with_data($userid) {
+function profile_get_user_fields_with_data(int $userid): array {
global $DB, $CFG;
// Join any user info data present with each user info field for the user object.
@@ -601,7 +609,7 @@ function profile_get_user_fields_with_data($userid) {
* @param int $userid
* @return profile_field_base[][]
*/
-function profile_get_user_fields_with_data_by_category($userid) {
+function profile_get_user_fields_with_data_by_category(int $userid): array {
$fields = profile_get_user_fields_with_data($userid);
$data = [];
foreach ($fields as $field) {
@@ -614,9 +622,7 @@ function profile_get_user_fields_with_data_by_category($userid) {
* Loads user profile field data into the user object.
* @param stdClass $user
*/
-function profile_load_data($user) {
- global $CFG;
-
+function profile_load_data(stdClass $user): void {
$fields = profile_get_user_fields_with_data($user->id);
foreach ($fields as $formfield) {
$formfield->edit_load_user_data($user);
@@ -626,10 +632,10 @@ function profile_load_data($user) {
/**
* Print out the customisable categories and fields for a users profile
*
- * @param moodleform $mform instance of the moodleform class
- * @param int $userid id of user whose profile is being edited.
+ * @param MoodleQuickForm $mform instance of the moodleform class
+ * @param int $userid id of user whose profile is being edited or 0 for the new user
*/
-function profile_definition($mform, $userid = 0) {
+function profile_definition(MoodleQuickForm $mform, int $userid = 0): void {
$categories = profile_get_user_fields_with_data_by_category($userid);
foreach ($categories as $categoryid => $fields) {
// Check first if *any* fields will be displayed.
@@ -655,12 +661,10 @@ function profile_definition($mform, $userid = 0) {
/**
* Adds profile fields to user edit forms.
- * @param moodleform $mform
+ * @param MoodleQuickForm $mform
* @param int $userid
*/
-function profile_definition_after_data($mform, $userid) {
- global $CFG;
-
+function profile_definition_after_data(MoodleQuickForm $mform, int $userid): void {
$userid = ($userid < 0) ? 0 : (int)$userid;
$fields = profile_get_user_fields_with_data($userid);
@@ -673,11 +677,9 @@ function profile_definition_after_data($mform, $userid) {
* Validates profile data.
* @param stdClass $usernew
* @param array $files
- * @return array
+ * @return array array of errors, same as in {@see moodleform::validation()}
*/
-function profile_validation($usernew, $files) {
- global $CFG;
-
+function profile_validation(stdClass $usernew, array $files): array {
$err = array();
$fields = profile_get_user_fields_with_data($usernew->id);
foreach ($fields as $formfield) {
@@ -690,7 +692,7 @@ function profile_validation($usernew, $files) {
* Saves profile data for a user.
* @param stdClass $usernew
*/
-function profile_save_data($usernew) {
+function profile_save_data(stdClass $usernew): void {
global $CFG;
$fields = profile_get_user_fields_with_data($usernew->id);
@@ -701,10 +703,15 @@ function profile_save_data($usernew) {
/**
* Display profile fields.
+ *
+ * @deprecated since Moodle 3.11 MDL-71051 - please do not use this function any more.
+ * @todo MDL-71413 This will be deleted in Moodle 4.3.
+ *
* @param int $userid
*/
function profile_display_fields($userid) {
- global $CFG, $USER, $DB;
+ debugging('Function profile_display_fields() is deprecated because it is no longer used and will be '.
+ 'removed in future versions of Moodle', DEBUG_DEVELOPER);
$categories = profile_get_user_fields_with_data_by_category($userid);
foreach ($categories as $categoryid => $fields) {
@@ -723,28 +730,16 @@ function profile_display_fields($userid) {
* @return array list of profile fields info
* @since Moodle 3.2
*/
-function profile_get_signup_fields() {
- global $CFG, $DB;
-
+function profile_get_signup_fields(): array {
$profilefields = array();
- // Only retrieve required custom fields (with category information)
- // results are sort by categories, then by fields.
- $sql = "SELECT uf.id as fieldid, ic.id as categoryid, ic.name as categoryname, uf.datatype
- FROM {user_info_field} uf
- JOIN {user_info_category} ic
- ON uf.categoryid = ic.id AND uf.signup = 1 AND uf.visible<>0
- ORDER BY ic.sortorder ASC, uf.sortorder ASC";
-
- if ($fields = $DB->get_records_sql($sql)) {
- foreach ($fields as $field) {
- require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
- $newfield = 'profile_field_'.$field->datatype;
- $fieldobject = new $newfield($field->fieldid);
-
+ $fieldobjects = profile_get_user_fields_with_data(0);
+ foreach ($fieldobjects as $fieldobject) {
+ $field = (object)$fieldobject->get_field_config_for_external();
+ if ($fieldobject->get_category_name() !== null && $fieldobject->is_signup_field() && $field->visible <> 0) {
$profilefields[] = (object) array(
'categoryid' => $field->categoryid,
- 'categoryname' => $field->categoryname,
- 'fieldid' => $field->fieldid,
+ 'categoryname' => $fieldobject->get_category_name(),
+ 'fieldid' => $field->id,
'datatype' => $field->datatype,
'object' => $fieldobject
);
@@ -756,9 +751,9 @@ function profile_get_signup_fields() {
/**
* Adds code snippet to a moodle form object for custom profile fields that
* should appear on the signup page
- * @param moodleform $mform moodle form object
+ * @param MoodleQuickForm $mform moodle form object
*/
-function profile_signup_fields($mform) {
+function profile_signup_fields(MoodleQuickForm $mform): void {
if ($fields = profile_get_signup_fields()) {
foreach ($fields as $field) {
@@ -774,13 +769,11 @@ function profile_signup_fields($mform) {
/**
* Returns an object with the custom profile fields set for the given user
- * @param integer $userid
+ * @param int $userid
* @param bool $onlyinuserobject True if you only want the ones in $USER.
- * @return stdClass
+ * @return stdClass object where properties names are shortnames of custom profile fields
*/
-function profile_user_record($userid, $onlyinuserobject = true) {
- global $CFG;
-
+function profile_user_record(int $userid, bool $onlyinuserobject = true): stdClass {
$usercustomfields = new stdClass();
$fields = profile_get_user_fields_with_data($userid);
@@ -807,33 +800,15 @@ function profile_user_record($userid, $onlyinuserobject = true) {
* @return array Array of field objects from database (indexed by id)
* @since Moodle 2.7.1
*/
-function profile_get_custom_fields($onlyinuserobject = false) {
- global $DB, $CFG;
-
- // Get all the fields.
- $fields = $DB->get_records('user_info_field', null, 'id ASC');
-
- // If only doing the user object ones, unset the rest.
- if ($onlyinuserobject) {
- foreach ($fields as $id => $field) {
- require_once($CFG->dirroot . '/user/profile/field/' .
- $field->datatype . '/field.class.php');
- $newfield = 'profile_field_' . $field->datatype;
- $formfield = new $newfield();
- if (!$formfield->is_user_object_data()) {
- unset($fields[$id]);
- }
+function profile_get_custom_fields(bool $onlyinuserobject = false): array {
+ $fieldobjects = profile_get_user_fields_with_data(0);
+ $fields = [];
+ foreach ($fieldobjects as $fieldobject) {
+ if (!$onlyinuserobject || $fieldobject->is_user_object_data()) {
+ $fields[$fieldobject->fieldid] = (object)$fieldobject->get_field_config_for_external();
}
}
-
- foreach ($fields as $index => $field) {
- $component = 'profilefield_' . $field->datatype;
- $classname = "\\$component\\helper";
- if (class_exists($classname) && method_exists($classname, 'get_fieldname')) {
- $fields[$index]->name = $classname::get_fieldname($field->name);
- }
- }
-
+ ksort($fields);
return $fields;
}
@@ -855,8 +830,10 @@ function profile_load_custom_fields($user) {
function profile_save_custom_fields($userid, $profilefields) {
global $DB;
- if ($fields = $DB->get_records('user_info_field')) {
- foreach ($fields as $field) {
+ $fields = profile_get_user_fields_with_data(0);
+ if ($fields) {
+ foreach ($fields as $fieldobject) {
+ $field = (object)$fieldobject->get_field_config_for_external();
if (isset($profilefields[$field->shortname])) {
$conditions = array('fieldid' => $field->id, 'userid' => $userid);
$id = $DB->get_field('user_info_data', 'id', $conditions);
@@ -877,26 +854,22 @@ function profile_save_custom_fields($userid, $profilefields) {
* current request for all fields so that it can be used quickly.
*
* @param string $shortname Shortname of custom profile field
- * @return array Array with id, name, and visible fields
+ * @return stdClass|null Object with properties id, shortname, name, visible, datatype, categoryid, etc
*/
-function profile_get_custom_field_data_by_shortname(string $shortname): array {
- global $DB;
-
+function profile_get_custom_field_data_by_shortname(string $shortname): ?stdClass {
$cache = \cache::make_from_params(cache_store::MODE_REQUEST, 'core_profile', 'customfields',
[], ['simplekeys' => true, 'simpledata' => true]);
$data = $cache->get($shortname);
- if (!$data) {
+ if ($data === false) {
// If we don't have data, we get and cache it for all fields to avoid multiple DB requests.
- $fields = $DB->get_records('user_info_field', null, '', 'id, shortname, name, visible');
+ $fields = profile_get_custom_fields();
+ $data = null;
foreach ($fields as $field) {
- $cache->set($field->shortname, (array)$field);
+ $cache->set($field->shortname, $field);
if ($field->shortname === $shortname) {
- $data = (array)$field;
+ $data = $field;
}
}
- if (!$data) {
- throw new \coding_exception('Unknown custom field: ' . $shortname);
- }
}
return $data;
@@ -946,15 +919,12 @@ function profile_view($user, $context, $course = null) {
* @return bool
*/
function profile_has_required_custom_fields_set($userid) {
- global $DB;
-
- $sql = "SELECT f.id
- FROM {user_info_field} f
- LEFT JOIN {user_info_data} d ON (d.fieldid = f.id AND d.userid = ?)
- WHERE f.required = 1 AND f.visible > 0 AND f.locked = 0 AND d.id IS NULL";
-
- if ($DB->record_exists_sql($sql, [$userid])) {
- return false;
+ $profilefields = profile_get_user_fields_with_data($userid);
+ foreach ($profilefields as $profilefield) {
+ if ($profilefield->is_required() && !$profilefield->is_locked() &&
+ $profilefield->is_empty() && $profilefield->get_field_config_for_external()['visible']) {
+ return false;
+ }
}
return true;
diff --git a/user/templates/edit_profile_fields.mustache b/user/templates/edit_profile_fields.mustache
new file mode 100644
index 00000000000..97faa9e4b8b
--- /dev/null
+++ b/user/templates/edit_profile_fields.mustache
@@ -0,0 +1,141 @@
+{{!
+ This file is part of Moodle - http://moodle.org/
+
+ Moodle is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Moodle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Moodle. If not, see .
+}}
+{{!
+ @template core_user/edit_profile_fields
+
+ UI for editing profile fields
+
+ Example context (json):
+ {
+ "baseurl": "index.php",
+ "sesskey": "12345",
+ "categories": [
+ {
+ "id": 1,
+ "name": "Cat1",
+ "fields": [
+ {"id": 1, "name": "Field1", "isfirst": true, "islast": false},
+ {"id": 2, "name": "Field2", "isfirst": false, "islast": false},
+ {"id": 3, "name": "Field3", "isfirst": false, "islast": true}
+ ],
+ "hasfields": true,
+ "isfirst": true,
+ "candelete": true
+ },
+ {
+ "id": 2,
+ "name": "Cat2",
+ "candelete": true
+ },
+ {
+ "id": 3,
+ "name": "Cat3",
+ "islast": true,
+ "candelete": true
+ }
+ ]
+ }
+}}
+
+
+
+
+{{#categories}}
+
+
+
+
+ {{#addfieldmenu}}{{> core/action_menu}}{{/addfieldmenu}}
+
+
+
+
+ {{#hasfields}}
+
+
+ {{#str}}profilefield, admin{{/str}} |
+ {{#str}}edit{{/str}} |
+
+
+
+ {{#fields}}
+
+
+ {{{name}}}
+ |
+
+
+ {{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
+
+ {{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}
+ {{^isfirst}}
+
+ {{#pix}}t/up, core, {{#str}}moveup{{/str}}{{/pix}}
+ {{/isfirst}}
+ {{#isfirst}}{{#pix}}spacer, moodle{{/pix}}{{/isfirst}}
+ {{^islast}}
+
+ {{#pix}}t/down, core, {{#str}}movedown{{/str}}{{/pix}}
+ {{/islast}}
+ {{#islast}}{{#pix}}spacer, moodle{{/pix}}{{/islast}}
+ |
+
+ {{/fields}}
+
+ {{/hasfields}}
+ {{^hasfields}}
+
+
+
+ {{#str}}profilenofieldsdefined, admin{{/str}}
+ |
+
+
+ {{/hasfields}}
+
+
+{{/categories}}
+
+
+{{#js}}
+ require(['core_user/edit_profile_fields'], function(s) {
+ s.init();
+ });
+{{/js}}
diff --git a/user/tests/behat/custom_profile_fields.feature b/user/tests/behat/custom_profile_fields.feature
index a17a063c470..31475fc59b7 100644
--- a/user/tests/behat/custom_profile_fields.feature
+++ b/user/tests/behat/custom_profile_fields.feature
@@ -17,7 +17,8 @@ Feature: Custom profile fields should be visible and editable by those with the
And I log in as "admin"
And I navigate to "Users > Accounts > User profile fields" in site administration
- And I set the field "datatype" to "Text input"
+ And I click on "Create a new profile field" "link"
+ And I click on "Text input" "link"
And I set the following fields to these values:
| Short name | notvisible_field |
| Name | notvisible_field |
@@ -25,7 +26,8 @@ Feature: Custom profile fields should be visible and editable by those with the
| Who is this field visible to? | Not visible |
And I click on "Save changes" "button"
- And I set the field "datatype" to "Text input"
+ And I click on "Create a new profile field" "link"
+ And I click on "Text input" "link"
And I set the following fields to these values:
| Short name | uservisible_field |
| Name | uservisible_field |
@@ -33,7 +35,8 @@ Feature: Custom profile fields should be visible and editable by those with the
| Who is this field visible to? | Visible to user |
And I click on "Save changes" "button"
- And I set the field "datatype" to "Text input"
+ And I click on "Create a new profile field" "link"
+ And I click on "Text input" "link"
And I set the following fields to these values:
| Short name | everyonevisible_field |
| Name | everyonevisible_field |
@@ -41,7 +44,8 @@ Feature: Custom profile fields should be visible and editable by those with the
| Who is this field visible to? | Visible to everyone |
And I click on "Save changes" "button"
- And I set the field "datatype" to "Text input"
+ And I click on "Create a new profile field" "link"
+ And I click on "Text input" "link"
And I set the following fields to these values:
| Short name | teachervisible_field |
| Name | teachervisible_field |
diff --git a/user/tests/profilelib_test.php b/user/tests/profilelib_test.php
index d598a1d4b4f..77da39879f1 100644
--- a/user/tests/profilelib_test.php
+++ b/user/tests/profilelib_test.php
@@ -39,16 +39,16 @@ class core_user_profilelib_testcase extends advanced_testcase {
* with profile_user_record.
*/
public function test_get_custom_fields() {
- global $DB, $CFG;
+ global $CFG;
require_once($CFG->dirroot . '/user/profile/lib.php');
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
// Add a custom field of textarea type.
- $id1 = $DB->insert_record('user_info_field', array(
- 'shortname' => 'frogdesc', 'name' => 'Description of frog', 'categoryid' => 1,
- 'datatype' => 'textarea'));
+ $id1 = $this->getDataGenerator()->create_custom_profile_field([
+ 'shortname' => 'frogdesc', 'name' => 'Description of frog',
+ 'datatype' => 'textarea'])->id;
// Check the field is returned.
$result = profile_get_custom_fields();
@@ -66,9 +66,9 @@ class core_user_profilelib_testcase extends advanced_testcase {
$this->assertObjectHasAttribute('frogdesc', profile_user_record($user->id, false));
// Add another custom field, this time of normal text type.
- $id2 = $DB->insert_record('user_info_field', array(
- 'shortname' => 'frogname', 'name' => 'Name of frog', 'categoryid' => 1,
- 'datatype' => 'text'));
+ $id2 = $this->getDataGenerator()->create_custom_profile_field(array(
+ 'shortname' => 'frogname', 'name' => 'Name of frog',
+ 'datatype' => 'text'))->id;
// Check both are returned using normal option.
$result = profile_get_custom_fields();
@@ -147,26 +147,26 @@ class core_user_profilelib_testcase extends advanced_testcase {
* Test that {@link user_not_fully_set_up()} takes required custom fields into account.
*/
public function test_profile_has_required_custom_fields_set() {
- global $CFG, $DB;
+ global $CFG;
require_once($CFG->dirroot.'/mnet/lib.php');
$this->resetAfterTest();
// Add a required, visible, unlocked custom field.
- $DB->insert_record('user_info_field', ['shortname' => 'house', 'name' => 'House', 'required' => 1,
- 'visible' => 1, 'locked' => 0, 'categoryid' => 1, 'datatype' => 'text']);
+ $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'house', 'name' => 'House', 'required' => 1,
+ 'visible' => 1, 'locked' => 0, 'datatype' => 'text']);
// Add an optional, visible, unlocked custom field.
- $DB->insert_record('user_info_field', ['shortname' => 'pet', 'name' => 'Pet', 'required' => 0,
- 'visible' => 1, 'locked' => 0, 'categoryid' => 1, 'datatype' => 'text']);
+ $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'pet', 'name' => 'Pet', 'required' => 0,
+ 'visible' => 1, 'locked' => 0, 'datatype' => 'text']);
// Add required but invisible custom field.
- $DB->insert_record('user_info_field', ['shortname' => 'secretid', 'name' => 'Secret ID', 'required' => 1,
- 'visible' => 0, 'locked' => 0, 'categoryid' => 1, 'datatype' => 'text']);
+ $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'secretid', 'name' => 'Secret ID',
+ 'required' => 1, 'visible' => 0, 'locked' => 0, 'datatype' => 'text']);
// Add required but locked custom field.
- $DB->insert_record('user_info_field', ['shortname' => 'muggleborn', 'name' => 'Muggle-born', 'required' => 1,
- 'visible' => 1, 'locked' => 1, 'categoryid' => 1, 'datatype' => 'checkbox']);
+ $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'muggleborn', 'name' => 'Muggle-born',
+ 'required' => 1, 'visible' => 1, 'locked' => 1, 'datatype' => 'checkbox']);
// Create some student accounts.
$hermione = $this->getDataGenerator()->create_user();
@@ -215,14 +215,14 @@ class core_user_profilelib_testcase extends advanced_testcase {
* Test that user generator sets the custom profile fields
*/
public function test_profile_fields_in_generator() {
- global $CFG, $DB;
+ global $CFG;
require_once($CFG->dirroot.'/mnet/lib.php');
$this->resetAfterTest();
// Add a required, visible, unlocked custom field.
- $DB->insert_record('user_info_field', ['shortname' => 'house', 'name' => 'House', 'required' => 1,
- 'visible' => 1, 'locked' => 0, 'categoryid' => 1, 'datatype' => 'text']);
+ $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'house', 'name' => 'House', 'required' => 1,
+ 'visible' => 1, 'locked' => 0, 'datatype' => 'text', 'defaultdata' => null]);
// Create some student accounts.
$hermione = $this->getDataGenerator()->create_user(['profile_field_house' => 'Gryffindor']);
@@ -261,17 +261,17 @@ class core_user_profilelib_testcase extends advanced_testcase {
// Get the first field data and check it is correct.
$data = profile_get_custom_field_data_by_shortname('speciality');
- $this->assertEquals('Speciality', $data['name']);
- $this->assertEquals(PROFILE_VISIBLE_ALL, $data['visible']);
- $this->assertEquals($field1->id, $data['id']);
+ $this->assertEquals('Speciality', $data->name);
+ $this->assertEquals(PROFILE_VISIBLE_ALL, $data->visible);
+ $this->assertEquals($field1->id, $data->id);
// Get the second field data, checking there is no database query this time.
$before = $DB->perf_get_queries();
$data = profile_get_custom_field_data_by_shortname('veggie');
$this->assertEquals($before, $DB->perf_get_queries());
- $this->assertEquals('Vegetarian', $data['name']);
- $this->assertEquals(PROFILE_VISIBLE_PRIVATE, $data['visible']);
- $this->assertEquals($field2->id, $data['id']);
+ $this->assertEquals('Vegetarian', $data->name);
+ $this->assertEquals(PROFILE_VISIBLE_PRIVATE, $data->visible);
+ $this->assertEquals($field2->id, $data->id);
}
/**
@@ -281,7 +281,6 @@ class core_user_profilelib_testcase extends advanced_testcase {
global $CFG;
require_once($CFG->dirroot . '/user/profile/lib.php');
- $this->expectExceptionMessage('Unknown custom field: speciality');
- profile_get_custom_field_data_by_shortname('speciality');
+ $this->assertNull(profile_get_custom_field_data_by_shortname('speciality'));
}
}