From 4ce0931462ae6b12b95175bcb9ab9e02d64f223e Mon Sep 17 00:00:00 2001 From: Simey Lameze Date: Mon, 11 Apr 2016 12:08:47 +0800 Subject: [PATCH] MDL-52781 core_user: improve core_user::fill_properties_cache() --- lang/en/error.php | 1 + lib/classes/user.php | 308 +++++++++++++++++++++++++++++++++------- lib/db/upgrade.php | 6 + lib/tests/user_test.php | 203 ++++++++++++++++++++++++++ 4 files changed, 463 insertions(+), 55 deletions(-) diff --git a/lang/en/error.php b/lang/en/error.php index 092ec783cf4..5400fd71fa6 100644 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -352,6 +352,7 @@ $string['invalidurl'] = 'Invalid URL'; $string['invaliduser'] = 'Invalid user'; $string['invaliduserid'] = 'Invalid user id'; $string['invaliduserfield'] = 'Invalid user field: {$a}'; +$string['invaliduserdata'] = 'Invalid user data: {$a}'; $string['invalidusername'] = 'The given username contains invalid characters'; $string['invalidxmlfile'] = '"{$a}" is not a valid XML file'; $string['iplookupfailed'] = 'Cannot find geo information about this IP address {$a}'; diff --git a/lib/classes/user.php b/lib/classes/user.php index 07c1faf302b..e902ab3c73d 100644 --- a/lib/classes/user.php +++ b/lib/classes/user.php @@ -281,10 +281,21 @@ class core_user { /** * Definition of user profile fields and the expected parameter type for data validation. * + * array( + * 'property_name' => array( // The user property to be checked. Should match the field on the user table. + * 'null' => NULL_ALLOWED, // Defaults to NULL_NOT_ALLOWED. Takes NULL_NOT_ALLOWED or NULL_ALLOWED. + * 'type' => PARAM_TYPE, // Expected parameter type of the user field. + * 'choices' => array(1, 2..) // An array of accepted values of the user field. + * 'default' => $CFG->setting // An default value for the field. + * ) + * ) + * + * The fields choices and default are optional. + * * @return void */ protected static function fill_properties_cache() { - + global $CFG; if (self::$propertiescache !== null) { return; } @@ -292,60 +303,70 @@ class core_user { // Array of user fields properties and expected parameters. // Every new field on the user table should be added here otherwise it won't be validated. $fields = array(); - $fields['id'] = array('type' => PARAM_INT); - $fields['auth'] = array('type' => PARAM_NOTAGS); - $fields['confirmed'] = array('type' => PARAM_BOOL); - $fields['policyagreed'] = array('type' => PARAM_BOOL); - $fields['deleted'] = array('type' => PARAM_BOOL); - $fields['suspended'] = array('type' => PARAM_BOOL); - $fields['mnethostid'] = array('type' => PARAM_BOOL); - $fields['username'] = array('type' => PARAM_USERNAME); - $fields['password'] = array('type' => PARAM_NOTAGS); - $fields['idnumber'] = array('type' => PARAM_NOTAGS); - $fields['firstname'] = array('type' => PARAM_NOTAGS); - $fields['lastname'] = array('type' => PARAM_NOTAGS); - $fields['surname'] = array('type' => PARAM_NOTAGS); - $fields['email'] = array('type' => PARAM_RAW_TRIMMED); - $fields['emailstop'] = array('type' => PARAM_INT); - $fields['icq'] = array('type' => PARAM_NOTAGS); - $fields['skype'] = array('type' => PARAM_NOTAGS); - $fields['aim'] = array('type' => PARAM_NOTAGS); - $fields['yahoo'] = array('type' => PARAM_NOTAGS); - $fields['msn'] = array('type' => PARAM_NOTAGS); - $fields['phone1'] = array('type' => PARAM_NOTAGS); - $fields['phone2'] = array('type' => PARAM_NOTAGS); - $fields['institution'] = array('type' => PARAM_TEXT); - $fields['department'] = array('type' => PARAM_TEXT); - $fields['address'] = array('type' => PARAM_TEXT); - $fields['city'] = array('type' => PARAM_TEXT); - $fields['country'] = array('type' => PARAM_TEXT); - $fields['lang'] = array('type' => PARAM_TEXT); - $fields['calendartype'] = array('type' => PARAM_NOTAGS); - $fields['theme'] = array('type' => PARAM_NOTAGS); - $fields['timezones'] = array('type' => PARAM_TEXT); - $fields['firstaccess'] = array('type' => PARAM_INT); - $fields['lastaccess'] = array('type' => PARAM_INT); - $fields['lastlogin'] = array('type' => PARAM_INT); - $fields['currentlogin'] = array('type' => PARAM_INT); - $fields['lastip'] = array('type' => PARAM_NOTAGS); - $fields['secret'] = array('type' => PARAM_TEXT); - $fields['picture'] = array('type' => PARAM_INT); - $fields['url'] = array('type' => PARAM_URL); - $fields['description'] = array('type' => PARAM_CLEANHTML); - $fields['descriptionformat'] = array('type' => PARAM_INT); - $fields['mailformat'] = array('type' => PARAM_INT); - $fields['maildigest'] = array('type' => PARAM_INT); - $fields['maildisplay'] = array('type' => PARAM_INT); - $fields['autosubscribe'] = array('type' => PARAM_INT); - $fields['trackforums'] = array('type' => PARAM_INT); - $fields['timecreated'] = array('type' => PARAM_INT); - $fields['timemodified'] = array('type' => PARAM_INT); - $fields['trustbitmask'] = array('type' => PARAM_INT); - $fields['imagealt'] = array('type' => PARAM_TEXT); - $fields['lastnamephonetic'] = array('type' => PARAM_NOTAGS); - $fields['firstnamephonetic'] = array('type' => PARAM_NOTAGS); - $fields['middlename'] = array('type' => PARAM_NOTAGS); - $fields['alternatename'] = array('type' => PARAM_NOTAGS); + $fields['id'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['auth'] = array('type' => PARAM_AUTH, 'null' => NULL_NOT_ALLOWED); + $fields['confirmed'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); + $fields['policyagreed'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); + $fields['deleted'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); + $fields['suspended'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); + $fields['mnethostid'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['username'] = array('type' => PARAM_USERNAME, 'null' => NULL_NOT_ALLOWED); + $fields['password'] = array('type' => PARAM_RAW, 'null' => NULL_NOT_ALLOWED); + $fields['idnumber'] = array('type' => PARAM_RAW, 'null' => NULL_NOT_ALLOWED); + $fields['firstname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['lastname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['surname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['email'] = array('type' => PARAM_RAW_TRIMMED, 'null' => NULL_NOT_ALLOWED); + $fields['emailstop'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['icq'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['skype'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); + $fields['aim'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['yahoo'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['msn'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['phone1'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['phone2'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['institution'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); + $fields['department'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); + $fields['address'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); + $fields['city'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultcity); + $fields['country'] = array('type' => PARAM_ALPHA, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->country, + 'choices' => array_merge(array('' => ''), get_string_manager()->get_list_of_countries(true, true))); + $fields['lang'] = array('type' => PARAM_LANG, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->lang, + 'choices' => array_merge(array('' => ''), get_string_manager()->get_list_of_languages())); + $fields['calendartype'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->calendartype, + 'choices' => array_merge(array('' => ''), \core_calendar\type_factory::get_list_of_calendar_types())); + $fields['theme'] = array('type' => PARAM_THEME, 'null' => NULL_NOT_ALLOWED, + 'default' => theme_config::DEFAULT_THEME, 'choices' => array_merge(array('' => ''), get_list_of_themes())); + $fields['timezone'] = array('type' => PARAM_TIMEZONE, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->timezone, + 'choices' => core_date::get_list_of_timezones(null, true)); + $fields['firstaccess'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['lastaccess'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['lastlogin'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['currentlogin'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['lastip'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); + $fields['secret'] = array('type' => PARAM_RAW, 'null' => NULL_NOT_ALLOWED); + $fields['picture'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['url'] = array('type' => PARAM_URL, 'null' => NULL_NOT_ALLOWED); + $fields['description'] = array('type' => PARAM_RAW, 'null' => NULL_ALLOWED); + $fields['descriptionformat'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['mailformat'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, + 'default' => $CFG->defaultpreference_mailformat); + $fields['maildigest'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, + 'default' => $CFG->defaultpreference_maildigest); + $fields['maildisplay'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, + 'default' => $CFG->defaultpreference_maildisplay); + $fields['autosubscribe'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, + 'default' => $CFG->defaultpreference_autosubscribe); + $fields['trackforums'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, + 'default' => $CFG->defaultpreference_trackforums); + $fields['timecreated'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['timemodified'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['trustbitmask'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); + $fields['imagealt'] = array('type' => PARAM_TEXT, 'null' => NULL_ALLOWED); + $fields['lastnamephonetic'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); + $fields['firstnamephonetic'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); + $fields['middlename'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); + $fields['alternatename'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); self::$propertiescache = $fields; } @@ -368,6 +389,38 @@ class core_user { return self::$propertiescache[$property]; } + /** + * Validate user data. + * + * This method just validates each user field and return an array of errors. It doesn't clean the data, + * the methods clean() and clean_field() should be used for this purpose. + * + * @param stdClass|array $data user data object or array to be validated. + * @return array|true $errors array of errors found on the user object, true if the validation passed. + */ + public static function validate($data) { + // Get all user profile fields definition. + self::fill_properties_cache(); + + foreach ($data as $property => $value) { + try { + if (isset(self::$propertiescache[$property])) { + validate_param($value, self::$propertiescache[$property]['type'], self::$propertiescache[$property]['null']); + } + // Check that the value is part of a list of allowed values. + if (!empty(self::$propertiescache[$property]['choices']) && + !isset(self::$propertiescache[$property]['choices'][$data->$property]) && + !array_key_exists($data->$property, self::$propertiescache[$property]['choices'])) { + throw new invalid_parameter_exception($value); + } + } catch (invalid_parameter_exception $e) { + $errors[$property] = $e->getMessage(); + } + } + + return empty($errors) ? true : $errors; + } + /** * Clean the properties cache. * @@ -377,4 +430,149 @@ class core_user { public static function reset_caches() { self::$propertiescache = null; } + + /** + * Clean the user data. + * + * @param stdClass|array $user the user data to be validated against properties definition. + * @return stdClass $user the cleaned user data. + */ + public static function clean_data($user) { + if (empty($user)) { + return $user; + } + + foreach ($user as $field => $value) { + // Get the property parameter type and do the cleaning. + try { + if (isset(self::$propertiescache[$field]['choices'])) { + if (!array_key_exists($value, self::$propertiescache[$field]['choices'])) { + if (isset(self::$propertiescache[$field]['default'])) { + $user->$field = self::$propertiescache[$field]['default']; + } else { + $user->$field = ''; + } + } + } else { + $user->$field = core_user::clean_field($value, $field); + } + } catch (coding_exception $e) { + debugging("The property '$field' could not be cleaned.", DEBUG_DEVELOPER); + } + } + + return $user; + } + + /** + * Clean a specific user field. + * + * @param string $data the user field data to be cleaned. + * @param string $field the user field name on the property definition cache. + * @return string the cleaned user data. + */ + public static function clean_field($data, $field) { + if (empty($data) || empty($field)) { + return $data; + } + + try { + $type = core_user::get_property_type($field); + + if (isset(self::$propertiescache[$field]['choices'])) { + if (!array_key_exists($data, self::$propertiescache[$field]['choices'])) { + if (isset(self::$propertiescache[$field]['default'])) { + $data = self::$propertiescache[$field]['default']; + } else { + $data = ''; + } + } + } else { + $data = clean_param($data, $type); + } + } catch (coding_exception $e) { + debugging("The property '$field' could not be cleaned.", DEBUG_DEVELOPER); + } + + return $data; + } + + /** + * Get the parameter type of the property. + * + * @param string $property property name to be retrieved. + * @throws coding_exception if the requested property name is invalid. + * @return int the property parameter type. + */ + public static function get_property_type($property) { + + self::fill_properties_cache(); + + if (!array_key_exists($property, self::$propertiescache)) { + throw new coding_exception('Invalid property requested: ' . $property); + } + + return self::$propertiescache[$property]['type']; + } + + /** + * Discover if the property is NULL_ALLOWED or NULL_NOT_ALLOWED. + * + * @param string $property property name to be retrieved. + * @throws coding_exception if the requested property name is invalid. + * @return bool true if the property is NULL_ALLOWED, false otherwise. + */ + public static function get_property_null($property) { + + self::fill_properties_cache(); + + if (!array_key_exists($property, self::$propertiescache)) { + throw new coding_exception('Invalid property requested: ' . $property); + } + + return self::$propertiescache[$property]['null']; + } + + /** + * Get the choices of the property. + * + * This is a helper method to validate a value against a list of acceptable choices. + * For instance: country, timezone, language, themes and etc. + * + * @param string $property property name to be retrieved. + * @throws coding_exception if the requested property name is invalid or if it does not has a list of choices. + * @return array the property parameter type. + */ + public static function get_property_choices($property) { + + self::fill_properties_cache(); + + if (!array_key_exists($property, self::$propertiescache) && !array_key_exists('choices', + self::$propertiescache[$property])) { + + throw new coding_exception('Invalid property requested, or the property does not has a list of choices.'); + } + + return self::$propertiescache[$property]['choices']; + } + + /** + * Get the property default. + * + * This method gets the default value of a field (if exists). + * + * @param string $property property name to be retrieved. + * @throws coding_exception if the requested property name is invalid or if it does not has a default value. + * @return string the property default value. + */ + public static function get_property_default($property) { + + self::fill_properties_cache(); + + if (!array_key_exists($property, self::$propertiescache) || !isset(self::$propertiescache[$property]['default'])) { + throw new coding_exception('Invalid property requested, or the property does not has a default value.'); + } + + return self::$propertiescache[$property]['default']; + } } diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index fc8ba43a926..18f671f259e 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1464,5 +1464,11 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2016030400.01); } + if ($oldversion < 2016040700.01) { + // Update all countries to upper case. + $DB->execute("UPDATE {user} SET country = UPPER(country)"); + // Main savepoint reached. + upgrade_main_savepoint(true, 2016040700.01); + } return true; } diff --git a/lib/tests/user_test.php b/lib/tests/user_test.php index c6ddbac9f91..ac7fdcec249 100644 --- a/lib/tests/user_test.php +++ b/lib/tests/user_test.php @@ -209,4 +209,207 @@ class core_user_testcase extends advanced_testcase { $this->assertRegExp('/Invalid property requested./', $e->getMessage()); } } + + /** + * Test validate() method. + */ + public function test_validate() { + + // Create user with just with username and firstname. + $record = array('username' => 's10', 'firstname' => 'Bebe Stevens'); + $validation = core_user::validate((object)$record); + + // Validate the user, should return true as the user data is correct. + $this->assertTrue($validation); + + // Create user with incorrect data (invalid country and theme). + $record = array('username' => 's1', 'firstname' => 'Eric Cartman', 'country' => 'UU', 'theme' => 'beise'); + + // Should return an array with 2 errors. + $validation = core_user::validate((object)$record); + $this->assertArrayHasKey('country', $validation); + $this->assertArrayHasKey('theme', $validation); + $this->assertCount(2, $validation); + + // Create user with malicious data (xss). + $record = array('username' => 's3', 'firstname' => 'Kyle Doe'; + $user->username = 'john%#&~%*_doe'; + $user->email = ' john@testing.com '; + $user->deleted = 'no'; + $user->description = 'A description about myself.'; + $usercleaned = core_user::clean_data($user); + + // Expected results. + $this->assertEquals('John alert(1) Doe', $usercleaned->firstname); + $this->assertEquals('john@testing.com', $usercleaned->email); + $this->assertEquals(0, $usercleaned->deleted); + $this->assertEquals('A description about myself.', $user->description); + $this->assertEquals('john_doe', $user->username); + + // Try to clean an invalid property (userfullname). + $user->userfullname = 'John Doe'; + core_user::clean_data($user); + $this->assertDebuggingCalled("The property 'userfullname' could not be cleaned."); + } + + /** + * Test clean_field() method. + */ + public function test_clean_field() { + + // Create a 'malicious' user object/ + $user = new stdClass(); + $user->firstname = 'John Doe'; + $user->username = 'john%#&~%*_doe'; + $user->email = ' john@testing.com '; + $user->deleted = 'no'; + $user->description = 'A description about myself.'; + $user->userfullname = 'John Doe'; + + // Expected results. + $this->assertEquals('John alert(1) Doe', core_user::clean_field($user->firstname, 'firstname')); + $this->assertEquals('john_doe', core_user::clean_field($user->username, 'username')); + $this->assertEquals('john@testing.com', core_user::clean_field($user->email, 'email')); + $this->assertEquals(0, core_user::clean_field($user->deleted, 'deleted')); + $this->assertEquals('A description about myself.', core_user::clean_field($user->description, 'description')); + + // Try to clean an invalid property (fullname). + core_user::clean_field($user->userfullname, 'fullname'); + $this->assertDebuggingCalled("The property 'fullname' could not be cleaned."); + } + + /** + * Test get_property_type() method. + */ + public function test_get_property_type() { + + // Fetch valid properties and verify if the type is correct. + $type = core_user::get_property_type('username'); + $this->assertEquals(PARAM_USERNAME, $type); + $type = core_user::get_property_type('email'); + $this->assertEquals(PARAM_RAW_TRIMMED, $type); + $type = core_user::get_property_type('timezone'); + $this->assertEquals(PARAM_TIMEZONE, $type); + + // Try to fetch type of a non-existent properties. + $nonexistingproperty = 'userfullname'; + $this->setExpectedException('coding_exception', 'Invalid property requested: ' . $nonexistingproperty); + core_user::get_property_type($nonexistingproperty); + $nonexistingproperty = 'mobilenumber'; + $this->setExpectedException('coding_exception', 'Invalid property requested: ' . $nonexistingproperty); + core_user::get_property_type($nonexistingproperty); + } + + /** + * Test get_property_null() method. + */ + public function test_get_property_null() { + // Fetch valid properties and verify if it is NULL_ALLOWED or NULL_NOT_ALLOWED. + $property = core_user::get_property_null('username'); + $this->assertEquals(NULL_NOT_ALLOWED, $property); + $property = core_user::get_property_null('password'); + $this->assertEquals(NULL_NOT_ALLOWED, $property); + $property = core_user::get_property_null('imagealt'); + $this->assertEquals(NULL_ALLOWED, $property); + $property = core_user::get_property_null('middlename'); + $this->assertEquals(NULL_ALLOWED, $property); + + // Try to fetch type of a non-existent properties. + $nonexistingproperty = 'lastnamefonetic'; + $this->setExpectedException('coding_exception', 'Invalid property requested: ' . $nonexistingproperty); + core_user::get_property_null($nonexistingproperty); + $nonexistingproperty = 'midlename'; + $this->setExpectedException('coding_exception', 'Invalid property requested: ' . $nonexistingproperty); + core_user::get_property_null($nonexistingproperty); + } + + /** + * Test get_property_choices() method. + */ + public function test_get_property_choices() { + + // Test against country property choices. + $choices = core_user::get_property_choices('country'); + $this->assertArrayHasKey('AU', $choices); + $this->assertArrayHasKey('BR', $choices); + $this->assertArrayNotHasKey('WW', $choices); + $this->assertArrayNotHasKey('TX', $choices); + + // Test against lang property choices. + $choices = core_user::get_property_choices('lang'); + $this->assertArrayHasKey('en', $choices); + $this->assertArrayHasKey('ko', $choices); + $this->assertArrayHasKey('ru', $choices); + $this->assertArrayNotHasKey('ww', $choices); + $this->assertArrayNotHasKey('yy', $choices); + + // Test against theme property choices. + $choices = core_user::get_property_choices('theme'); + $this->assertArrayHasKey('base', $choices); + $this->assertArrayHasKey('clean', $choices); + $this->assertArrayNotHasKey('unknowntheme', $choices); + $this->assertArrayNotHasKey('wrongtheme', $choices); + + // Test against timezone property choices. + $choices = core_user::get_property_choices('timezone'); + $this->assertArrayHasKey('America/Sao_Paulo', $choices); + $this->assertArrayHasKey('Australia/Perth', $choices); + $this->assertArrayHasKey('99', $choices); + $this->assertArrayHasKey('UTC', $choices); + $this->assertArrayNotHasKey('North Korea', $choices); + $this->assertArrayNotHasKey('New york', $choices); + + // Try to fetch type of a non-existent properties. + $nonexistingproperty = 'language'; + $this->setExpectedException('coding_exception', 'Invalid property requested: ' . $nonexistingproperty); + core_user::get_property_null($nonexistingproperty); + $nonexistingproperty = 'coutries'; + $this->setExpectedException('coding_exception', 'Invalid property requested: ' . $nonexistingproperty); + core_user::get_property_null($nonexistingproperty); + } + + /** + * Test get_property_default(). + */ + public function test_get_property_default() { + global $CFG; + + $country = core_user::get_property_default('country'); + $this->assertEquals($CFG->country, $country); + set_config('country', 'AU'); + core_user::reset_caches(); + $country = core_user::get_property_default('country'); + $this->assertEquals($CFG->country, $country); + + $lang = core_user::get_property_default('lang'); + $this->assertEquals($CFG->lang, $lang); + set_config('lang', 'en'); + $lang = core_user::get_property_default('lang'); + $this->assertEquals($CFG->lang, $lang); + + $timezone = core_user::get_property_default('timezone'); + $this->assertEquals($CFG->timezone, $timezone); + set_config('timezone', 99); + core_user::reset_caches(); + $timezone = core_user::get_property_default('timezone'); + $this->assertEquals(99, $timezone); + + $this->setExpectedException('coding_exception', 'Invalid property requested, or the property does not has a default value.'); + core_user::get_property_default('firstname'); + } } -- 2.43.0