From 7150323ecd4d2283d19669a1667c75d4ab5000e5 Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Wed, 18 May 2016 14:05:40 +0800 Subject: [PATCH 1/2] MDL-54623 mod_assign: Unit test for list_participants() --- mod/assign/tests/externallib_test.php | 70 +++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/mod/assign/tests/externallib_test.php b/mod/assign/tests/externallib_test.php index 822d36e83c5..dd16c4a51f7 100644 --- a/mod/assign/tests/externallib_test.php +++ b/mod/assign/tests/externallib_test.php @@ -2267,6 +2267,76 @@ class mod_assign_external_testcase extends externallib_advanced_testcase { $this->assertEquals($group->name, $result['groupname']); } + /** + * Test for mod_assign_external::list_participants(). + * + * @throws coding_exception + */ + public function test_list_participants_user_info_with_special_characters() { + global $CFG, $DB; + $this->resetAfterTest(true); + $CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution'; + + $data = $this->create_assign_with_student_and_teacher(); + $assignment = $data['assign']; + $teacher = $data['teacher']; + + // Set data for student info that contain special characters. + $student = $data['student']; + $student->idnumber = '<\'"1am@wesome&c00l"\'>'; + $student->phone1 = '+63 (999) 888-7777'; + $student->phone2 = '(011) [15]4-123-4567'; + $student->department = 'Arts & Sciences & \' " ¢ £ © € ¥ ® < >'; + $student->institution = 'University of Awesome People & \' " ¢ £ © € ¥ ® < >'; + // Assert that we have valid user data. + $this->assertTrue(core_user::validate($student)); + // Update the user record. + $DB->update_record('user', $student); + + $this->setUser($teacher); + $participants = mod_assign_external::list_participants($assignment->id, 0, '', 0, 0); + $this->assertCount(1, $participants); + + // Asser that we have a valid response data. + $response = external_api::clean_returnvalue(mod_assign_external::list_participants_returns(), $participants); + $this->assertEquals($response, $participants); + + // Check participant data. + $participant = $participants[0]; + $this->assertEquals($student->idnumber, $participant['idnumber']); + $this->assertEquals($student->email, $participant['email']); + $this->assertEquals($student->phone1, $participant['phone1']); + $this->assertEquals($student->phone2, $participant['phone2']); + $this->assertEquals($student->department, $participant['department']); + $this->assertEquals($student->institution, $participant['institution']); + } + + /** + * Test for the type of the user-related properties in mod_assign_external::list_participants_returns(). + * + * @throws coding_exception + */ + public function test_list_participants_returns_user_property_types() { + // User properties defined in list_participants_returns(). + $userproperties = [ + 'id', 'username', 'firstname', 'lastname', 'idnumber', 'email', 'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo', + 'aim', 'msn', 'department', 'institution', 'firstaccess', 'lastaccess', 'description', 'descriptionformat', 'city', + 'url', 'country' + ]; + $returns = mod_assign_external::list_participants_returns(); + $this->assertTrue(isset($returns->content)); + $keydescs = $returns->content->keys; + // Get properties from returns description. + $keys = array_keys($keydescs); + foreach ($userproperties as $property) { + // Assert that the property exists in the returns description. + $this->assertContains($property, $keys); + // Assert that user-related property types match those of the defined in core_user. + $desc = $keydescs[$property]; + $this->assertEquals(core_user::get_property_type($property), $desc->type); + } + } + /** * Create a a course, assignment module instance, student and teacher and enrol them in * the course. From 5684c89b937092552dd06c592a975eea9deff4c7 Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Wed, 18 May 2016 10:44:17 +0800 Subject: [PATCH 2/2] MDL-54623 mod_assign: Fetch correct types for user properties Utilising core_user_external::user_description() to fetch the correct types for the user properties. --- mod/assign/externallib.php | 142 ++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 80 deletions(-) diff --git a/mod/assign/externallib.php b/mod/assign/externallib.php index fa0b1a5b224..d0924caafa0 100644 --- a/mod/assign/externallib.php +++ b/mod/assign/externallib.php @@ -2593,7 +2593,7 @@ class mod_assign_external extends external_api { } /** - * Trigger the grading_table_viewed event. + * Retrieves the list of students to be graded for the assignment. * * @param int $assignid the assign instance id * @param int $groupid the current group id @@ -2601,7 +2601,7 @@ class mod_assign_external extends external_api { * @param int $skip Number of records to skip * @param int $limit Maximum number of records to return * @return array of warnings and status result - * @since Moodle 3.0 + * @since Moodle 3.1 * @throws moodle_exception */ public static function list_participants($assignid, $groupid, $filter, $skip, $limit) { @@ -2680,88 +2680,70 @@ class mod_assign_external extends external_api { } /** - * Returns description of method result value + * Returns the description of the results of the mod_assign_external::list_participants() method. * * @return external_description - * @since Moodle 3.0 + * @since Moodle 3.1 */ public static function list_participants_returns() { - return new external_multiple_structure( - new external_single_structure(array( - 'id' => new external_value(PARAM_INT, 'ID of the user'), - 'username' => new external_value(PARAM_RAW, 'Username', VALUE_OPTIONAL), - 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL), - 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), - 'fullname' => new external_value(PARAM_NOTAGS, 'The fullname of the user'), - 'idnumber' => new external_value(PARAM_NOTAGS, 'The idnumber of the user', VALUE_OPTIONAL), - 'email' => new external_value(PARAM_TEXT, 'Email address', VALUE_OPTIONAL), - 'address' => new external_value(PARAM_MULTILANG, 'Postal address', VALUE_OPTIONAL), - 'phone1' => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL), - 'phone2' => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL), - 'icq' => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL), - 'skype' => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL), - 'yahoo' => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL), - 'aim' => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL), - 'msn' => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL), - 'department' => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL), - 'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL), - 'interests' => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL), - 'firstaccess' => new external_value(PARAM_INT, 'first access to the site (0 if never)', VALUE_OPTIONAL), - 'lastaccess' => new external_value(PARAM_INT, 'last access to the site (0 if never)', VALUE_OPTIONAL), - 'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL), - 'descriptionformat' => new external_value(PARAM_INT, 'User profile description format', VALUE_OPTIONAL), - 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), - 'url' => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL), - 'country' => new external_value(PARAM_ALPHA, 'Country code of the user, such as AU or CZ', VALUE_OPTIONAL), - 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small', VALUE_OPTIONAL), - 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big', VALUE_OPTIONAL), - 'customfields' => new external_multiple_structure( - new external_single_structure( - array( - 'type' => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field'), - 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), - 'name' => new external_value(PARAM_RAW, 'The name of the custom field'), - 'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field'), - ) - ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL), - 'groups' => new external_multiple_structure( - new external_single_structure( - array( - 'id' => new external_value(PARAM_INT, 'group id'), - 'name' => new external_value(PARAM_RAW, 'group name'), - 'description' => new external_value(PARAM_RAW, 'group description'), - ) - ), 'user groups', VALUE_OPTIONAL), - 'roles' => new external_multiple_structure( - new external_single_structure( - array( - 'roleid' => new external_value(PARAM_INT, 'role id'), - 'name' => new external_value(PARAM_RAW, 'role name'), - 'shortname' => new external_value(PARAM_ALPHANUMEXT, 'role shortname'), - 'sortorder' => new external_value(PARAM_INT, 'role sortorder') - ) - ), 'user roles', VALUE_OPTIONAL), - 'preferences' => new external_multiple_structure( - new external_single_structure( - array( - 'name' => new external_value(PARAM_ALPHANUMEXT, 'The name of the preferences'), - 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), - ) - ), 'User preferences', VALUE_OPTIONAL), - 'enrolledcourses' => new external_multiple_structure( - new external_single_structure( - array( - 'id' => new external_value(PARAM_INT, 'Id of the course'), - 'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'), - 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course') - ) - ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL), - 'submitted' => new external_value(PARAM_BOOL, 'have they submitted their assignment'), - 'requiregrading' => new external_value(PARAM_BOOL, 'is their submission waiting for grading'), - 'groupid' => new external_value(PARAM_INT, 'for group assignments this is the group id', VALUE_OPTIONAL), - 'groupname' => new external_value(PARAM_NOTAGS, 'for group assignments this is the group name', VALUE_OPTIONAL), - )) - ); + // Get user description. + $userdesc = core_user_external::user_description(); + // List unneeded properties. + $unneededproperties = [ + 'auth', 'confirmed', 'lang', 'calendartype', 'theme', 'timezone', 'mailformat' + ]; + // Remove unneeded properties for consistency with the previous version. + foreach ($unneededproperties as $prop) { + unset($userdesc->keys[$prop]); + } + + // Override property attributes for consistency with the previous version. + $userdesc->keys['fullname']->type = PARAM_NOTAGS; + $userdesc->keys['profileimageurlsmall']->required = VALUE_OPTIONAL; + $userdesc->keys['profileimageurl']->required = VALUE_OPTIONAL; + $userdesc->keys['email']->desc = 'Email address'; + $userdesc->keys['email']->desc = 'Email address'; + $userdesc->keys['idnumber']->desc = 'The idnumber of the user'; + + // Define other keys. + $otherkeys = [ + 'groups' => new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'group id'), + 'name' => new external_value(PARAM_RAW, 'group name'), + 'description' => new external_value(PARAM_RAW, 'group description'), + ] + ), 'user groups', VALUE_OPTIONAL + ), + 'roles' => new external_multiple_structure( + new external_single_structure( + [ + 'roleid' => new external_value(PARAM_INT, 'role id'), + 'name' => new external_value(PARAM_RAW, 'role name'), + 'shortname' => new external_value(PARAM_ALPHANUMEXT, 'role shortname'), + 'sortorder' => new external_value(PARAM_INT, 'role sortorder') + ] + ), 'user roles', VALUE_OPTIONAL + ), + 'enrolledcourses' => new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'Id of the course'), + 'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'), + 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course') + ] + ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL + ), + 'submitted' => new external_value(PARAM_BOOL, 'have they submitted their assignment'), + 'requiregrading' => new external_value(PARAM_BOOL, 'is their submission waiting for grading'), + 'groupid' => new external_value(PARAM_INT, 'for group assignments this is the group id', VALUE_OPTIONAL), + 'groupname' => new external_value(PARAM_NOTAGS, 'for group assignments this is the group name', VALUE_OPTIONAL), + ]; + + // Merge keys. + $userdesc->keys = array_merge($userdesc->keys, $otherkeys); + return new external_multiple_structure($userdesc); } /**