MDL-58768 Calendar: Update get_raw_events_legacy_implementation
authorShamim Rezaie <shamim@moodle.com>
Wed, 28 Mar 2018 14:58:06 +0000 (01:58 +1100)
committerShamim Rezaie <shamim@moodle.com>
Fri, 27 Jul 2018 21:51:32 +0000 (07:51 +1000)
Update get_raw_events_legacy_implementation to work with the passed $users parameter instead of the logged in user.
Also, fixed a bug where get_raw_events_legacy_implementation was failing when $users was set to true, and a list of
$groups was given.

calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php
calendar/tests/raw_event_retrieval_strategy_test.php

index 5b863b2..37d1a80 100644 (file)
@@ -96,11 +96,24 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
             return array();
         }
 
+        if (is_numeric($users)) {
+            $users = array($users);
+        }
+        if (is_numeric($groups)) {
+            $groups = array($groups);
+        }
+        if (is_numeric($courses)) {
+            $courses = array($courses);
+        }
+        if (is_numeric($categories)) {
+            $categories = array($categories);
+        }
+
         // Array of filter conditions. To be concatenated by the OR operator.
         $filters = [];
 
         // User filter.
-        if ((is_array($users) && !empty($users)) or is_numeric($users)) {
+        if (is_array($users) && !empty($users)) {
             // Events from a number of users.
             list($insqlusers, $inparamsusers) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED);
             $filters[] = "(e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0 AND e.categoryid = 0)";
@@ -112,7 +125,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         // Boolean false (no users at all): We don't need to do anything.
 
         // Group filter.
-        if ((is_array($groups) && !empty($groups)) or is_numeric($groups)) {
+        if (is_array($groups) && !empty($groups)) {
             // Events from a number of groups.
             list($insqlgroups, $inparamsgroups) = $DB->get_in_or_equal($groups, SQL_PARAMS_NAMED);
             $filters[] = "e.groupid $insqlgroups";
@@ -124,7 +137,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         // Boolean false (no groups at all): We don't need to do anything.
 
         // Course filter.
-        if ((is_array($courses) && !empty($courses)) or is_numeric($courses)) {
+        if (is_array($courses) && !empty($courses)) {
             list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED);
             $filters[] = "(e.groupid = 0 AND e.courseid $insqlcourses)";
             $params = array_merge($params, $inparamscourses);
@@ -134,7 +147,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         }
 
         // Category filter.
-        if ((is_array($categories) && !empty($categories)) or is_numeric($categories)) {
+        if (is_array($categories) && !empty($categories)) {
             list($insqlcategories, $inparamscategories) = $DB->get_in_or_equal($categories, SQL_PARAMS_NAMED);
             $filters[] = "(e.groupid = 0 AND e.courseid = 0 AND e.categoryid $insqlcategories)";
             $params = array_merge($params, $inparamscategories);
@@ -168,54 +181,81 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         // Build SQL subquery and conditions for filtered events based on priorities.
         $subquerywhere = '';
         $subqueryconditions = [];
-
-        // Get the user's courses. Otherwise, get the default courses being shown by the calendar.
-        $usercourses = calendar_get_default_courses(null, 'id, category, groupmode, groupmodeforce');
-
-        // Set calendar filters.
-        list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true);
         $subqueryparams = [];
-
-        // Flag to indicate whether the query needs to exclude group overrides.
-        $viewgroupsonly = false;
-
-        if ($user) {
-            // Set filter condition for the user's events.
-            $subqueryconditions[] = "(ev.userid = :user AND ev.courseid = 0 AND ev.groupid = 0 AND ev.categoryid = 0)";
-            $subqueryparams['user'] = $user;
-
-            foreach ($usercourses as $courseid) {
-                if (has_capability('moodle/site:accessallgroups', \context_course::instance($courseid))) {
-                    $usergroupmembership = groups_get_all_groups($courseid, $user, 0, 'g.id');
-                    if (count($usergroupmembership) == 0) {
-                        $viewgroupsonly = true;
-                        break;
+        $allusercourses = [];
+
+        if (is_array($users) && !empty($users)) {
+            $userrecords = $DB->get_records_sql("SELECT * FROM {user} WHERE id $insqlusers", $inparamsusers);
+            foreach ($userrecords as $userrecord) {
+                // Get the user's courses. Otherwise, get the default courses being shown by the calendar.
+                $usercourses = calendar_get_default_courses(null, 'id, category, groupmode, groupmodeforce',
+                        false, $userrecord->id);
+
+                // Set calendar filters.
+                list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true, $userrecord);
+
+                $allusercourses = array_merge($allusercourses, $usercourses);
+
+                // Flag to indicate whether the query needs to exclude group overrides.
+                $viewgroupsonly = false;
+
+                if ($user) {
+                    // Set filter condition for the user's events.
+                    // Even though $user is a single scalar, we still use get_in_or_equal() because we are inside a loop.
+                    list($inusers, $inuserparams) = $DB->get_in_or_equal($user, SQL_PARAMS_NAMED);
+                    $subqueryconditions[] = "(ev.userid $inusers AND ev.courseid = 0 AND ev.groupid = 0 AND ev.categoryid = 0)";
+                    $subqueryparams = array_merge($subqueryparams, $inuserparams);
+
+                    foreach ($usercourses as $courseid) {
+                        if (has_capability('moodle/site:accessallgroups', \context_course::instance($courseid), $userrecord)) {
+                            $usergroupmembership = groups_get_all_groups($courseid, $user, 0, 'g.id');
+                            if (count($usergroupmembership) == 0) {
+                                $viewgroupsonly = true;
+                                break;
+                            }
+                        }
                     }
                 }
+
+                // Set filter condition for the user's group events.
+                if ($usergroups === true || $viewgroupsonly) {
+                    // Fetch group events, but not group overrides.
+                    $subqueryconditions[] = "(ev.groupid != 0 AND ev.eventtype = 'group')";
+                } else if (!empty($usergroups)) {
+                    // Fetch group events and group overrides.
+                    list($inusergroups, $inusergroupparams) = $DB->get_in_or_equal($usergroups, SQL_PARAMS_NAMED);
+                    $subqueryconditions[] = "(ev.groupid $inusergroups)";
+                    $subqueryparams = array_merge($subqueryparams, $inusergroupparams);
+                }
+            }
+        } else if ($users === true) {
+            // Events from ALL users.
+            $subqueryconditions[] = "(ev.userid != 0 AND ev.courseid = 0 AND ev.groupid = 0 AND ev.categoryid = 0)";
+
+            if (is_array($groups)) {
+                // Events from a number of groups.
+                list($insqlgroups, $inparamsgroups) = $DB->get_in_or_equal($groups, SQL_PARAMS_NAMED);
+                $subqueryconditions[] = "ev.groupid $insqlgroups";
+                $subqueryparams = array_merge($subqueryparams, $inparamsgroups);
+            } else if ($groups === true) {
+                // Events from ALL groups.
+                $subqueryconditions[] = "ev.groupid != 0";
             }
-        }
 
-        // Set filter condition for the user's group events.
-        if ($usergroups === true || $viewgroupsonly) {
-            // Fetch group events, but not group overrides.
-            $subqueryconditions[] = "(ev.groupid != 0 AND ev.eventtype = 'group')";
-        } else if (!empty($usergroups)) {
-            // Fetch group events and group overrides.
-            list($inusergroups, $inusergroupparams) = $DB->get_in_or_equal($usergroups, SQL_PARAMS_NAMED);
-            $subqueryconditions[] = "(ev.groupid $inusergroups)";
-            $subqueryparams = array_merge($subqueryparams, $inusergroupparams);
+            if ($courses === true) {
+                // ALL course events. It's not needed to worry about users' access as $users = true.
+                $subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid != 0 AND ev.categoryid = 0)";
+            }
         }
 
         // Get courses to be used for the subquery.
         $subquerycourses = [];
         if (is_array($courses)) {
             $subquerycourses = $courses;
-        } else if (is_numeric($courses)) {
-            $subquerycourses[] = $courses;
         }
         // Merge with user courses, if necessary.
-        if (!empty($usercourses)) {
-            $subquerycourses = array_merge($subquerycourses, $usercourses);
+        if (!empty($allusercourses)) {
+            $subquerycourses = array_merge($subquerycourses, $allusercourses);
             // Make sure we remove duplicate values.
             $subquerycourses = array_unique($subquerycourses);
         }
index 1a927c2..82cd7a8 100644 (file)
@@ -90,15 +90,29 @@ class core_calendar_raw_event_retrieval_strategy_testcase extends advanced_testc
         $this->assertCount(2, $events);
 
         // Disable the lesson module.
-        $modulerecord = $DB->get_record('modules', ['name' => 'lesson']);
-        $modulerecord->visible = 0;
-        $DB->update_record('modules', $modulerecord);
+        $DB->set_field('modules', 'visible', 0, ['name' => 'lesson']);
 
         // Check that we only return the assign event.
         $events = $retrievalstrategy->get_raw_events(null, [0], null);
         $this->assertCount(1, $events);
         $event = reset($events);
         $this->assertEquals('assign', $event->modulename);
+
+        // Now, log out and repeat the above test in the reverse order.
+        $this->setUser();
+
+        // Check that we only return the assign event (given that the lesson module is still disabled).
+        $events = $retrievalstrategy->get_raw_events([$student->id], [0], null);
+        $this->assertCount(1, $events);
+        $event = reset($events);
+        $this->assertEquals('assign', $event->modulename);
+
+        // Enable the lesson module.
+        $DB->set_field('modules', 'visible', 1, ['name' => 'lesson']);
+
+        // Get all events.
+        $events = $retrievalstrategy->get_raw_events(null, [0], null);
+        $this->assertCount(2, $events);
     }
 
     /**
@@ -209,37 +223,37 @@ class core_calendar_raw_event_retrieval_strategy_testcase extends advanced_testc
             calendar_event::create($event, false);
         }
 
-        $timestart = $now - 100;
-        $timeend = $now + (3 * 86400);
         $groups = [$group1->id, $group2->id];
 
-        // Get user override events.
-        $this->setUser($useroverridestudent);
-        $events = $retrievalstrategy->get_raw_events([$useroverridestudent->id], $groups, [$course->id]);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date - User override', $event->name);
-
-        // Get events for user that does not belong to any group and has no user override events.
-        $this->setUser($nogroupstudent);
-        $events = $retrievalstrategy->get_raw_events([$nogroupstudent->id], $groups, [$course->id]);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date', $event->name);
-
-        // Get events for user that belongs to groups A and B and has no user override events.
-        $this->setUser($group12student);
-        $events = $retrievalstrategy->get_raw_events([$group12student->id], $groups, [$course->id]);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
-
-        // Get events for user that belongs to group A and has no user override events.
-        $this->setUser($group1student);
-        $events = $retrievalstrategy->get_raw_events([$group1student->id], $groups, [$course->id]);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
+        // Do the following tests multiple times when logged in with different users. Also run the whole set when logged out.
+        // In any cases, the tests should not depend on the logged-in user.
+        foreach ([$useroverridestudent, $nogroupstudent, $group12student, $group1student, null] as $login) {
+            $this->setUser($login);
+
+            // Get user override events.
+            $events = $retrievalstrategy->get_raw_events([$useroverridestudent->id], $groups, [$course->id]);
+            $this->assertCount(1, $events);
+            $event = reset($events);
+            $this->assertEquals('Assignment 1 due date - User override', $event->name);
+
+            // Get events for user that does not belong to any group and has no user override events.
+            $events = $retrievalstrategy->get_raw_events([$nogroupstudent->id], $groups, [$course->id]);
+            $this->assertCount(1, $events);
+            $event = reset($events);
+            $this->assertEquals('Assignment 1 due date', $event->name);
+
+            // Get events for user that belongs to groups A and B and has no user override events.
+            $events = $retrievalstrategy->get_raw_events([$group12student->id], $groups, [$course->id]);
+            $this->assertCount(1, $events);
+            $event = reset($events);
+            $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
+
+            // Get events for user that belongs to group A and has no user override events.
+            $events = $retrievalstrategy->get_raw_events([$group1student->id], $groups, [$course->id]);
+            $this->assertCount(1, $events);
+            $event = reset($events);
+            $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
+        }
 
         // Add repeating events.
         $repeatingevents = [
@@ -290,8 +304,6 @@ class core_calendar_raw_event_retrieval_strategy_testcase extends advanced_testc
      * Test retrieval strategy with category specifications.
      */
     public function test_get_raw_events_category() {
-        global $DB;
-
         $this->resetAfterTest();
         $retrievalstrategy = new raw_event_retrieval_strategy();
         $generator = $this->getDataGenerator();
@@ -351,4 +363,88 @@ class core_calendar_raw_event_retrieval_strategy_testcase extends advanced_testc
         $events = $retrievalstrategy->get_raw_events(null, null, null, [$category1->id, $category2->id]);
         $this->assertCount(2, $events);
     }
+
+    public function test_get_raw_events_for_multiple_users() {
+        $this->resetAfterTest();
+
+        $generator = $this->getDataGenerator();
+
+        // Create users.
+        $user1 = $generator->create_user();
+        $user2 = $generator->create_user();
+        $user3 = $generator->create_user();
+
+        // Create user events.
+        $events = [
+            [
+                'name' => 'User1 Event',
+                'eventtype' => 'user',
+                'userid' => $user1->id,
+                'timestart' => time(),
+            ], [
+                'name' => 'User2 Event',
+                'eventtype' => 'user',
+                'userid' => $user2->id,
+                'timestart' => time(),
+            ], [
+                'name' => 'User3 Event',
+                'eventtype' => 'user',
+                'userid' => $user3->id,
+                'timestart' => time(),
+            ]
+        ];
+        foreach ($events as $event) {
+            calendar_event::create($event, false);
+        }
+
+        $retrievalstrategy = new raw_event_retrieval_strategy();
+
+        // Get all events.
+        $events = $retrievalstrategy->get_raw_events([$user1->id, $user2->id]);
+        $this->assertCount(2, $events);
+        $this->assertEquals(
+                ['User1 Event', 'User2 Event'],
+                array_column($events, 'name'),
+                '', 0.0, 10, true);
+    }
+
+    public function test_get_raw_events_for_groups_with_no_members() {
+        $this->resetAfterTest();
+
+        $generator = $this->getDataGenerator();
+
+        $course = $generator->create_course();
+
+        // Create groups.
+        $group1 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 1']);
+        $group2 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 2']);
+
+        // Create group events.
+        $events = [
+            [
+                'name' => 'Group 1 Event',
+                'eventtype' => 'group',
+                'groupid' => $group1->id,
+                'timestart' => time(),
+            ], [
+                'name' => 'Group 2 Event',
+                'eventtype' => 'group',
+                'groupid' => $group2->id,
+                'timestart' => time(),
+            ]
+        ];
+        foreach ($events as $event) {
+            calendar_event::create($event, false);
+        }
+
+        $retrievalstrategy = new raw_event_retrieval_strategy;
+
+        // Get group eventsl.
+        $events = $retrievalstrategy->get_raw_events(null, [$group1->id, $group2->id]);
+        $this->assertCount(2, $events);
+        $this->assertEquals(
+                ['Group 1 Event', 'Group 2 Event'],
+                array_column($events, 'name'),
+                '', 0.0, 10, true);
+    }
 }