Commit b36ee81e authored by Juan Leyva's avatar Juan Leyva
Browse files

MDL-63523 enrol: Return extra fields for new dashboard

WebService core_enrol_get_users_courses should return extra information for the app
so we can display all the new dashboard information without having to do extra WS requests.
parent 3cced42e
......@@ -295,15 +295,18 @@ class core_enrol_external extends external_api {
global $CFG, $USER, $DB;
require_once($CFG->dirroot . '/course/lib.php');
require_once($CFG->libdir . '/completionlib.php');
// Do basic automatic PARAM checks on incoming data, using params description
// If any problems are found then exceptions are thrown with helpful error messages
$params = self::validate_parameters(self::get_users_courses_parameters(), array('userid'=>$userid));
$courses = enrol_get_users_courses($params['userid'], true, 'id, shortname, fullname, idnumber, visible,
summary, summaryformat, format, showgrades, lang, enablecompletion, category, startdate, enddate');
$courses = enrol_get_users_courses($params['userid'], true, '*');
$result = array();
// Get user data including last access to courses.
$user = get_complete_user_data('id', $userid);
foreach ($courses as $course) {
$context = context_course::instance($course->id, IGNORE_MISSING);
try {
......@@ -313,7 +316,8 @@ class core_enrol_external extends external_api {
continue;
}
if ($userid != $USER->id and !course_can_view_participants($context)) {
$sameuser = $USER->id == $userid;
if (!$sameuser and !course_can_view_participants($context)) {
// we need capability to view participants
continue;
}
......@@ -322,20 +326,58 @@ class core_enrol_external extends external_api {
$enrolledsql = "SELECT COUNT('x') FROM ($enrolledsqlselect) enrolleduserids";
$enrolledusercount = $DB->count_records_sql($enrolledsql, $enrolledparams);
$displayname = external_format_string(get_course_display_name_for_list($course), $context->id);
list($course->summary, $course->summaryformat) =
external_format_text($course->summary, $course->summaryformat, $context->id, 'course', 'summary', null);
$course->fullname = external_format_string($course->fullname, $context->id);
$course->shortname = external_format_string($course->shortname, $context->id);
$progress = null;
if ($course->enablecompletion) {
$progress = \core_completion\progress::get_course_progress_percentage($course);
$completed = null;
// Return only private information if the user should be able to see it.
if ($sameuser || completion_can_view_data($userid, $course)) {
if ($course->enablecompletion) {
$completion = new completion_info($course);
$completed = $completion->is_course_complete($userid);
$progress = \core_completion\progress::get_course_progress_percentage($course, $userid);
}
}
$lastaccess = null;
// Check if last access is a hidden field.
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
$canviewlastaccess = $sameuser || !isset($hiddenfields['lastaccess']);
if (!$canviewlastaccess) {
$canviewlastaccess = has_capability('moodle/course:viewhiddenuserfields', $context);
}
if ($canviewlastaccess && isset($user->lastcourseaccess[$course->id])) {
$lastaccess = $user->lastcourseaccess[$course->id];
}
// Retrieve course overview used files.
$courselist = new core_course_list_element($course);
$overviewfiles = array();
foreach ($courselist->get_course_overviewfiles() as $file) {
$fileurl = moodle_url::make_webservice_pluginfile_url($file->get_contextid(), $file->get_component(),
$file->get_filearea(), null, $file->get_filepath(),
$file->get_filename())->out(false);
$overviewfiles[] = array(
'filename' => $file->get_filename(),
'fileurl' => $fileurl,
'filesize' => $file->get_filesize(),
'filepath' => $file->get_filepath(),
'mimetype' => $file->get_mimetype(),
'timemodified' => $file->get_timemodified(),
);
}
$result[] = array(
'id' => $course->id,
'shortname' => $course->shortname,
'fullname' => $course->fullname,
'displayname' => $displayname,
'idnumber' => $course->idnumber,
'visible' => $course->visible,
'enrolledusercount' => $enrolledusercount,
......@@ -347,8 +389,12 @@ class core_enrol_external extends external_api {
'enablecompletion' => $course->enablecompletion,
'category' => $course->category,
'progress' => $progress,
'completed' => $completed,
'startdate' => $course->startdate,
'enddate' => $course->enddate,
'marker' => $course->marker,
'lastaccess' => $lastaccess,
'overviewfiles' => $overviewfiles,
);
}
......@@ -367,6 +413,7 @@ class core_enrol_external extends external_api {
'id' => new external_value(PARAM_INT, 'id of course'),
'shortname' => new external_value(PARAM_RAW, 'short name of course'),
'fullname' => new external_value(PARAM_RAW, 'long name of course'),
'displayname' => new external_value(PARAM_TEXT, 'course display name for lists.', VALUE_OPTIONAL),
'enrolledusercount' => new external_value(PARAM_INT, 'Number of enrolled users in this course'),
'idnumber' => new external_value(PARAM_RAW, 'id number of course'),
'visible' => new external_value(PARAM_INT, '1 means visible, 0 means hidden course'),
......@@ -379,8 +426,12 @@ class core_enrol_external extends external_api {
VALUE_OPTIONAL),
'category' => new external_value(PARAM_INT, 'course category id', VALUE_OPTIONAL),
'progress' => new external_value(PARAM_FLOAT, 'Progress percentage', VALUE_OPTIONAL),
'completed' => new external_value(PARAM_BOOL, 'Whether the course is completed.', VALUE_OPTIONAL),
'startdate' => new external_value(PARAM_INT, 'Timestamp when the course start', VALUE_OPTIONAL),
'enddate' => new external_value(PARAM_INT, 'Timestamp when the course end', VALUE_OPTIONAL),
'marker' => new external_value(PARAM_INT, 'Course section marker.', VALUE_OPTIONAL),
'lastaccess' => new external_value(PARAM_INT, 'Last access to the course (timestamp).', VALUE_OPTIONAL),
'overviewfiles' => new external_files('Overview files attached to this course.', VALUE_OPTIONAL),
)
)
);
......
......@@ -359,9 +359,10 @@ class core_enrol_externallib_testcase extends externallib_advanced_testcase {
* Test get_users_courses
*/
public function test_get_users_courses() {
global $USER;
global $CFG, $DB;
$this->resetAfterTest(true);
$CFG->enablecompletion = 1;
$timenow = time();
$coursedata1 = array(
......@@ -373,7 +374,8 @@ class core_enrol_externallib_testcase extends externallib_advanced_testcase {
'enablecompletion' => true,
'showgrades' => true,
'startdate' => $timenow,
'enddate' => $timenow + WEEKSECS
'enddate' => $timenow + WEEKSECS,
'marker' => 1
);
$coursedata2 = array(
......@@ -383,21 +385,32 @@ class core_enrol_externallib_testcase extends externallib_advanced_testcase {
$course1 = self::getDataGenerator()->create_course($coursedata1);
$course2 = self::getDataGenerator()->create_course($coursedata2);
$courses = array($course1, $course2);
$contexts = array ($course1->id => context_course::instance($course1->id),
$course2->id => context_course::instance($course2->id));
// Enrol $USER in the courses.
// We use the manual plugin.
$roleid = null;
$contexts = array();
foreach ($courses as $course) {
$contexts[$course->id] = context_course::instance($course->id);
$roleid = $this->assignUserCapability('moodle/course:viewparticipants',
$contexts[$course->id]->id, $roleid);
$student = $this->getDataGenerator()->create_user();
$otherstudent = $this->getDataGenerator()->create_user();
$studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentroleid);
$this->getDataGenerator()->enrol_user($otherstudent->id, $course1->id, $studentroleid);
$this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentroleid);
$this->getDataGenerator()->enrol_user($USER->id, $course->id, $roleid, 'manual');
}
// Force last access.
$timenow = time();
$lastaccess = array(
'userid' => $student->id,
'courseid' => $course1->id,
'timeaccess' => $timenow
);
$DB->insert_record('user_lastaccess', $lastaccess);
// Force completion.
$ccompletion = new completion_completion(array('course' => $course1->id, 'userid' => $student->id));
$ccompletion->mark_complete();
$this->setUser($student);
// Call the external function.
$enrolledincourses = core_enrol_external::get_users_courses($USER->id);
$enrolledincourses = core_enrol_external::get_users_courses($student->id);
// We need to execute the return values cleaning process to simulate the web service server.
$enrolledincourses = external_api::clean_returnvalue(core_enrol_external::get_users_courses_returns(), $enrolledincourses);
......@@ -418,11 +431,54 @@ class core_enrol_externallib_testcase extends externallib_advanced_testcase {
foreach ($coursedata1 as $fieldname => $value) {
$this->assertEquals($courseenrol[$fieldname], $course1->$fieldname);
}
// Text extra fields.
$this->assertEquals($course1->fullname, $courseenrol['displayname']);
$this->assertEquals([], $courseenrol['overviewfiles']);
$this->assertEquals($timenow, $courseenrol['lastaccess']);
$this->assertEquals(100.0, $courseenrol['progress']);
$this->assertEquals(true, $courseenrol['completed']);
} else {
// Check language pack. Should be empty since an incorrect one was used when creating the course.
$this->assertEmpty($courseenrol['lang']);
$this->assertEquals($course2->fullname, $courseenrol['displayname']);
$this->assertEquals([], $courseenrol['overviewfiles']);
$this->assertEquals(0, $courseenrol['lastaccess']);
$this->assertEquals(0, $courseenrol['progress']);
$this->assertEquals(false, $courseenrol['completed']);
}
}
// Now check that admin users can see all the info.
$this->setAdminUser();
$enrolledincourses = core_enrol_external::get_users_courses($student->id);
$enrolledincourses = external_api::clean_returnvalue(core_enrol_external::get_users_courses_returns(), $enrolledincourses);
$this->assertEquals(2, count($enrolledincourses));
foreach ($enrolledincourses as $courseenrol) {
if ($courseenrol['id'] == $course1->id) {
$this->assertEquals($timenow, $courseenrol['lastaccess']);
$this->assertEquals(100.0, $courseenrol['progress']);
} else {
$this->assertEquals(0, $courseenrol['progress']);
}
}
// Check other users can't see private info.
$this->setUser($otherstudent);
$enrolledincourses = core_enrol_external::get_users_courses($student->id);
$enrolledincourses = external_api::clean_returnvalue(core_enrol_external::get_users_courses_returns(), $enrolledincourses);
$this->assertEquals(1, count($enrolledincourses));
$this->assertEquals($timenow, $enrolledincourses[0]['lastaccess']); // I can see this, not hidden.
$this->assertEquals(null, $enrolledincourses[0]['progress']); // I can't see this, private.
// Change some global profile visibility fields.
$CFG->hiddenuserfields = 'lastaccess';
$enrolledincourses = core_enrol_external::get_users_courses($student->id);
$enrolledincourses = external_api::clean_returnvalue(core_enrol_external::get_users_courses_returns(), $enrolledincourses);
$this->assertEquals(0, $enrolledincourses[0]['lastaccess']); // I can't see this, hidden by global setting.
}
/**
......
This files describes API changes in /enrol/* - plugins,
information provided here is intended especially for developers.
=== 3.6 ===
* External function core_enrol_external::get_users_courses now return more information to avoid multiple queries to build the
user dashboard:
- displayname: Course display name for lists.
- marker: Course section active marker.
- completed: Whether the given user completed the course or not.
- lastaccess: Last time the user accessed the course.
- overviewfiles: Course overview files.
=== 3.5 ===
* Default sorting in enrol_get_my_courses(), enrol_get_all_users_courses() and enrol_get_users_courses() now respects
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment