From 76807203a3abeab65feb4755228b6a1a012853e0 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Thu, 23 Mar 2023 18:00:46 +0100 Subject: [PATCH] MDL-77726 user: Fix custom user profiles supporting filtering in WS --- user/externallib.php | 4 ++- user/lib.php | 20 +++++---------- user/profile/field/menu/field.class.php | 18 +++++++++++++ user/tests/externallib_test.php | 34 ++++++++++++++++++++----- user/upgrade.txt | 4 +++ 5 files changed, 60 insertions(+), 20 deletions(-) diff --git a/user/externallib.php b/user/externallib.php index 9a58d1103da..a6b1f47745b 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -1149,7 +1149,9 @@ class core_user_external extends \core_external\external_api { new external_single_structure( array( 'type' => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'), - 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), + 'value' => new external_value(PARAM_RAW, 'The value of the custom field (as stored in the database)'), + 'displayvalue' => new external_value(PARAM_RAW, 'The value of the custom field for display', + VALUE_OPTIONAL), 'name' => new external_value(PARAM_RAW, 'The name of the custom field'), 'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'), ) diff --git a/user/lib.php b/user/lib.php index a2022b462c1..2ab18a227cd 100644 --- a/user/lib.php +++ b/user/lib.php @@ -361,19 +361,13 @@ function user_get_user_details($user, $course = null, array $userfields = array( foreach ($fields as $formfield) { if ($formfield->is_visible() and !$formfield->is_empty()) { - // TODO: Part of MDL-50728, this conditional coding must be moved to - // proper profile fields API so they are self-contained. - // We only use display_data in fields that require text formatting. - if ($formfield->field->datatype == 'text' or $formfield->field->datatype == 'textarea') { - $fieldvalue = $formfield->display_data(); - } else { - // Cases: datetime, checkbox and menu. - $fieldvalue = $formfield->data; - } - - $userdetails['customfields'][] = - array('name' => $formfield->field->name, 'value' => $fieldvalue, - 'type' => $formfield->field->datatype, 'shortname' => $formfield->field->shortname); + $userdetails['customfields'][] = [ + 'name' => $formfield->field->name, + 'value' => $formfield->data, + 'displayvalue' => $formfield->display_data(), + 'type' => $formfield->field->datatype, + 'shortname' => $formfield->field->shortname + ]; } } } diff --git a/user/profile/field/menu/field.class.php b/user/profile/field/menu/field.class.php index a304cc4102a..061c791440c 100644 --- a/user/profile/field/menu/field.class.php +++ b/user/profile/field/menu/field.class.php @@ -168,6 +168,24 @@ class profile_field_menu extends profile_field_base { public function get_field_properties() { return array(PARAM_TEXT, NULL_NOT_ALLOWED); } + + /** + * Return the field settings suitable to be exported via an external function. + * + * @return array all the settings + */ + public function get_field_config_for_external() { + + if (isset($this->field->param1) && !empty($this->options)) { + // Remove "Choose" option to make it consisten with the rest of the data. + if (!empty($this->field->required)) { + unset($this->options['']); + } + $this->field->param2 = implode("\n", array_values($this->options)); + } + + return (array) $this->field; + } } diff --git a/user/tests/externallib_test.php b/user/tests/externallib_test.php index 387bca93f6a..c75827a8781 100644 --- a/user/tests/externallib_test.php +++ b/user/tests/externallib_test.php @@ -184,7 +184,20 @@ class externallib_test extends externallib_advanced_testcase { $this->resetAfterTest(true); - $course = self::getDataGenerator()->create_course(); + $generator = self::getDataGenerator(); + + // Create complex user profile field supporting multi-lang. + filter_set_global_state('multilang', TEXTFILTER_ON); + $statuses = 'UE\nSE\nOtherOtro'; + $generator->create_custom_profile_field( + [ + 'datatype' => 'menu', + 'shortname' => 'employmentstatus', 'name' => 'Employment status', + 'param1' => $statuses + ] + ); + + $course = $generator->create_course(); $user1 = array( 'username' => 'usernametest1', 'idnumber' => 'idnumbertest1', @@ -200,14 +213,16 @@ class externallib_test extends externallib_advanced_testcase { 'descriptionformat' => FORMAT_MOODLE, 'city' => 'Perth', 'country' => 'AU', + 'profile_field_jobposition' => 'Manager', + 'profile_field_employmentstatus' => explode('\n', $statuses)[2], ); - $user1 = self::getDataGenerator()->create_user($user1); + $user1 = $generator->create_user($user1); if (!empty($CFG->usetags)) { require_once($CFG->dirroot . '/user/editlib.php'); $user1->interests = array('Cinema', 'Tennis', 'Dance', 'Guitar', 'Cooking'); useredit_update_interests($user1, $user1->interests); } - $user2 = self::getDataGenerator()->create_user( + $user2 = $generator->create_user( array('username' => 'usernametest2', 'idnumber' => 'idnumbertest2')); $generatedusers = array(); @@ -218,9 +233,9 @@ class externallib_test extends externallib_advanced_testcase { $roleid = $this->assignUserCapability('moodle/user:viewdetails', $context->id); // Enrol the users in the course. - $this->getDataGenerator()->enrol_user($user1->id, $course->id, $roleid, 'manual'); - $this->getDataGenerator()->enrol_user($user2->id, $course->id, $roleid, 'manual'); - $this->getDataGenerator()->enrol_user($USER->id, $course->id, $roleid, 'manual'); + $generator->enrol_user($user1->id, $course->id, $roleid, 'manual'); + $generator->enrol_user($user2->id, $course->id, $roleid, 'manual'); + $generator->enrol_user($USER->id, $course->id, $roleid, 'manual'); // call as admin and receive all possible fields. $this->setAdminUser(); @@ -290,6 +305,13 @@ class externallib_test extends externallib_advanced_testcase { // Default language and no theme were used for the user. $this->assertEquals($CFG->lang, $returneduser['lang']); $this->assertEmpty($returneduser['theme']); + + if ($returneduser['id'] == $user1->id) { + $this->assertCount(1, $returneduser['customfields']); + $dbvalue = explode('\n', $statuses)[2]; + $this->assertEquals($dbvalue, $returneduser['customfields'][0]['value']); + $this->assertEquals('Other', $returneduser['customfields'][0]['displayvalue']); + } } } diff --git a/user/upgrade.txt b/user/upgrade.txt index 609451b6456..b1f5ca91960 100644 --- a/user/upgrade.txt +++ b/user/upgrade.txt @@ -14,6 +14,10 @@ This files describes API changes for code that uses the user API. * New method `core_user::is_current_user`, useful for components implementing permission callbacks for their preferences * New `profile_get_user_field` method for returning profile field instance of given type * The `profile_field_base::is_visible` method now accepts an optional `$context` argument +* The `customfields` structure used for returning user profile fields information has been updated to: + * Return in the field `value` the value of the custom field (as stored in the database) + * Return in the field `displayvalue` the value of the custom field for display + External systems displaying user information should always use `displayvalue === 4.1 ===