diff --git a/lib/db/services.php b/lib/db/services.php index 53c1309fa64c9..e0e70ebbaf09c 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -129,6 +129,15 @@ 'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update', ), + 'moodle_user_get_users_by_courseid' => array( + 'classname' => 'moodle_user_external', + 'methodname' => 'get_users_by_courseid', + 'classpath' => 'user/externallib.php', + 'description' => 'Get enrolled users by course id.', + 'type' => 'read', + 'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update, moodle/site:accessallgroups', + ), + 'moodle_user_get_course_participants_by_id' => array( 'classname' => 'moodle_user_external', 'methodname' => 'get_course_participants_by_id', @@ -258,6 +267,7 @@ 'moodle_webservice_get_siteinfo', 'moodle_notes_create_notes', 'moodle_user_get_course_participants_by_id', + 'moodle_user_get_users_by_courseid', 'moodle_message_send_messages'), 'enabled' => 0, 'restrictedusers' => 0, diff --git a/user/externallib.php b/user/externallib.php index fdc28bdc8a0fd..ac8cd74d9ae41 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -355,10 +355,6 @@ public static function get_users_by_id_parameters() { public static function get_users_by_id($userids) { global $CFG, $USER, $DB; require_once($CFG->dirroot . "/user/lib.php"); - require_once($CFG->dirroot . "/user/profile/lib.php"); //custom field library - require_once($CFG->dirroot . "/lib/filelib.php"); // file handling on description and friends - - $isadmin = is_siteadmin($USER); $params = self::validate_parameters(self::get_users_by_id_parameters(), array('userids'=>$userids)); @@ -371,205 +367,29 @@ public static function get_users_by_id($userids) { $users = $DB->get_recordset_sql($usersql, $params); $result = array(); + $hasuserupdatecap = has_capability('moodle/user:update', get_system_context()); foreach ($users as $user) { if (!empty($user->deleted)) { continue; } context_instance_preload($user); - // cached - $context = get_context_instance(CONTEXT_USER, $user->id); - $hasviewdetailscap = has_capability('moodle/user:viewdetails', $context); - $hasuserupdatecap = has_capability('moodle/user:update', get_system_context()); - - self::validate_context($context); - + $usercontext = get_context_instance(CONTEXT_USER, $user->id); + self::validate_context($usercontext); $currentuser = ($user->id == $USER->id); - if (!$currentuser && !$hasviewdetailscap && !has_coursecontact_role($user->id)) { - throw new moodle_exception('usernotavailable', 'error'); - } - - $userarray = array(); - - //basic fields - $userarray['id'] = $user->id; - if ($isadmin) { - $userarray['username'] = $user->username; - } - if ($isadmin or has_capability('moodle/site:viewfullnames', $context)) { - $userarray['firstname'] = $user->firstname; - $userarray['lastname'] = $user->lastname; - } - $userarray['fullname'] = fullname($user); - - //fields matching permissions from /user/editadvanced.php - if ($currentuser or $hasuserupdatecap) { - $userarray['auth'] = $user->auth; - $userarray['confirmed'] = $user->confirmed; - $userarray['idnumber'] = $user->idnumber; - $userarray['lang'] = $user->lang; - $userarray['theme'] = $user->theme; - $userarray['timezone'] = $user->timezone; - $userarray['mailformat'] = $user->mailformat; - } - - //Custom fields (matching /user/profil/lib.php - profile_display_fields code logic) - $fields = $DB->get_recordset_sql("SELECT f.* - FROM {user_info_field} f - JOIN {user_info_category} c - ON f.categoryid=c.id - ORDER BY c.sortorder ASC, f.sortorder ASC"); - foreach ($fields as $field) { - require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); - $newfield = 'profile_field_'.$field->datatype; - $formfield = new $newfield($field->id, $user->id); - if ($formfield->is_visible() and !$formfield->is_empty()) { - $userarray['customfields'][] = - array('name' => $formfield->field->name, 'value' => $formfield->data, - 'type' => $field->datatype, 'shortname' => $formfield->field->shortname); - } - } - $fields->close(); - - //image profiles urls (public, no permission required in fact) - $profileimageurl = moodle_url::make_pluginfile_url($context->id, 'user', 'icon', NULL, '/', 'f1'); - $userarray['profileimageurl'] = $profileimageurl->out(false); - $profileimageurlsmall = moodle_url::make_pluginfile_url($context->id, 'user', 'icon', NULL, '/', 'f2'); - $userarray['profileimageurlsmall'] = $profileimageurlsmall->out(false); - - //hidden user field - if (has_capability('moodle/user:viewhiddendetails', $context)) { - $hiddenfields = array(); - } else { - $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); - } - - if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) { - if (empty($CFG->profilesforenrolledusersonly) || $currentuser) { - $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $context->id, 'user', 'profile', null); - $userarray['description'] = $user->description; - $userarray['descriptionformat'] = $user->descriptionformat; - } - } - - if ((! isset($hiddenfields['country']) or $isadmin) && $user->country) { - $userarray['country'] = $user->country; - } - - if ((! isset($hiddenfields['city']) or $isadmin) && $user->city) { - $userarray['city'] = $user->city; - } - - if (has_capability('moodle/user:viewhiddendetails', $context)) { - if ($user->address) { - $userarray['address'] = $user->address; - } - if ($user->phone1) { - $userarray['phone1'] = $user->phone1; - } - if ($user->phone2) { - $userarray['phone2'] = $user->phone2; - } - } - - if ($currentuser - or $user->maildisplay == 1 - or has_capability('moodle/course:useremail', $context) - or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) { - $userarray['email'] = $user->email;; - } - - if ($user->url && (!isset($hiddenfields['webpage']) or $isadmin)) { - $url = $user->url; - if (strpos($user->url, '://') === false) { - $url = 'http://'. $url; - } - $user->url = clean_param($user->url, PARAM_URL); - $userarray['url'] = $user->url; - } - - if ($user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) { - $userarray['icq'] = $user->icq; - } - - if ($user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) { - $userarray['skype'] = $user->skype; - } - if ($user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) { - $userarray['yahoo'] = $user->yahoo; - } - if ($user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) { - $userarray['aim'] = $user->aim; - } - if ($user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) { - $userarray['msn'] = $user->msn; - } - - if ((!isset($hiddenfields['firstaccess'])) or $isadmin) { - if ($user->firstaccess) { - $userarray['firstaccess'] = $user->firstaccess; - } else { - $userarray['firstaccess'] = 0; - } - } - if ((!isset($hiddenfields['lastaccess'])) or $isadmin) { - if ($user->lastaccess) { - $userarray['lastaccess'] = $user->lastaccess; - } else { - $userarray['lastaccess'] = 0; + if ($userarray = user_get_user_details($user)) { + //fields matching permissions from /user/editadvanced.php + if ($currentuser or $hasuserupdatecap) { + $userarray['auth'] = $user->auth; + $userarray['confirmed'] = $user->confirmed; + $userarray['idnumber'] = $user->idnumber; + $userarray['lang'] = $user->lang; + $userarray['theme'] = $user->theme; + $userarray['timezone'] = $user->timezone; + $userarray['mailformat'] = $user->mailformat; } + $result[] = $userarray; } - /// Printing tagged interests - if (!empty($CFG->usetags)) { - require_once($CFG->dirroot . '/tag/lib.php'); - if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) { - $userarray['interests'] = $interests; - } - } - - //Departement/Institution are not displayed on any profile, however you can get them from editing profile. - if ($isadmin or $currentuser) { - if ($user->institution) { - $userarray['institution'] = $user->institution; - } - if (isset($user->department)) { //isset because it's ok to have department 0 - $userarray['department'] = $user->department; - } - } - - //list of courses where the user is enrolled - $enrolledcourses = array(); - if (!isset($hiddenfields['mycourses'])) { - if ($mycourses = enrol_get_users_courses($user->id, true, NULL, 'visible DESC,sortorder ASC')) { - $courselisting = ''; - foreach ($mycourses as $mycourse) { - if ($mycourse->category) { - if ($mycourse->visible == 0) { - $ccontext = get_context_instance(CONTEXT_COURSE, $mycourse->id); - if (!has_capability('moodle/course:viewhiddencourses', $ccontext)) { - continue; - } - } - $enrolledcourse = array(); - $enrolledcourse['id'] = $mycourse->id; - $enrolledcourse['fullname'] = $mycourse->fullname; - $enrolledcourses[] = $enrolledcourse; - } - } - $userarray['enrolledcourses'] = $enrolledcourses; - } - } - - //user preferences - if ($currentuser) { - $preferences = array(); - $userpreferences = get_user_preferences(); - foreach($userpreferences as $prefname => $prefvalue) { - $preferences[] = array('name' => $prefname, 'value' => $prefvalue); - } - $userarray['preferences'] = $preferences; - } - $result[] = $userarray; } $users->close(); @@ -637,7 +457,8 @@ public static function get_users_by_id_returns() { 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') + '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) ) @@ -671,11 +492,6 @@ public static function get_course_participants_by_id_parameters() { public static function get_course_participants_by_id($userlist) { global $CFG, $USER, $DB; require_once($CFG->dirroot . "/user/lib.php"); - require_once($CFG->dirroot . "/user/profile/lib.php"); //custom field library - require_once($CFG->dirroot . "/lib/filelib.php"); // file handling on description and friends - - $isadmin = is_siteadmin($USER); - $params = self::validate_parameters(self::get_course_participants_by_id_parameters(), array('userlist'=>$userlist)); $userids = array(); @@ -713,190 +529,217 @@ public static function get_course_participants_by_id($userlist) { continue; } context_instance_preload($user); - $usercontext = get_context_instance(CONTEXT_USER, $user->id); $course = $courses[$courseids[$user->id]]; $context = get_context_instance(CONTEXT_COURSE, $courseids[$user->id]); - $hasviewdetailscap = has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext); - self::validate_context($context); - - $currentuser = ($user->id == $USER->id); - - if (!$currentuser && !$hasviewdetailscap && !has_coursecontact_role($user->id)) { - throw new moodle_exception('usernotavailable', 'error'); - } - $userarray = array(); - - //basic fields - $userarray['id'] = $user->id; - if ($isadmin) { - $userarray['username'] = $user->username; - } - if ($isadmin or has_capability('moodle/site:viewfullnames', $context)) { - $userarray['firstname'] = $user->firstname; - $userarray['lastname'] = $user->lastname; - } - $userarray['fullname'] = fullname($user); - - //Custom fields (matching /user/profile/lib.php - profile_display_fields code logic) - $userarray['customfields'] = array(); - - $fields = $DB->get_recordset_sql("SELECT f.* - FROM {user_info_field} f - JOIN {user_info_category} c - ON f.categoryid=c.id - ORDER BY c.sortorder ASC, f.sortorder ASC"); - foreach ($fields as $field) { - require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); - $newfield = 'profile_field_'.$field->datatype; - $formfield = new $newfield($field->id, $user->id); - if ($formfield->is_visible() and !$formfield->is_empty()) { - $userarray['customfields'][] = - array('name' => $formfield->field->name, 'value' => $formfield->data, - 'type' => $field->datatype, 'shortname' => $formfield->field->shortname); - } - } - $fields->close(); - - //image profiles urls (public, no permission required in fact) - $profileimageurl = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f1'); - $userarray['profileimageurl'] = $profileimageurl->out(false); - $profileimageurlsmall = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f2'); - $userarray['profileimageurlsmall'] = $profileimageurlsmall->out(false); - - //hidden user field - if (has_capability('moodle/course:viewhiddenuserfields', $context)) { - $hiddenfields = array(); - } else { - $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); - } - - if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) { - if (empty($CFG->profilesforenrolledusersonly) || $currentuser) { - $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $context->id, 'user', 'profile', null); - $userarray['description'] = $user->description; - $userarray['descriptionformat'] = $user->descriptionformat; - } - } - - if ((! isset($hiddenfields['country']) or $isadmin) && $user->country) { - $userarray['country'] = $user->country; + if ($userarray = user_get_user_details($user, $course)) { + $result[] = $userarray; } + } - if ((! isset($hiddenfields['city']) or $isadmin) && $user->city) { - $userarray['city'] = $user->city; - } + $users->close(); - if (has_capability('moodle/course:viewhiddenuserfields', $context)) { - if ($user->address) { - $userarray['address'] = $user->address; - } - if ($user->phone1) { - $userarray['phone1'] = $user->phone1; - } - if ($user->phone2) { - $userarray['phone2'] = $user->phone2; - } - } + return $result; + } - if ($currentuser - or $user->maildisplay == 1 - or has_capability('moodle/course:useremail', $context) - or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) { - $userarray['email'] = $user->email;; - } + /** + * Returns description of method result value + * @return external_description + */ + public static function get_course_participants_by_id_returns() { + return new external_multiple_structure( + new external_single_structure( + array( + 'id' => new external_value(PARAM_NUMBER, 'ID of the user'), + 'username' => new external_value(PARAM_RAW, '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_TEXT, 'An email address - allow email as root@localhost', 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, '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), + '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) + ) + ) + ); + } - if ($user->url && (!isset($hiddenfields['webpage']) or $isadmin)) { - $url = $user->url; - if (strpos($user->url, '://') === false) { - $url = 'http://'. $url; - } - $user->url = clean_param($user->url, PARAM_URL); - $userarray['url'] = $user->url; - } + /** + * Returns description of method parameters + * @return external_function_parameters + */ + public static function get_users_by_courseid_parameters() { + return new external_function_parameters( + array( + 'courseid' => new external_value(PARAM_INT, 'course id'), + 'options' => new external_multiple_structure( + new external_single_structure( + array( + 'name' => new external_value(PARAM_ALPHANUMEXT, 'option name'), + 'value' => new external_value(PARAM_RAW, 'option value') + ) + ), 'method options'), + ) + ); + } - if ($user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) { - $userarray['icq'] = $user->icq; - } + /** + * Get course participants details + * @param int $courseid course id + * @param array $options options { + * 'name' => option name + * 'value' => option value + * } + * @return array An array of users + */ + public static function get_users_by_courseid($courseid, $options) { + global $CFG, $USER, $DB; + require_once($CFG->dirroot . "/user/lib.php"); - if ($user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) { - $userarray['skype'] = $user->skype; - } - if ($user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) { - $userarray['yahoo'] = $user->yahoo; - } - if ($user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) { - $userarray['aim'] = $user->aim; - } - if ($user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) { - $userarray['msn'] = $user->msn; + $params = self::validate_parameters( + self::get_users_by_courseid_parameters(), + array( + 'courseid'=>$courseid, + 'options'=>$options + ) + ); + $withcapability = ''; + $groupid = 0; + $onlyactive = false; + foreach ($options as $option) { + switch ($option['name']) { + case 'withcapability': + $withcapability = $option['value']; + break; + case 'groupid': + $groupid = (int)$option['value']; + break; + case 'onlyactive': + $onlyactive = !empty($option['value']); + break; } + } - if ((!isset($hiddenfields['firstaccess'])) or $isadmin) { - if ($user->firstaccess) { - $userarray['firstaccess'] = $user->firstaccess; - } else { - $userarray['firstaccess'] = 0; - } - } - if ((!isset($hiddenfields['lastaccess'])) or $isadmin) { - if ($user->lastaccess) { - $userarray['lastaccess'] = $user->lastaccess; - } else { - $userarray['lastaccess'] = 0; - } - } - /// Printing tagged interests - if (!empty($CFG->usetags)) { - require_once($CFG->dirroot . '/tag/lib.php'); - if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) { - $userarray['interests'] = $interests; - } - } + // to overwrite this parameter, you need role:review capability + if ($withcapability) { + require_capability('moodle/role:review', $coursecontext); + } + // need accessallgroups capability if you want to overwrite this option + if (!empty($groupid) && groups_is_member($groupid)) { + require_capability('moodle/site:accessallgroups', $context); + } + // to overwrite this option, you need course:enrolereview permission + if ($onlyactive) { + require_capability('moodle/course:enrolreview', $coursecontext); + } - //Departement/Institution are not displayed on any profile, however you can get them from editing profile. - if ($isadmin or $currentuser) { - if ($user->institution) { - $userarray['institution'] = $user->institution; - } - if (isset($user->department)) { //isset because it's ok to have department 0 - $userarray['department'] = $user->department; - } - } + list($coursectxselect, $coursectxjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); + $coursesql = "SELECT c.* $coursectxselect + FROM {course} c $coursectxjoin + WHERE c.id = $courseid"; + $course = $DB->get_record_sql($coursesql); + context_instance_preload($course); + $coursecontext = get_context_instance(CONTEXT_COURSE, $params['courseid']); + if ($courseid == SITEID) { + $context = get_system_context(); + } else { + $context = $coursecontext; + } + try { + self::validate_context($context); + } catch (Exception $e) { + $exceptionparam = new stdClass(); + $exceptionparam->message = $e->getMessage(); + $exceptionparam->courseid = $params['courseid']; + throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + } - // not a big secret - $userarray['roles'] = array(); - $roles = get_user_roles($context, $user->id, false); - foreach ($roles as $role) { - $userarray['roles'][] = array( - 'roleid' => $role->roleid, - 'name' => $role->name, - 'shortname' => $role->shortname, - 'sortorder' => $role->sortorder - ); + list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext, $withcapability, $groupid, $onlyactive); + list($ctxselect, $ctxjoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx'); + $records = $DB->get_records_sql($enrolledsql, $enrolledparams); + $sqlparams['courseid'] = $courseid; + $sql = "SELECT u.* $ctxselect + FROM {user} u $ctxjoin + WHERE u.id IN ($enrolledsql) + ORDER BY u.id ASC"; + $enrolledusers = $DB->get_recordset_sql($sql, $enrolledparams); + $users = array(); + foreach ($enrolledusers as $user) { + if (!empty($user->deleted)) { + continue; } - - // If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group - if (has_capability('moodle/site:accessallgroups', $context)) { - $usergroups = groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid, 'g.id, g.name,g.description'); - foreach ($usergroups as $group) { - $group->description = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group', 'description', $group->id); - $userarray['groups'][] = array('id'=>$group->id, 'name'=>$group->name, 'description'=>$group->description); - } + context_instance_preload($user); + if ($userdetails = user_get_user_details($user, $course)) { + $users[] = $userdetails; } - $result[] = $userarray; } + $enrolledusers->close(); - $users->close(); - - return $result; + return $users; } - /** * Returns description of method result value * @return external_description */ - public static function get_course_participants_by_id_returns() { + public static function get_users_by_courseid_returns() { return new external_multiple_structure( new external_single_structure( array( @@ -952,6 +795,21 @@ public static function get_course_participants_by_id_returns() { '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) ) ) ); diff --git a/user/lib.php b/user/lib.php index 3e9296dbf569c..668e7a83c0733 100644 --- a/user/lib.php +++ b/user/lib.php @@ -96,6 +96,249 @@ function user_get_users_by_id($userids) { return $DB->get_records_list('user', 'id', $userids); } + +/** + * + * Give user record from mdl_user, build an array conntains + * all user details + * @param stdClass $user user record from mdl_user + * @param stdClass $context context object + * @param stdClass $course moodle course + * @return array + */ +function user_get_user_details($user, $course = null) { + global $USER, $DB, $CFG; + require_once($CFG->dirroot . "/user/profile/lib.php"); //custom field library + require_once($CFG->dirroot . "/lib/filelib.php"); // file handling on description and friends + + if (!empty($course)) { + $context = get_context_instance(CONTEXT_COURSE, $course->id); + $usercontext = get_context_instance(CONTEXT_USER, $user->id); + $canviewdetailscap = has_capability('moodle/user:viewdetails', $usercontext); + } else { + $context = get_context_instance(CONTEXT_USER, $user->id); + $usercontext = $context; + } + + $currentuser = ($user->id == $USER->id); + $isadmin = is_siteadmin($USER); + + if (!empty($course)) { + $canviewhiddenuserfields = has_capability('moodle/course:viewhiddenuserfields', $context); + } else { + $canviewhiddenuserfields = has_capability('moodle/user:viewhiddendetails', $context); + } + $canviewdetailscap = ($canviewdetailscap || has_capability('moodle/user:viewdetails', $context)); + $canviewfullnames = has_capability('moodle/site:viewfullnames', $context); + if (!empty($course)) { + $canviewuseremail = has_capability('moodle/course:useremail', $context); + } else { + $canviewuseremail = false; + } + $cannotviewdescription = !empty($CFG->profilesforenrolledusersonly) && !$currentuser && !$DB->record_exists('role_assignments', array('userid'=>$user->id)); + if (!empty($course)) { + $canaccessallgroups = has_capability('moodle/site:accessallgroups', $context); + } else { + $canaccessallgroups = false; + } + + if (!$currentuser && !$canviewdetailscap && !has_coursecontact_role($user->id)) { + // skip this user details + return null; + } + + $userdetails = array(); + $userdetails['id'] = $user->id; + + if ($isadmin or $currentuser) { + $userdetails['username'] = $user->username; + } + if ($isadmin or $canviewfullnames) { + $userdetails['firstname'] = $user->firstname; + $userdetails['lastname'] = $user->lastname; + } + $userdetails['fullname'] = fullname($user); + + $fields = $DB->get_recordset_sql("SELECT f.* + FROM {user_info_field} f + JOIN {user_info_category} c + ON f.categoryid=c.id + ORDER BY c.sortorder ASC, f.sortorder ASC"); + $userdetails['customfields'] = array(); + foreach ($fields as $field) { + require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); + $newfield = 'profile_field_'.$field->datatype; + $formfield = new $newfield($field->id, $user->id); + if ($formfield->is_visible() and !$formfield->is_empty()) { + $userdetails['customfields'][] = + array('name' => $formfield->field->name, 'value' => $formfield->data, + 'type' => $field->datatype, 'shortname' => $formfield->field->shortname); + } + } + $fields->close(); + // unset customfields if it's empty + if (empty($userdetails['customfields'])) { + unset($userdetails['customfields']); + } + + // profile image + $profileimageurl = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f1'); + $userdetails['profileimageurl'] = $profileimageurl->out(false); + $profileimageurlsmall = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f2'); + $userdetails['profileimageurlsmall'] = $profileimageurlsmall->out(false); + + //hidden user field + if ($canviewhiddenuserfields) { + $hiddenfields = array(); + // address, phone1 and phone2 not appears in hidden fields list + // but require viewhiddenfields capability + // according to user/profile.php + if ($user->address) { + $userdetails['address'] = $user->address; + } + if ($user->phone1) { + $userdetails['phone1'] = $user->phone1; + } + if ($user->phone2) { + $userdetails['phone2'] = $user->phone2; + } + } else { + $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); + } + + if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) { + if (!$cannotviewdescription) { + $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $usercontext->id, 'user', 'profile', null); + $userdetails['description'] = $user->description; + $userdetails['descriptionformat'] = $user->descriptionformat; + } + } + + if ((!isset($hiddenfields['country']) or $isadmin) && $user->country) { + $userdetails['country'] = $user->country; + } + + if ((!isset($hiddenfields['city']) or $isadmin) && $user->city) { + $userdetails['city'] = $user->city; + } + + if ($user->url && (!isset($hiddenfields['webpage']) or $isadmin)) { + $url = $user->url; + if (strpos($user->url, '://') === false) { + $url = 'http://'. $url; + } + $user->url = clean_param($user->url, PARAM_URL); + $userdetails['url'] = $user->url; + } + + if ($user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) { + $userdetails['icq'] = $user->icq; + } + + if ($user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) { + $userdetails['skype'] = $user->skype; + } + if ($user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) { + $userdetails['yahoo'] = $user->yahoo; + } + if ($user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) { + $userdetails['aim'] = $user->aim; + } + if ($user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) { + $userdetails['msn'] = $user->msn; + } + + if (!isset($hiddenfields['firstaccess']) or $isadmin) { + if ($user->firstaccess) { + $userdetails['firstaccess'] = $user->firstaccess; + } else { + $userdetails['firstaccess'] = 0; + } + } + if (!isset($hiddenfields['lastaccess']) or $isadmin) { + if ($user->lastaccess) { + $userdetails['lastaccess'] = $user->lastaccess; + } else { + $userdetails['lastaccess'] = 0; + } + } + + if ($currentuser + or $canviewuseremail // this is a capability in course context, it will be false in usercontext + or $user->maildisplay == 1 + or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) { + $userdetails['email'] = $user->email;; + } + + if (!empty($CFG->usetags)) { + require_once($CFG->dirroot . '/tag/lib.php'); + if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) { + $userdetails['interests'] = $interests; + } + } + + //Departement/Institution are not displayed on any profile, however you can get them from editing profile. + if ($isadmin or $currentuser) { + if ($user->institution) { + $userdetails['institution'] = $user->institution; + } + if (isset($user->department)) { //isset because it's ok to have department 0 + $userdetails['department'] = $user->department; + } + } + + if (!empty($course)) { + // not a big secret + $roles = get_user_roles($context, $user->id, false); + $userdetails['roles'] = array(); + foreach ($roles as $role) { + $userdetails['roles'][] = array( + 'roleid' => $role->roleid, + 'name' => $role->name, + 'shortname' => $role->shortname, + 'sortorder' => $role->sortorder + ); + } + } + + // If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group + if (!empty($course) && $canaccessallgroups) { + $usergroups = groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid, 'g.id, g.name,g.description'); + $userdetails['groups'] = array(); + foreach ($usergroups as $group) { + $group->description = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group', 'description', $group->id); + $userdetails['groups'][] = array('id'=>$group->id, 'name'=>$group->name, 'description'=>$group->description); + } + } + //list of courses where the user is enrolled + if (!isset($hiddenfields['mycourses'])) { + $enrolledcourses = array(); + if ($mycourses = enrol_get_users_courses($user->id, true)) { + foreach ($mycourses as $mycourse) { + if ($mycourse->category) { + $enrolledcourse = array(); + $enrolledcourse['id'] = $mycourse->id; + $enrolledcourse['fullname'] = $mycourse->fullname; + $enrolledcourse['shortname'] = $mycourse->shortname; + $enrolledcourses[] = $enrolledcourse; + } + } + $userdetails['enrolledcourses'] = $enrolledcourses; + } + } + + //user preferences + if ($currentuser) { + $preferences = array(); + $userpreferences = get_user_preferences(); + foreach($userpreferences as $prefname => $prefvalue) { + $preferences[] = array('name' => $prefname, 'value' => $prefvalue); + } + $userdetails['preferences'] = $preferences; + } + return $userdetails; +} + /** * Return a list of page types * @param string $pagetype current page type diff --git a/version.php b/version.php index 2504d70c72479..1f28cf1fba5d9 100644 --- a/version.php +++ b/version.php @@ -31,7 +31,7 @@ -$version = 2011062700.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2011062700.03; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes