MDL-50705 core_user: introduce new fill_properties_cache()
authorSimey Lameze <simey@moodle.com>
Mon, 18 Jan 2016 01:38:17 +0000 (09:38 +0800)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Thu, 10 Mar 2016 12:17:08 +0000 (13:17 +0100)
    Also the get_property_definition() was created to get the property without retrieve the whole definition cache and
    unit tests were created to tests those new methods.

lib/classes/user.php
lib/phpunit/classes/util.php
lib/tests/user_test.php
lib/upgrade.txt

index f11cb75..07c1faf 100644 (file)
@@ -49,6 +49,9 @@ class core_user {
     /** @var stdClass keep record of support user */
     public static $supportuser = false;
 
+    /** @var array store user fields properties cache. */
+    protected static $propertiescache = null;
+
     /**
      * Return user object from db or create noreply or support user,
      * if userid matches corse_user::NOREPLY_USER or corse_user::SUPPORT_USER
@@ -274,4 +277,104 @@ class core_user {
             throw new moodle_exception('suspended', 'auth');
         }
     }
+
+    /**
+     * Definition of user profile fields and the expected parameter type for data validation.
+     *
+     * @return void
+     */
+    protected static function fill_properties_cache() {
+
+        if (self::$propertiescache !== null) {
+            return;
+        }
+
+        // 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);
+
+        self::$propertiescache = $fields;
+    }
+
+    /**
+     * Get properties of a user field.
+     *
+     * @param string $property property name to be retrieved.
+     * @throws coding_exception if the requested property name is invalid.
+     * @return array the property definition.
+     */
+    public static function get_property_definition($property) {
+
+        self::fill_properties_cache();
+
+        if (!array_key_exists($property, self::$propertiescache)) {
+            throw new coding_exception('Invalid property requested.');
+        }
+
+        return self::$propertiescache[$property];
+    }
+
+    /**
+     * Clean the properties cache.
+     *
+     * During unit tests we need to be able to reset all caches so that each new test starts in a known state.
+     * Intended for use only for testing, phpunit calls this before every test.
+     */
+    public static function reset_caches() {
+        self::$propertiescache = null;
+    }
 }
index 5cbe558..60704c8 100644 (file)
@@ -216,6 +216,7 @@ class phpunit_util extends testing_util {
         filter_manager::reset_caches();
         core_filetypes::reset_caches();
         \core_search\manager::clear_static();
+        core_user::reset_caches();
 
         // Reset static unit test options.
         if (class_exists('\availability_date\condition', false)) {
index 4f0f268..c6ddbac 100644 (file)
@@ -184,4 +184,29 @@ class core_user_testcase extends advanced_testcase {
         }
 
     }
+
+    /**
+     * Test get_property_definition() method.
+     */
+    public function test_get_property_definition() {
+        // Try to get a existing property.
+        $properties = core_user::get_property_definition('id');
+        $this->assertEquals($properties['type'], PARAM_INT);
+        $properties = core_user::get_property_definition('username');
+        $this->assertEquals($properties['type'], PARAM_USERNAME);
+
+        // Invalid property.
+        try {
+            core_user::get_property_definition('fullname');
+        } catch (coding_exception $e) {
+            $this->assertRegExp('/Invalid property requested./', $e->getMessage());
+        }
+
+        // Empty parameter.
+        try {
+            core_user::get_property_definition('');
+        } catch (coding_exception $e) {
+            $this->assertRegExp('/Invalid property requested./', $e->getMessage());
+        }
+    }
 }
index d9192e6..72e47f2 100644 (file)
@@ -3,6 +3,11 @@ information provided here is intended especially for developers.
 
 === 3.1 ===
 
+* The core_user::fill_properties_cache() static method has been introduced to be a reference
+  and allow standard user fields data validation. Right now only type validation is supported
+  checking it against the parameter (PARAM_*) type of the target user field. MDL-52781 is
+  going to add support to null/not null and choices validation, replacing the existing code to
+  validate the user fields in different places in a common way.
 * Webservice function core_course_search_courses now returns results when the search string
   is less than 2 chars long.
 * Webservice function core_course_search_courses accepts a new parameter 'requiredcapabilities' to filter the results