MDL-63062 block_recentlyaccessedcourses: add web service

This commit is contained in:
Victor Deniz
2018-11-05 23:46:43 +00:00
committed by Víctor Déniz Falcón
parent bebef89174
commit 98a52c80bb
8 changed files with 283 additions and 4 deletions
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/ajax"],function(a,b){var c=function(a,c,d,e){var f={classification:a};"undefined"!=typeof c&&(f.limit=c),"undefined"!=typeof d&&(f.offset=d),"undefined"!=typeof e&&(f.sort=e);var g={methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:f};return b.call([g])[0]};return{getEnrolledCoursesByTimelineClassification:c}});
define(["jquery","core/ajax"],function(a,b){var c=function(a,c,d,e){var f={classification:a};"undefined"!=typeof c&&(f.limit=c),"undefined"!=typeof d&&(f.offset=d),"undefined"!=typeof e&&(f.sort=e);var g={methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:f};return b.call([g])[0]},d=function(a,c,d,e){var f={userid:a};"undefined"!=typeof c&&(f.limit=c),"undefined"!=typeof d&&(f.offset=d),"undefined"!=typeof e&&(f.sort=e);var g={methodname:"core_course_get_recent_courses",args:f};return b.call([g])[0]};return{getEnrolledCoursesByTimelineClassification:c,getLastAccessedCourses:d}});
+39 -1
View File
@@ -57,7 +57,45 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
return Ajax.call([request])[0];
};
/**
* Get the list of courses that the user has most recently accessed.
*
* @method getLastAccessedCourses
* @param {int} userid User from which the courses will be obtained
* @param {int} limit Only return this many results
* @param {int} offset Skip this many results from the start of the result set
* @param {string} sort Column to sort by and direction, e.g. 'shortname asc'
* @return {promise} Resolved with an array of courses
*/
var getLastAccessedCourses = function(userid, limit, offset, sort) {
var args = {};
if (typeof userid !== 'undefined') {
args.limit = limit;
}
if (typeof limit !== 'undefined') {
args.limit = limit;
}
if (typeof offset !== 'undefined') {
args.offset = offset;
}
if (typeof sort !== 'undefined') {
args.sort = sort;
}
var request = {
methodname: 'core_course_get_recent_courses',
args: args
};
return Ajax.call([request])[0];
};
return {
getEnrolledCoursesByTimelineClassification: getEnrolledCoursesByTimelineClassification
getEnrolledCoursesByTimelineClassification: getEnrolledCoursesByTimelineClassification,
getLastAccessedCourses: getLastAccessedCourses
};
});
+4
View File
@@ -141,6 +141,10 @@ class course_summary_exporter extends \core\external\exporter {
),
'hidden' => array(
'type' => PARAM_BOOL
),
'timeaccess' => array(
'type' => PARAM_INT,
'optional' => true
)
);
}
+81
View File
@@ -29,6 +29,7 @@ defined('MOODLE_INTERNAL') || die;
use core_course\external\course_summary_exporter;
require_once("$CFG->libdir/externallib.php");
require_once("lib.php");
/**
* Course external functions
@@ -3886,4 +3887,84 @@ class core_course_external extends external_api {
)
);
}
/**
* Returns description of method parameters
*
* @return external_function_parameters
* @since Moodle 3.6
*/
public static function get_recent_courses_parameters() {
return new external_function_parameters(
array(
'userid' => new external_value(PARAM_INT, 'id of the user, default to current user', VALUE_DEFAULT, 0),
'limit' => new external_value(PARAM_INT, 'result set limit', VALUE_DEFAULT, 0),
'offset' => new external_value(PARAM_INT, 'Result set offset', VALUE_DEFAULT, 0),
'sort' => new external_value(PARAM_TEXT, 'Sort string', VALUE_DEFAULT, null)
)
);
}
/**
* Get last accessed courses adding additional course information like images.
*
* @param int $userid User id from which the courses will be obtained
* @param int $limit Restrict result set to this amount
* @param int $offset Skip this number of records from the start of the result set
* @param string|null $sort SQL string for sorting
* @return array List of courses
* @throws invalid_parameter_exception
*/
public static function get_recent_courses(int $userid = 0, int $limit = 0, int $offset = 0, string $sort = null) {
global $USER, $PAGE;
if (empty($userid)) {
$userid = $USER->id;
}
$params = self::validate_parameters(self::get_recent_courses_parameters(),
array(
'userid' => $userid,
'limit' => $limit,
'offset' => $offset,
'sort' => $sort
)
);
$userid = $params['userid'];
$limit = $params['limit'];
$offset = $params['offset'];
$sort = $params['sort'];
$usercontext = context_user::instance($userid);
self::validate_context($usercontext);
if ($userid != $USER->id and !has_capability('moodle/user:viewdetails', $usercontext)) {
return array();
}
$courses = course_get_recent_courses($userid, $limit, $offset, $sort);
$renderer = $PAGE->get_renderer('core');
$recentcourses = array_map(function($course) use ($renderer) {
context_helper::preload_from_record($course);
$context = context_course::instance($course->id);
$exporter = new course_summary_exporter($course, ['context' => $context]);
return $exporter->export($renderer);
}, $courses);
return $recentcourses;
}
/**
* Returns description of method result value
*
* @return external_description
* @since Moodle 3.6
*/
public static function get_recent_courses_returns() {
return new external_multiple_structure(course_summary_exporter::get_read_structure(), 'Courses');
}
}
+66
View File
@@ -4529,3 +4529,69 @@ function get_hidden_courses_on_timeline($user = null) {
return $ids;
}
/**
* Returns a list of the most recently courses accessed by a user
*
* @param int $userid User id from which the courses will be obtained
* @param int $limit Restrict result set to this amount
* @param int $offset Skip this number of records from the start of the result set
* @param string|null $sort SQL string for sorting
* @return array
*/
function course_get_recent_courses(int $userid = null, int $limit = 0, int $offset = 0, string $sort = null) {
global $CFG, $USER, $DB;
if (empty($userid)) {
$userid = $USER->id;
}
$basefields = array('id', 'idnumber', 'summary', 'summaryformat', 'startdate', 'enddate', 'category',
'shortname', 'fullname', 'userid', 'timeaccess');
$sort = trim($sort);
if (empty($sort)) {
$sort = 'timeaccess DESC';
} else {
$rawsorts = explode(',', $sort);
$sorts = array();
foreach ($rawsorts as $rawsort) {
$rawsort = trim($rawsort);
$sorts[] = trim($rawsort);
}
$sort = implode(',', $sorts);
}
$orderby = "ORDER BY $sort";
$ctxfields = context_helper::get_preload_record_columns_sql('ctx');
$coursefields = 'c.' .join(',', $basefields);
$sql = "SELECT $ctxfields, $coursefields
FROM {course} c
JOIN {context} ctx ON ctx.contextlevel = :contextlevel
AND ctx.instanceid = c.id
JOIN {user_lastaccess} ul ON ul.courseid = c.id
WHERE ul.userid = :userid
$orderby";
$params = ['userid' => $userid, 'contextlevel' => CONTEXT_COURSE];
$recentcourses = $DB->get_records_sql($sql, $params, $offset, $limit);
// Filter courses if last access field is hidden.
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
if ($userid != $USER->id && isset($hiddenfields['lastaccess'])) {
$recentcourses = array_filter($recentcourses, function($course) {
context_helper::preload_from_record($course);
$context = context_course::instance($course->id, IGNORE_MISSING);
// If last access was a hidden field, a user requesting info about another user would need permission to view hidden
// fields.
return has_capability('moodle/course:viewhiddenuserfields', $context);
});
}
return $recentcourses;
}
+83 -1
View File
@@ -2744,4 +2744,86 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals($expectedcourses, $actual);
$this->assertEquals($expectednextoffset, $result['nextoffset']);
}
}
/**
* Test the get_recent_courses function.
*/
public function test_get_recent_courses() {
global $USER, $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
set_config('hiddenuserfields', 'lastaccess');
$courses = array();
for ($i = 1; $i < 12; $i++) {
$courses[] = $generator->create_course();
};
$student = $generator->create_user();
$teacher = $generator->create_user();
foreach ($courses as $course) {
$generator->enrol_user($student->id, $course->id, 'student');
}
$generator->enrol_user($teacher->id, $courses[0]->id, 'teacher');
$this->setUser($student);
$result = core_course_external::get_recent_courses($USER->id);
// No course accessed.
$this->assertCount(0, $result);
foreach ($courses as $course) {
core_course_external::view_course($course->id);
}
// Every course accessed.
$result = core_course_external::get_recent_courses($USER->id);
$this->assertCount( 11, $result);
// Every course accessed, result limited to 10 courses.
$result = core_course_external::get_recent_courses($USER->id, 10);
$this->assertCount(10, $result);
$guestcourse = $generator->create_course(
(object)array('shortname' => 'guestcourse',
'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
'enrol_guest_password_0' => ''));
core_course_external::view_course($guestcourse->id);
// Every course accessed, even the not enrolled one.
$result = core_course_external::get_recent_courses($USER->id);
$this->assertCount(12, $result);
// Offset 5, return 7 out of 12.
$result = core_course_external::get_recent_courses($USER->id, 0, 5);
$this->assertCount(7, $result);
// Offset 5 and limit 3, return 3 out of 12.
$result = core_course_external::get_recent_courses($USER->id, 3, 5);
$this->assertCount(3, $result);
// Sorted by course id ASC.
$result = core_course_external::get_recent_courses($USER->id, 0, 0, 'id ASC');
$this->assertEquals($courses[0]->id, array_shift($result)->id);
// Sorted by course id DESC.
$result = core_course_external::get_recent_courses($USER->id, 0, 0, 'id DESC');
$this->assertEquals($guestcourse->id, array_shift($result)->id);
// If last access is hidden, only get the courses where has viewhiddenuserfields capability.
$this->setUser($teacher);
$teacherroleid = $DB->get_field('role', 'id', array('shortname' => 'editingteacher'));
$usercontext = context_user::instance($student->id);
$this->assignUserCapability('moodle/user:viewdetails', $usercontext, $teacherroleid);
// Sorted by course id DESC.
$result = core_course_external::get_recent_courses($student->id);
$this->assertCount(1, $result);
$this->assertEquals($courses[0]->id, array_shift($result)->id);
}
}
+8
View File
@@ -544,6 +544,14 @@ $functions = array(
'type' => 'read',
'ajax' => true
),
'core_course_get_recent_courses' => array(
'classname' => 'core_course_external',
'methodname' => 'get_recent_courses',
'classpath' => 'course/externallib.php',
'description' => 'List of courses a user has accessed most recently.',
'type' => 'read',
'ajax' => true
),
'core_enrol_get_course_enrolment_methods' => array(
'classname' => 'core_enrol_external',
'methodname' => 'get_course_enrolment_methods',
+1 -1
View File
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2018110300.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2018110300.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.