mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 08:22:07 +02:00
Merge branch 'MDL-35443-wip' of git://github.com/mouneyrac/moodle
This commit is contained in:
commit
3913743aa3
@ -118,6 +118,7 @@ $string['missingusername'] = 'Missing username';
|
||||
$string['missingversionfile'] = 'Coding error: version.php file is missing for the component {$a}';
|
||||
$string['mobilewsdisabled'] = 'Disabled';
|
||||
$string['mobilewsenabled'] = 'Enabled';
|
||||
$string['nocapabilitytouseparameter'] = 'The user does not have the required capability to use the parameter {$a}';
|
||||
$string['nofunctions'] = 'This service has no functions.';
|
||||
$string['norequiredcapability'] = 'No required capability';
|
||||
$string['notoken'] = 'The token list is empty.';
|
||||
|
@ -282,6 +282,15 @@ $functions = array(
|
||||
'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update',
|
||||
),
|
||||
|
||||
'core_user_get_users_by_field' => array(
|
||||
'classname' => 'core_user_external',
|
||||
'methodname' => 'get_users_by_field',
|
||||
'classpath' => 'user/externallib.php',
|
||||
'description' => 'Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users()',
|
||||
'type' => 'read',
|
||||
'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update',
|
||||
),
|
||||
|
||||
'core_user_get_users_by_id' => array(
|
||||
'classname' => 'core_user_external',
|
||||
'methodname' => 'get_users_by_id',
|
||||
|
@ -368,6 +368,153 @@ class core_user_external extends external_api {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 2.4
|
||||
*/
|
||||
public static function get_users_by_field_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'field' => new external_value(PARAM_ALPHA, 'the search field can be
|
||||
\'id\' or \'idnumber\' or \'username\' or \'email\''),
|
||||
'values' => new external_multiple_structure(
|
||||
new external_value(PARAM_RAW, 'the value to match'))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user information for a unique field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return array An array of arrays containg user profiles.
|
||||
* @since Moodle 2.4
|
||||
*/
|
||||
public static function get_users_by_field($field, $values) {
|
||||
global $CFG, $USER, $DB;
|
||||
require_once($CFG->dirroot . "/user/lib.php");
|
||||
|
||||
$params = self::validate_parameters(self::get_users_by_field_parameters(),
|
||||
array('field' => $field, 'values' => $values));
|
||||
|
||||
// This array will keep all the users that are allowed to be searched,
|
||||
// according to the current user's privileges.
|
||||
$cleanedvalues = array();
|
||||
|
||||
switch ($field) {
|
||||
case 'id':
|
||||
$paramtype = PARAM_INT;
|
||||
break;
|
||||
case 'idnumber':
|
||||
$paramtype = PARAM_RAW;
|
||||
break;
|
||||
case 'username':
|
||||
$paramtype = PARAM_USERNAME;
|
||||
break;
|
||||
case 'email':
|
||||
$paramtype = PARAM_EMAIL;
|
||||
break;
|
||||
default:
|
||||
throw new coding_exception('invalid field parameter',
|
||||
'The search field \'' . $field . '\' is not supported, look at the web service documentation');
|
||||
}
|
||||
|
||||
// Clean the values
|
||||
foreach ($values as $value) {
|
||||
$cleanedvalue = clean_param($value, $paramtype);
|
||||
if ( $value != $cleanedvalue) {
|
||||
throw new invalid_parameter_exception('The field \'' . $field .
|
||||
'\' value is invalid: ' . $value . '(cleaned value: '.$cleanedvalue.')');
|
||||
}
|
||||
$cleanedvalues[] = $cleanedvalue;
|
||||
}
|
||||
|
||||
// Retrieve the users
|
||||
$users = $DB->get_records_list('user', $field, $cleanedvalues, 'id');
|
||||
|
||||
// Finally retrieve each users information
|
||||
$returnedusers = array();
|
||||
foreach ($users as $user) {
|
||||
|
||||
$userdetails = user_get_user_details_courses($user);
|
||||
|
||||
// Return the user only if the searched field is returned
|
||||
// Otherwise it means that the $USER was not allowed to search the returned user
|
||||
if (!empty($userdetails) and !empty($userdetails[$field])) {
|
||||
$returnedusers[] = $userdetails;
|
||||
}
|
||||
}
|
||||
|
||||
return $returnedusers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_multiple_structure
|
||||
* @since Moodle 2.4
|
||||
*/
|
||||
public static function get_users_by_field_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_USERNAME, 'Username policy is defined in Moodle security config', 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'),
|
||||
'email' => new external_value(PARAM_EMAIL, 'An email address', VALUE_OPTIONAL),
|
||||
'address' => new external_value(PARAM_TEXT, '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),
|
||||
'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the 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),
|
||||
'auth' => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL),
|
||||
'confirmed' => new external_value(PARAM_INT, 'Active user: 1 if confirmed, 0 otherwise', VALUE_OPTIONAL),
|
||||
'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL),
|
||||
'theme' => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
|
||||
'timezone' => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
|
||||
'mailformat' => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
|
||||
'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL),
|
||||
'descriptionformat' => new external_format_value('description', 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, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL),
|
||||
'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'),
|
||||
'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'),
|
||||
'customfields' => new external_multiple_structure(
|
||||
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'),
|
||||
'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'),
|
||||
)
|
||||
), 'User custom fields (also known as user profil fields)', 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)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
@ -938,4 +1085,4 @@ class moodle_user_external extends external_api {
|
||||
require_once($CFG->dirroot . '/enrol/externallib.php');
|
||||
return core_enrol_external::get_enrolled_users_returns();
|
||||
}
|
||||
}
|
||||
}
|
57
user/lib.php
57
user/lib.php
@ -244,7 +244,7 @@ function user_get_user_details($user, $course = null, array $userfields = array(
|
||||
} else {
|
||||
$canviewhiddenuserfields = has_capability('moodle/user:viewhiddendetails', $context);
|
||||
}
|
||||
$canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
|
||||
$canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
|
||||
if (!empty($course)) {
|
||||
$canviewuseremail = has_capability('moodle/course:useremail', $context);
|
||||
} else {
|
||||
@ -484,6 +484,59 @@ function user_get_user_details($user, $course = null, array $userfields = array(
|
||||
return $userdetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to obtain user details, either recurring directly to the user's system profile
|
||||
* or through one of the user's course enrollments (course profile).
|
||||
*
|
||||
* @param object $user The user.
|
||||
* @return array if unsuccessful or the allowed user details.
|
||||
*/
|
||||
function user_get_user_details_courses($user) {
|
||||
global $USER;
|
||||
$userdetails = null;
|
||||
|
||||
// Get the courses that the user is enrolled in (only active).
|
||||
$courses = enrol_get_users_courses($user->id, true);
|
||||
|
||||
$systemprofile = false;
|
||||
if (can_view_user_details_cap($user) || ($user->id == $USER->id) || has_coursecontact_role($user->id)) {
|
||||
$systemprofile = true;
|
||||
}
|
||||
|
||||
// Try using system profile.
|
||||
if ($systemprofile) {
|
||||
$userdetails = user_get_user_details($user, null);
|
||||
} else {
|
||||
// Try through course profile.
|
||||
foreach ($courses as $course) {
|
||||
if ($can_view_user_details_cap($user, $course) || ($user->id == $USER->id) || has_coursecontact_role($user->id)) {
|
||||
$userdetails = user_get_user_details($user, $course);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $userdetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $USER have the necessary capabilities to obtain user details.
|
||||
*
|
||||
* @param object $user
|
||||
* @param object $course if null then only consider system profile otherwise also consider the course's profile.
|
||||
* @return bool true if $USER can view user details.
|
||||
*/
|
||||
function can_view_user_details_cap($user, $course = null) {
|
||||
// Check $USER has the capability to view the user details at user context.
|
||||
$usercontext = get_context_instance(CONTEXT_USER, $user->id);
|
||||
$result = has_capability('moodle/user:viewdetails', $usercontext);
|
||||
// Otherwise can $USER see them at course context.
|
||||
if (!$result && !empty($course)) {
|
||||
$context = get_context_instance(CONTEXT_COURSE, $course->id);
|
||||
$result = has_capability('moodle/user:viewdetails', $context);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of page types
|
||||
* @param string $pagetype current page type
|
||||
@ -492,4 +545,4 @@ function user_get_user_details($user, $course = null, array $userfields = array(
|
||||
*/
|
||||
function user_page_type_list($pagetype, $parentcontext, $currentcontext) {
|
||||
return array('user-profile'=>get_string('page-user-profile', 'pagetype'));
|
||||
}
|
||||
}
|
@ -33,6 +33,164 @@ require_once($CFG->dirroot . '/user/externallib.php');
|
||||
|
||||
class core_user_external_testcase extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test get_users_by_field
|
||||
*/
|
||||
public function test_get_users_by_field() {
|
||||
global $USER, $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$course = self::getDataGenerator()->create_course();
|
||||
$user1 = array(
|
||||
'username' => 'usernametest1',
|
||||
'idnumber' => 'idnumbertest1',
|
||||
'firstname' => 'First Name User Test 1',
|
||||
'lastname' => 'Last Name User Test 1',
|
||||
'email' => 'usertest1@email.com',
|
||||
'address' => '2 Test Street Perth 6000 WA',
|
||||
'phone1' => '01010101010',
|
||||
'phone2' => '02020203',
|
||||
'icq' => 'testuser1',
|
||||
'skype' => 'testuser1',
|
||||
'yahoo' => 'testuser1',
|
||||
'aim' => 'testuser1',
|
||||
'msn' => 'testuser1',
|
||||
'department' => 'Department of user 1',
|
||||
'institution' => 'Institution of user 1',
|
||||
'description' => 'This is a description for user 1',
|
||||
'descriptionformat' => FORMAT_MOODLE,
|
||||
'city' => 'Perth',
|
||||
'url' => 'http://moodle.org',
|
||||
'country' => 'au'
|
||||
);
|
||||
$user1 = self::getDataGenerator()->create_user($user1);
|
||||
if (!empty($CFG->usetags)) {
|
||||
require_once($CFG->dirroot . '/user/editlib.php');
|
||||
require_once($CFG->dirroot . '/tag/lib.php');
|
||||
$user1->interests = array('Cinema', 'Tennis', 'Dance', 'Guitar', 'Cooking');
|
||||
useredit_update_interests($user1, $user1->interests);
|
||||
}
|
||||
$user2 = self::getDataGenerator()->create_user(
|
||||
array('username' => 'usernametest2', 'idnumber' => 'idnumbertest2'));
|
||||
|
||||
$generatedusers = array();
|
||||
$generatedusers[$user1->id] = $user1;
|
||||
$generatedusers[$user2->id] = $user2;
|
||||
|
||||
$context = context_course::instance($course->id);
|
||||
$roleid = $this->assignUserCapability('moodle/user:viewdetails', $context->id);
|
||||
|
||||
// Enrol the users in the course.
|
||||
// We use the manual plugin.
|
||||
$enrol = enrol_get_plugin('manual');
|
||||
$enrolinstances = enrol_get_instances($course->id, true);
|
||||
foreach ($enrolinstances as $courseenrolinstance) {
|
||||
if ($courseenrolinstance->enrol == "manual") {
|
||||
$instance = $courseenrolinstance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$enrol->enrol_user($instance, $user1->id, $roleid);
|
||||
$enrol->enrol_user($instance, $user2->id, $roleid);
|
||||
$enrol->enrol_user($instance, $USER->id, $roleid);
|
||||
|
||||
// call as admin and receive all possible fields.
|
||||
$this->setAdminUser();
|
||||
|
||||
$fieldstosearch = array('id', 'idnumber', 'username', 'email');
|
||||
|
||||
foreach ($fieldstosearch as $fieldtosearch) {
|
||||
|
||||
// Call the external function.
|
||||
$returnedusers = core_user_external::get_users_by_field($fieldtosearch,
|
||||
array($USER->{$fieldtosearch}, $user1->{$fieldtosearch}, $user2->{$fieldtosearch}));
|
||||
|
||||
// Expected result differ following the searched field
|
||||
// Admin user in the PHPunit framework doesn't have email or idnumber.
|
||||
if ($fieldtosearch == 'email' or $fieldtosearch == 'idnumber') {
|
||||
$expectedreturnedusers = 2;
|
||||
} else {
|
||||
$expectedreturnedusers = 3;
|
||||
}
|
||||
|
||||
// Check we retrieve the good total number of enrolled users + no error on capability.
|
||||
$this->assertEquals($expectedreturnedusers, count($returnedusers));
|
||||
|
||||
foreach($returnedusers as $returneduser) {
|
||||
$generateduser = ($returneduser['id'] == $USER->id) ?
|
||||
$USER : $generatedusers[$returneduser['id']];
|
||||
$this->assertEquals($generateduser->username, $returneduser['username']);
|
||||
if (!empty($generateduser->idnumber)) {
|
||||
$this->assertEquals($generateduser->idnumber, $returneduser['idnumber']);
|
||||
}
|
||||
$this->assertEquals($generateduser->firstname, $returneduser['firstname']);
|
||||
$this->assertEquals($generateduser->lastname, $returneduser['lastname']);
|
||||
if ($generateduser->email != $USER->email) { //don't check the tmp modified $USER email
|
||||
$this->assertEquals($generateduser->email, $returneduser['email']);
|
||||
}
|
||||
if (!empty($generateduser->address)) {
|
||||
$this->assertEquals($generateduser->address, $returneduser['address']);
|
||||
}
|
||||
if (!empty($generateduser->phone1)) {
|
||||
$this->assertEquals($generateduser->phone1, $returneduser['phone1']);
|
||||
}
|
||||
if (!empty($generateduser->phone2)) {
|
||||
$this->assertEquals($generateduser->phone2, $returneduser['phone2']);
|
||||
}
|
||||
if (!empty($generateduser->icq)) {
|
||||
$this->assertEquals($generateduser->icq, $returneduser['icq']);
|
||||
}
|
||||
if (!empty($generateduser->skype)) {
|
||||
$this->assertEquals($generateduser->skype, $returneduser['skype']);
|
||||
}
|
||||
if (!empty($generateduser->yahoo)) {
|
||||
$this->assertEquals($generateduser->yahoo, $returneduser['yahoo']);
|
||||
}
|
||||
if (!empty($generateduser->aim)) {
|
||||
$this->assertEquals($generateduser->aim, $returneduser['aim']);
|
||||
}
|
||||
if (!empty($generateduser->msn)) {
|
||||
$this->assertEquals($generateduser->msn, $returneduser['msn']);
|
||||
}
|
||||
if (!empty($generateduser->department)) {
|
||||
$this->assertEquals($generateduser->department, $returneduser['department']);
|
||||
}
|
||||
if (!empty($generateduser->institution)) {
|
||||
$this->assertEquals($generateduser->institution, $returneduser['institution']);
|
||||
}
|
||||
if (!empty($generateduser->description)) {
|
||||
$this->assertEquals($generateduser->description, $returneduser['description']);
|
||||
}
|
||||
if (!empty($generateduser->descriptionformat)) {
|
||||
$this->assertEquals(FORMAT_HTML, $returneduser['descriptionformat']);
|
||||
}
|
||||
if (!empty($generateduser->city)) {
|
||||
$this->assertEquals($generateduser->city, $returneduser['city']);
|
||||
}
|
||||
if (!empty($generateduser->country)) {
|
||||
$this->assertEquals($generateduser->country, $returneduser['country']);
|
||||
}
|
||||
if (!empty($generateduser->url)) {
|
||||
$this->assertEquals($generateduser->url, $returneduser['url']);
|
||||
}
|
||||
if (!empty($CFG->usetags) and !empty($generateduser->interests)) {
|
||||
$this->assertEquals(implode(', ', $generateduser->interests), $returneduser['interests']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that no result are returned for search by username if we are not admin
|
||||
$this->setGuestUser();
|
||||
|
||||
// Call the external function.
|
||||
$returnedusers = core_user_external::get_users_by_field('username',
|
||||
array($USER->username, $user1->username, $user2->username));
|
||||
|
||||
// Only the own $USER username should be returned
|
||||
$this->assertEquals(1, count($returnedusers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_course_user_profiles
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user