MDL-58768 calendar: Add $requestinguser to the container class
[moodle.git] / calendar / classes / local / event / container.php
index 597eb70..0afc594 100644 (file)
@@ -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
                 ]
             );
         }