mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
Merge branch 'MDL-71051-master-2' of git://github.com/marinaglancy/moodle
This commit is contained in:
commit
d4673e3047
@ -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 . ' *';
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 |
|
||||
|
@ -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';
|
||||
|
@ -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
|
||||
|
@ -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');
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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 |
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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']);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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).<br />Do you still wish to delete this category?';
|
||||
$string['profileconfirmfielddeletion'] = 'There is/are {$a} user record/s for this field which will be deleted.<br />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';
|
||||
|
@ -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) {
|
||||
|
@ -1289,7 +1289,7 @@ EOD;
|
||||
'defaultdata' => 0
|
||||
]
|
||||
];
|
||||
foreach ($typedefaults[$data['datatype']] as $field => $value) {
|
||||
foreach ($typedefaults[$data['datatype']] ?? [] as $field => $value) {
|
||||
$defaults[$field] = $value;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
|
2
user/amd/build/edit_profile_fields.min.js
vendored
Normal file
2
user/amd/build/edit_profile_fields.min.js
vendored
Normal file
@ -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
|
1
user/amd/build/edit_profile_fields.min.js.map
Normal file
1
user/amd/build/edit_profile_fields.min.js.map
Normal file
File diff suppressed because one or more lines are too long
80
user/amd/src/edit_profile_fields.js
Normal file
80
user/amd/src/edit_profile_fields.js
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
};
|
@ -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.
|
||||
|
125
user/classes/form/profile_category_form.php
Normal file
125
user/classes/form/profile_category_form.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
183
user/classes/form/profile_field_form.php
Normal file
183
user/classes/form/profile_field_form.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 '<hr />';
|
||||
echo '<div class="profileeditor">';
|
||||
|
||||
// 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 '</div>';
|
||||
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 = '<a title="'.$stredit.'" href="index.php?id='.$category->id.'&action=editcategory">' .
|
||||
$OUTPUT->pix_icon('t/edit', $stredit) .'</a> ';
|
||||
|
||||
// Delete.
|
||||
// Can only delete the last category if there are no fields in it.
|
||||
if (($categorycount > 1) or ($fieldcount == 0)) {
|
||||
$editstr .= '<a title="'.$strdelete.'"';
|
||||
$editstr .= ' href="index.php?id='.$category->id.'&action=deletecategory&sesskey='.sesskey() . '">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/delete', $strdelete).'</a> ';
|
||||
} else {
|
||||
$editstr .= $OUTPUT->spacer() . ' ';
|
||||
}
|
||||
|
||||
// Move up.
|
||||
if ($category->sortorder > 1) {
|
||||
$editstr .= '<a title="'.$strmoveup.'" ';
|
||||
$editstr .= ' href="index.php?id='.$category->id.'&action=movecategory&dir=up&sesskey='.sesskey().'">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/up', $strmoveup) . '</a> ';
|
||||
} else {
|
||||
$editstr .= $OUTPUT->spacer() . ' ';
|
||||
}
|
||||
|
||||
// Move down.
|
||||
if ($category->sortorder < $categorycount) {
|
||||
$editstr .= '<a title="'.$strmovedown.'" ';
|
||||
$editstr .= ' href="index.php?id='.$category->id.'&action=movecategory&dir=down&sesskey='.sesskey().'">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/down', $strmovedown) . '</a> ';
|
||||
} 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 = '<a title="'.$stredit.'" href="index.php?id='.$field->id.'&action=editfield">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/edit', $stredit) . '</a> ';
|
||||
|
||||
// Delete.
|
||||
$editstr .= '<a title="'.$strdelete.'" href="index.php?id='.$field->id.'&action=deletefield&sesskey='.sesskey().'">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/delete', $strdelete) . '</a> ';
|
||||
|
||||
// Move up.
|
||||
if ($field->sortorder > 1) {
|
||||
$editstr .= '<a title="'.$strmoveup.'" ';
|
||||
$editstr .= ' href="index.php?id='.$field->id.'&action=movefield&dir=up&sesskey='.sesskey().'">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/up', $strmoveup) . '</a> ';
|
||||
} else {
|
||||
$editstr .= $OUTPUT->spacer() . ' ';
|
||||
}
|
||||
|
||||
// Move down.
|
||||
if ($field->sortorder < $fieldcount) {
|
||||
$editstr .= '<a title="'.$strmovedown.'" ';
|
||||
$editstr .= ' href="index.php?id='.$field->id.'&action=movefield&dir=down&sesskey='.sesskey().'">';
|
||||
$editstr .= $OUTPUT->pix_icon('t/down', $strmovedown) . '</a> ';
|
||||
} else {
|
||||
$editstr .= $OUTPUT->spacer() . ' ';
|
||||
}
|
||||
|
||||
return $editstr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,95 +0,0 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,100 +0,0 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
141
user/templates/edit_profile_fields.mustache
Normal file
141
user/templates/edit_profile_fields.mustache
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@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
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
<div class="row profileeditor">
|
||||
<div class="col align-self-end">
|
||||
<a tabindex="0" role="button" class="btn btn-secondary float-right" data-action="editcategory">{{#str}}profilecreatecategory, admin{{/str}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="categorieslist">
|
||||
{{#categories}}
|
||||
<div data-category-id="{{id}}" id="category-{{id}}" class="mt-2">
|
||||
<div class="row justify-content-between align-items-end">
|
||||
<div class="col-6 categoryinstance">
|
||||
<h3>
|
||||
{{{name}}}
|
||||
<a href="#" data-action="editcategory" data-id="{{id}}" data-name="{{name}}">
|
||||
{{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}</a>
|
||||
{{#candelete}}
|
||||
<a href="{{baseurl}}?action=deletecategory&id={{id}}&sesskey={{sesskey}}">
|
||||
{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}</a>
|
||||
{{/candelete}}
|
||||
{{^isfirst}}
|
||||
<a href="{{baseurl}}?id={{id}}&action=movecategory&dir=up&sesskey={{sesskey}}">
|
||||
{{#pix}}t/up, core, {{#str}}moveup{{/str}}{{/pix}}</a>
|
||||
{{/isfirst}}
|
||||
{{#isfirst}}{{#pix}}spacer, moodle{{/pix}}{{/isfirst}}
|
||||
{{^islast}}
|
||||
<a href="{{baseurl}}?id={{id}}&action=movecategory&dir=down&sesskey={{sesskey}}">
|
||||
{{#pix}}t/down, core, {{#str}}movedown{{/str}}{{/pix}}</a>
|
||||
{{/islast}}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
{{#addfieldmenu}}{{> core/action_menu}}{{/addfieldmenu}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="generaltable fullwidth profilefield">
|
||||
{{#hasfields}}
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="col-8">{{#str}}profilefield, admin{{/str}}</th>
|
||||
<th scope="col" class="col-3 text-right">{{#str}}edit{{/str}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#fields}}
|
||||
<tr>
|
||||
<td class="col-8">
|
||||
{{{name}}}
|
||||
</td>
|
||||
<td class="col-3 text-right">
|
||||
<a href="#" data-action="editfield" data-id="{{id}}" data-name="{{name}}">
|
||||
{{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}</a>
|
||||
<a href="{{baseurl}}?action=deletefield&id={{id}}&sesskey={{sesskey}}">
|
||||
{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}</a>
|
||||
{{^isfirst}}
|
||||
<a href="{{baseurl}}?id={{id}}&action=movefield&dir=up&sesskey={{sesskey}}">
|
||||
{{#pix}}t/up, core, {{#str}}moveup{{/str}}{{/pix}}</a>
|
||||
{{/isfirst}}
|
||||
{{#isfirst}}{{#pix}}spacer, moodle{{/pix}}{{/isfirst}}
|
||||
{{^islast}}
|
||||
<a href="{{baseurl}}?id={{id}}&action=movefield&dir=down&sesskey={{sesskey}}">
|
||||
{{#pix}}t/down, core, {{#str}}movedown{{/str}}{{/pix}}</a>
|
||||
{{/islast}}
|
||||
{{#islast}}{{#pix}}spacer, moodle{{/pix}}{{/islast}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/fields}}
|
||||
</tbody>
|
||||
{{/hasfields}}
|
||||
{{^hasfields}}
|
||||
<thead>
|
||||
<tr class="nofields alert alert-danger alert-block fade in">
|
||||
<td>
|
||||
{{#str}}profilenofieldsdefined, admin{{/str}}
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
{{/hasfields}}
|
||||
</table>
|
||||
</div>
|
||||
{{/categories}}
|
||||
</div>
|
||||
|
||||
{{#js}}
|
||||
require(['core_user/edit_profile_fields'], function(s) {
|
||||
s.init();
|
||||
});
|
||||
{{/js}}
|
@ -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 |
|
||||
|
@ -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'));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user