diff --git a/availability/condition/profile/classes/condition.php b/availability/condition/profile/classes/condition.php index 4d22e4e507c..27e92352853 100644 --- a/availability/condition/profile/classes/condition.php +++ b/availability/condition/profile/classes/condition.php @@ -292,14 +292,23 @@ class condition extends \core_availability\condition { * Gets data about custom profile fields. Cached statically in current * request. * + * This only includes fields which can be tested by the system (those whose + * data is cached in $USER object) - basically doesn't include textarea type + * fields. + * * @return array Array of records indexed by shortname */ public static function get_custom_profile_fields() { - global $DB; + global $DB, $CFG; if (self::$customprofilefields === null) { - self::$customprofilefields = $DB->get_records('user_info_field', null, - 'id ASC', 'shortname, id, name, defaultdata'); + // Get fields and store them indexed by shortname. + require_once($CFG->dirroot . '/user/profile/lib.php'); + $fields = profile_get_custom_fields(true); + self::$customprofilefields = array(); + foreach ($fields as $field) { + self::$customprofilefields[$field->shortname] = $field; + } } return self::$customprofilefields; } diff --git a/availability/condition/profile/tests/condition_test.php b/availability/condition/profile/tests/condition_test.php index d81d9518667..8b2619adc74 100644 --- a/availability/condition/profile/tests/condition_test.php +++ b/availability/condition/profile/tests/condition_test.php @@ -317,6 +317,29 @@ class availability_profile_condition_testcase extends advanced_testcase { $this->assertTrue($cond->is_available(false, $info, true, $user->id)); } + /** + * Tests what happens with custom fields that are text areas. These should + * not be offered in the menu because their data is not included in user + * object + */ + public function test_custom_textarea_field() { + global $USER, $SITE, $DB; + $this->setAdminUser(); + $info = new \core_availability\mock_info(); + + // Add custom textarea type. + $DB->insert_record('user_info_field', array( + 'shortname' => 'longtext', 'name' => 'Long text', 'categoryid' => 1, + '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. + $fields = condition::get_custom_profile_fields(); + $this->assertEquals(array('frogtype'), array_keys($fields)); + } + /** * Sets the custom profile field used for testing. * diff --git a/user/profile/lib.php b/user/profile/lib.php index d8b93b7837a..5a040aa609d 100644 --- a/user/profile/lib.php +++ b/user/profile/lib.php @@ -572,6 +572,42 @@ function profile_user_record($userid) { return $usercustomfields; } +/** + * Obtains a list of all available custom profile fields, indexed by id. + * + * Some profile fields are not included in the user object data (see + * profile_user_record function above). Optionally, you can obtain only those + * fields that are included in the user object. + * + * To be clear, this function returns the available fields, and does not + * return the field values for a particular user. + * + * @param bool $onlyinuserobject True if you only want the ones in $USER + * @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]); + } + } + } + + return $fields; +} + /** * Load custom profile fields into user object * diff --git a/user/profile/tests/profilelib_test.php b/user/profile/tests/profilelib_test.php new file mode 100644 index 00000000000..ad4e2887732 --- /dev/null +++ b/user/profile/tests/profilelib_test.php @@ -0,0 +1,88 @@ +. + +/** + * Unit tests for user/profile/lib.php. + * + * @package core_user + * @copyright 2014 The Open University + * @licensehttp://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/user/profile/lib.php'); + +/** + * Unit tests for user/profile/lib.php. + * + * @package core_user + * @copyright 2014 The Open University + * @licensehttp://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_user_profilelib_testcase extends advanced_testcase { + /** + * Tests profile_get_custom_fields function and checks it is consistent + * with profile_user_record. + */ + public function test_get_custom_fields() { + global $DB; + + $this->resetAfterTest(); + $user = $this->getDataGenerator()->create_user(); + + // Check function with no custom fields. + $this->assertEquals(array(), profile_get_custom_fields()); + + // Check that profile_user_record returns same (no) fields. + $this->assertEquals(array(), array_keys((array)profile_user_record($user->id))); + + // 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')); + + // Check the field is returned. + $result = profile_get_custom_fields(); + $this->assertEquals(array($id1), array_keys($result)); + $this->assertEquals('frogdesc', $result[$id1]->shortname); + + // Textarea types are not included in user data though, so if we + // use the 'only in user data' parameter, there is still nothing. + $this->assertEquals(array(), profile_get_custom_fields(true)); + + // Check that profile_user_record returns same (no) fields. + $this->assertEquals(array(), array_keys((array)profile_user_record($user->id))); + + // 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')); + + // Check both are returned using normal option. + $result = profile_get_custom_fields(); + $this->assertEquals(array($id1, $id2), array_keys($result)); + $this->assertEquals('frogname', $result[$id2]->shortname); + + // And check that only the one is returned the other way. + $result = profile_get_custom_fields(true); + $this->assertEquals(array($id2), array_keys($result)); + + // Check profile_user_record returns same field. + $this->assertEquals(array('frogname'), array_keys((array)profile_user_record($user->id))); + } +}