Commit 95ae74a7 authored by Shamim Rezaie's avatar Shamim Rezaie
Browse files

MDL-58768 calendar: Add $requestinguser to the container class

The requesting user is not always the same as the current user. The container class now allows a different user
to be set as the requesting user. All capability checks are done against the requesting user.

Also, the $requestinguser is passed to core_calendar_provide_event_action and core_calendar_is_event_visible
callback functions. These callback functions need to be updated in all activity modules to accept a $user parameter.
parent f7115c2e
......@@ -81,6 +81,11 @@ class container {
*/
protected static $modulecache = array();
/**
* @var int The requesting user. All capability checks are done against this user.
*/
protected static $requestinguserid;
/**
* Initialises the dependency graph if it hasn't yet been.
*/
......@@ -117,11 +122,13 @@ class container {
[self::class, 'apply_component_provide_event_action'],
[self::class, 'apply_component_is_event_visible'],
function ($dbrow) {
$requestinguserid = self::get_requesting_user();
if (!empty($dbrow->categoryid)) {
// This is a category event. Check that the category is visible to this user.
$category = \coursecat::get($dbrow->categoryid, IGNORE_MISSING, true);
$category = \coursecat::get($dbrow->categoryid, IGNORE_MISSING, true, $requestinguserid);
if (empty($category) || !$category->is_uservisible()) {
if (empty($category) || !$category->is_uservisible($requestinguserid)) {
return true;
}
}
......@@ -131,7 +138,7 @@ class container {
return false;
}
$instances = get_fast_modinfo($dbrow->courseid)->instances;
$instances = get_fast_modinfo($dbrow->courseid, $requestinguserid)->instances;
// If modinfo doesn't know about the module, we should ignore it.
if (!isset($instances[$dbrow->modulename]) || !isset($instances[$dbrow->modulename][$dbrow->instance])) {
......@@ -156,11 +163,13 @@ class container {
}
$coursecontext = \context_course::instance($dbrow->courseid);
if (!$cm->get_course()->visible && !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
if (!$cm->get_course()->visible &&
!has_capability('moodle/course:viewhiddencourses', $coursecontext, $requestinguserid)) {
return true;
}
if (!has_capability('moodle/course:view', $coursecontext) && !is_enrolled($coursecontext)) {
if (!has_capability('moodle/course:view', $coursecontext, $requestinguserid) &&
!is_enrolled($coursecontext, $requestinguserid)) {
return true;
}
......@@ -191,6 +200,7 @@ class container {
* Reset all static caches, called between tests.
*/
public static function reset_caches() {
self::$requestinguserid = null;
self::$eventfactory = null;
self::$eventmapper = null;
self::$eventvault = null;
......@@ -230,6 +240,31 @@ class container {
return self::$eventvault;
}
/**
* Sets the requesting user so that all capability checks are done against this user.
* Setting the requesting user (hence calling this function) is optional and if you do not so,
* $USER will be used as the requesting user. However, if you wish to set the requesting user yourself,
* you should call this function before any other function of the container class is called.
*
* @param int $userid The user id.
* @throws \coding_exception
*/
public static function set_requesting_user($userid) {
self::$requestinguserid = $userid;
}
/**
* Returns the requesting user id.
* It usually is the current user unless it has been set explicitly using set_requesting_user.
*
* @return int
*/
public static function get_requesting_user() {
global $USER;
return empty(self::$requestinguserid) ? $USER->id : self::$requestinguserid;
}
/**
* Calls callback 'core_calendar_provide_event_action' from the component responsible for the event
*
......@@ -245,14 +280,23 @@ class container {
$mapper = self::$eventmapper;
$action = null;
if ($event->get_course_module()) {
$requestinguserid = self::get_requesting_user();
$legacyevent = $mapper->from_event_to_legacy_event($event);
// We know for a fact that the the requesting user might be different from the logged in user,
// but the event mapper is not aware of that.
if (empty($event->user) && !empty($legacyevent->userid)) {
$legacyevent->userid = $requestinguserid;
}
// TODO MDL-58866 Only activity modules currently support this callback.
// Any other event will not be displayed on the dashboard.
$action = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_provide_event_action',
[
$mapper->from_event_to_legacy_event($event),
self::$actionfactory
$legacyevent,
self::$actionfactory,
$requestinguserid
]
);
}
......@@ -279,12 +323,21 @@ class container {
$mapper = self::$eventmapper;
$eventvisible = null;
if ($event->get_course_module()) {
$requestinguserid = self::get_requesting_user();
$legacyevent = $mapper->from_event_to_legacy_event($event);
// We know for a fact that the the requesting user might be different from the logged in user,
// but the event mapper is not aware of that.
if (empty($event->user) && !empty($legacyevent->userid)) {
$legacyevent->userid = $requestinguserid;
}
// TODO MDL-58866 Only activity modules currently support this callback.
$eventvisible = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_is_event_visible',
[
$mapper->from_event_to_legacy_event($event)
$legacyevent,
$requestinguserid
]
);
}
......
......@@ -3258,6 +3258,11 @@ function calendar_get_legacy_events($tstart, $tend, $users, $groups, $courses,
return $param;
}, [$users, $groups, $courses, $categories]);
// If a single user is provided, we can use that for capability checks.
// Otherwise current logged in user is used - See MDL-58768.
if (is_array($userparam) && count($userparam) == 1) {
\core_calendar\local\event\container::set_requesting_user($userparam[0]);
}
$mapper = \core_calendar\local\event\container::get_event_mapper();
$events = \core_calendar\local\api::get_events(
$tstart,
......
......@@ -4,6 +4,8 @@ information provided here is intended especially for developers.
=== 3.6 ===
* calendar_get_default_courses() function now has optional $userid parameter.
* calendar_set_filters() function now has optional $user parameter.
* The core_calendar\local\event\container class now provides two new helper methods for getting and setting the requesting user:
set_requesting_user() and get_requesting_user().
=== 3.5 ===
* core_calendar_external::get_calendar_events now returns the categoryid for category events.
......
......@@ -6,6 +6,8 @@ information provided here is intended especially for developers.
* The final deprecation of xxx_get_types() callback means that this function will no longer be called.
Please use get_shortcuts() instead.
* lti_get_shortcuts has been deprecated. Please use get_shortcuts() instead to add items to the activity chooser.
* Now, when mod_<modname>_core_calendar_is_event_visible or mod_<modname>_core_calendar_provide_event_action callback functions
are called, the userid of the requesting user is also passed to them.
=== 3.5 ===
......
Supports Markdown
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