| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 5 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 6 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 7 | // (at your option) any later version.
 | 
        
           |  |  | 8 | //
 | 
        
           |  |  | 9 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 12 | // GNU General Public License for more details.
 | 
        
           |  |  | 13 | //
 | 
        
           |  |  | 14 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 16 | /**
 | 
        
           |  |  | 17 |  * Unit tests for (some of) mod/feedback/lib.php.
 | 
        
           |  |  | 18 |  *
 | 
        
           |  |  | 19 |  * @package    mod_feedback
 | 
        
           |  |  | 20 |  * @copyright  2016 Stephen Bourget
 | 
        
           |  |  | 21 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 22 |  */
 | 
        
           |  |  | 23 | namespace mod_feedback;
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | use mod_feedback_completion;
 | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 28 | global $CFG;
 | 
        
           |  |  | 29 | require_once($CFG->dirroot . '/mod/feedback/lib.php');
 | 
        
           |  |  | 30 |   | 
        
           |  |  | 31 | /**
 | 
        
           |  |  | 32 |  * Unit tests for (some of) mod/feedback/lib.php.
 | 
        
           |  |  | 33 |  *
 | 
        
           |  |  | 34 |  * @copyright  2016 Stephen Bourget
 | 
        
           |  |  | 35 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 36 |  */
 | 
        
           |  |  | 37 | class lib_test extends \advanced_testcase {
 | 
        
           |  |  | 38 |   | 
        
           |  |  | 39 |     public function test_feedback_initialise() {
 | 
        
           |  |  | 40 |         $this->resetAfterTest();
 | 
        
           |  |  | 41 |         $this->setAdminUser();
 | 
        
           |  |  | 42 |   | 
        
           |  |  | 43 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 44 |         $params['course'] = $course->id;
 | 
        
           |  |  | 45 |         $params['timeopen'] = time() - 5 * MINSECS;
 | 
        
           |  |  | 46 |         $params['timeclose'] = time() + DAYSECS;
 | 
        
           |  |  | 47 |         $params['anonymous'] = 1;
 | 
        
           |  |  | 48 |         $params['intro'] = 'Some introduction text';
 | 
        
           |  |  | 49 |         $feedback = $this->getDataGenerator()->create_module('feedback', $params);
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 |         // Test different ways to construct the structure object.
 | 
        
           |  |  | 52 |         $pseudocm = get_coursemodule_from_instance('feedback', $feedback->id); // Object similar to cm_info.
 | 
        
           |  |  | 53 |         $cm = get_fast_modinfo($course)->instances['feedback'][$feedback->id]; // Instance of cm_info.
 | 
        
           |  |  | 54 |   | 
        
           |  |  | 55 |         $constructorparams = [
 | 
        
           |  |  | 56 |             [$feedback, null],
 | 
        
           |  |  | 57 |             [null, $pseudocm],
 | 
        
           |  |  | 58 |             [null, $cm],
 | 
        
           |  |  | 59 |             [$feedback, $pseudocm],
 | 
        
           |  |  | 60 |             [$feedback, $cm],
 | 
        
           |  |  | 61 |         ];
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |         foreach ($constructorparams as $params) {
 | 
        
           |  |  | 64 |             $structure = new mod_feedback_completion($params[0], $params[1], 0);
 | 
        
           |  |  | 65 |             $this->assertTrue($structure->is_open());
 | 
        
           |  |  | 66 |             $this->assertTrue($structure->get_cm() instanceof \cm_info);
 | 
        
           |  |  | 67 |             $this->assertEquals($feedback->cmid, $structure->get_cm()->id);
 | 
        
           |  |  | 68 |             $this->assertEquals($feedback->intro, $structure->get_feedback()->intro);
 | 
        
           |  |  | 69 |         }
 | 
        
           |  |  | 70 |     }
 | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |     /**
 | 
        
           |  |  | 73 |      * Tests for mod_feedback_refresh_events.
 | 
        
           |  |  | 74 |      */
 | 
        
           |  |  | 75 |     public function test_feedback_refresh_events() {
 | 
        
           |  |  | 76 |         global $DB;
 | 
        
           |  |  | 77 |         $this->resetAfterTest();
 | 
        
           |  |  | 78 |         $this->setAdminUser();
 | 
        
           |  |  | 79 |   | 
        
           |  |  | 80 |         $timeopen = time();
 | 
        
           |  |  | 81 |         $timeclose = time() + 86400;
 | 
        
           |  |  | 82 |   | 
        
           |  |  | 83 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 84 |         $generator = $this->getDataGenerator()->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 85 |         $params['course'] = $course->id;
 | 
        
           |  |  | 86 |         $params['timeopen'] = $timeopen;
 | 
        
           |  |  | 87 |         $params['timeclose'] = $timeclose;
 | 
        
           |  |  | 88 |         $feedback = $generator->create_instance($params);
 | 
        
           |  |  | 89 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 90 |         $context = \context_module::instance($cm->id);
 | 
        
           |  |  | 91 |   | 
        
           |  |  | 92 |         // Normal case, with existing course.
 | 
        
           |  |  | 93 |         $this->assertTrue(feedback_refresh_events($course->id));
 | 
        
           |  |  | 94 |         $eventparams = array('modulename' => 'feedback', 'instance' => $feedback->id, 'eventtype' => 'open');
 | 
        
           |  |  | 95 |         $openevent = $DB->get_record('event', $eventparams, '*', MUST_EXIST);
 | 
        
           |  |  | 96 |         $this->assertEquals($openevent->timestart, $timeopen);
 | 
        
           |  |  | 97 |   | 
        
           |  |  | 98 |         $eventparams = array('modulename' => 'feedback', 'instance' => $feedback->id, 'eventtype' => 'close');
 | 
        
           |  |  | 99 |         $closeevent = $DB->get_record('event', $eventparams, '*', MUST_EXIST);
 | 
        
           |  |  | 100 |         $this->assertEquals($closeevent->timestart, $timeclose);
 | 
        
           |  |  | 101 |         // In case the course ID is passed as a numeric string.
 | 
        
           |  |  | 102 |         $this->assertTrue(feedback_refresh_events('' . $course->id));
 | 
        
           |  |  | 103 |         // Course ID not provided.
 | 
        
           |  |  | 104 |         $this->assertTrue(feedback_refresh_events());
 | 
        
           |  |  | 105 |         $eventparams = array('modulename' => 'feedback');
 | 
        
           |  |  | 106 |         $events = $DB->get_records('event', $eventparams);
 | 
        
           |  |  | 107 |         foreach ($events as $event) {
 | 
        
           |  |  | 108 |             if ($event->modulename === 'feedback' && $event->instance === $feedback->id && $event->eventtype === 'open') {
 | 
        
           |  |  | 109 |                 $this->assertEquals($event->timestart, $timeopen);
 | 
        
           |  |  | 110 |             }
 | 
        
           |  |  | 111 |             if ($event->modulename === 'feedback' && $event->instance === $feedback->id && $event->eventtype === 'close') {
 | 
        
           |  |  | 112 |                 $this->assertEquals($event->timestart, $timeclose);
 | 
        
           |  |  | 113 |             }
 | 
        
           |  |  | 114 |         }
 | 
        
           |  |  | 115 |     }
 | 
        
           |  |  | 116 |   | 
        
           |  |  | 117 |     /**
 | 
        
           |  |  | 118 |      * Test check_updates_since callback.
 | 
        
           |  |  | 119 |      */
 | 
        
           |  |  | 120 |     public function test_check_updates_since() {
 | 
        
           |  |  | 121 |         global $DB;
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 |         $this->resetAfterTest();
 | 
        
           |  |  | 124 |         $this->setAdminUser();
 | 
        
           |  |  | 125 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 126 |   | 
        
           |  |  | 127 |         // Create user.
 | 
        
           |  |  | 128 |         $student = self::getDataGenerator()->create_user();
 | 
        
           |  |  | 129 |   | 
        
           |  |  | 130 |         // User enrolment.
 | 
        
           |  |  | 131 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 132 |         $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 133 |   | 
        
           |  |  | 134 |         $this->setCurrentTimeStart();
 | 
        
           |  |  | 135 |         $record = array(
 | 
        
           |  |  | 136 |             'course' => $course->id,
 | 
        
           |  |  | 137 |             'custom' => 0,
 | 
        
           |  |  | 138 |             'feedback' => 1,
 | 
        
           |  |  | 139 |         );
 | 
        
           |  |  | 140 |         $feedback = $this->getDataGenerator()->create_module('feedback', $record);
 | 
        
           |  |  | 141 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id, $course->id);
 | 
        
           |  |  | 142 |         $cm = \cm_info::create($cm);
 | 
        
           |  |  | 143 |   | 
        
           |  |  | 144 |         $this->setUser($student);
 | 
        
           |  |  | 145 |         // Check that upon creation, the updates are only about the new configuration created.
 | 
        
           |  |  | 146 |         $onehourago = time() - HOURSECS;
 | 
        
           |  |  | 147 |         $updates = feedback_check_updates_since($cm, $onehourago);
 | 
        
           |  |  | 148 |         foreach ($updates as $el => $val) {
 | 
        
           |  |  | 149 |             if ($el == 'configuration') {
 | 
        
           |  |  | 150 |                 $this->assertTrue($val->updated);
 | 
        
           |  |  | 151 |                 $this->assertTimeCurrent($val->timeupdated);
 | 
        
           |  |  | 152 |             } else {
 | 
        
           |  |  | 153 |                 $this->assertFalse($val->updated);
 | 
        
           |  |  | 154 |             }
 | 
        
           |  |  | 155 |         }
 | 
        
           |  |  | 156 |   | 
        
           |  |  | 157 |         $record = [
 | 
        
           |  |  | 158 |             'feedback' => $feedback->id,
 | 
        
           |  |  | 159 |             'userid' => $student->id,
 | 
        
           |  |  | 160 |             'timemodified' => time(),
 | 
        
           |  |  | 161 |             'random_response' => 0,
 | 
        
           |  |  | 162 |             'anonymous_response' => FEEDBACK_ANONYMOUS_NO,
 | 
        
           |  |  | 163 |             'courseid' => $course->id,
 | 
        
           |  |  | 164 |         ];
 | 
        
           |  |  | 165 |         $DB->insert_record('feedback_completed', (object)$record);
 | 
        
           |  |  | 166 |         $DB->insert_record('feedback_completedtmp', (object)$record);
 | 
        
           |  |  | 167 |   | 
        
           |  |  | 168 |         // Check now for finished and unfinished attempts.
 | 
        
           |  |  | 169 |         $updates = feedback_check_updates_since($cm, $onehourago);
 | 
        
           |  |  | 170 |         $this->assertTrue($updates->attemptsunfinished->updated);
 | 
        
           |  |  | 171 |         $this->assertCount(1, $updates->attemptsunfinished->itemids);
 | 
        
           |  |  | 172 |   | 
        
           |  |  | 173 |         $this->assertTrue($updates->attemptsfinished->updated);
 | 
        
           |  |  | 174 |         $this->assertCount(1, $updates->attemptsfinished->itemids);
 | 
        
           |  |  | 175 |     }
 | 
        
           |  |  | 176 |   | 
        
           |  |  | 177 |     /**
 | 
        
           |  |  | 178 |      * Test calendar event provide action open.
 | 
        
           |  |  | 179 |      */
 | 
        
           |  |  | 180 |     public function test_feedback_core_calendar_provide_event_action_open() {
 | 
        
           |  |  | 181 |         $this->resetAfterTest();
 | 
        
           |  |  | 182 |         $this->setAdminUser();
 | 
        
           |  |  | 183 |   | 
        
           |  |  | 184 |         $now = time();
 | 
        
           |  |  | 185 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 186 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id,
 | 
        
           |  |  | 187 |                 'timeopen' => $now - DAYSECS, 'timeclose' => $now + DAYSECS]);
 | 
        
           |  |  | 188 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 189 |   | 
        
           |  |  | 190 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 191 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |         $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 | 
        
           |  |  | 194 |         $this->assertEquals(get_string('answerquestions', 'feedback'), $actionevent->get_name());
 | 
        
           |  |  | 195 |         $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 | 
        
           |  |  | 196 |         $this->assertEquals(1, $actionevent->get_item_count());
 | 
        
           |  |  | 197 |         $this->assertTrue($actionevent->is_actionable());
 | 
        
           |  |  | 198 |     }
 | 
        
           |  |  | 199 |   | 
        
           |  |  | 200 |     /**
 | 
        
           |  |  | 201 |      * Test calendar event provide action open, viewed by a different user.
 | 
        
           |  |  | 202 |      */
 | 
        
           |  |  | 203 |     public function test_feedback_core_calendar_provide_event_action_open_for_user() {
 | 
        
           |  |  | 204 |         global $DB;
 | 
        
           |  |  | 205 |   | 
        
           |  |  | 206 |         $this->resetAfterTest();
 | 
        
           |  |  | 207 |         $this->setAdminUser();
 | 
        
           |  |  | 208 |   | 
        
           |  |  | 209 |         $now = time();
 | 
        
           |  |  | 210 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 211 |         $user2 = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 212 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 213 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 214 |         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 215 |   | 
        
           |  |  | 216 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id,
 | 
        
           |  |  | 217 |             'timeopen' => $now - DAYSECS, 'timeclose' => $now + DAYSECS]);
 | 
        
           |  |  | 218 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 219 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 220 |   | 
        
           |  |  | 221 |         $this->setUser($user2);
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |         // User2 checking their events.
 | 
        
           |  |  | 224 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user2->id);
 | 
        
           |  |  | 225 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 226 |   | 
        
           |  |  | 227 |         // User2 checking $user's events.
 | 
        
           |  |  | 228 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user->id);
 | 
        
           |  |  | 229 |         $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 | 
        
           |  |  | 230 |         $this->assertEquals(get_string('answerquestions', 'feedback'), $actionevent->get_name());
 | 
        
           |  |  | 231 |         $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 | 
        
           |  |  | 232 |         $this->assertEquals(1, $actionevent->get_item_count());
 | 
        
           |  |  | 233 |         $this->assertTrue($actionevent->is_actionable());
 | 
        
           |  |  | 234 |     }
 | 
        
           |  |  | 235 |   | 
        
           |  |  | 236 |     /**
 | 
        
           |  |  | 237 |      * Test calendar event provide action closed.
 | 
        
           |  |  | 238 |      */
 | 
        
           |  |  | 239 |     public function test_feedback_core_calendar_provide_event_action_closed() {
 | 
        
           |  |  | 240 |         $this->resetAfterTest();
 | 
        
           |  |  | 241 |         $this->setAdminUser();
 | 
        
           |  |  | 242 |   | 
        
           |  |  | 243 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 244 |         $feedback = $this->getDataGenerator()->create_module('feedback', array('course' => $course->id,
 | 
        
           |  |  | 245 |                 'timeclose' => time() - DAYSECS));
 | 
        
           |  |  | 246 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 247 |   | 
        
           |  |  | 248 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 249 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 250 |   | 
        
           |  |  | 251 |         // No event on the dashboard if feedback is closed.
 | 
        
           |  |  | 252 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 253 |     }
 | 
        
           |  |  | 254 |   | 
        
           |  |  | 255 |     /**
 | 
        
           |  |  | 256 |      * Test calendar event provide action closed, viewed by a different user.
 | 
        
           |  |  | 257 |      */
 | 
        
           |  |  | 258 |     public function test_feedback_core_calendar_provide_event_action_closed_for_user() {
 | 
        
           |  |  | 259 |         global $DB;
 | 
        
           |  |  | 260 |   | 
        
           |  |  | 261 |         $this->resetAfterTest();
 | 
        
           |  |  | 262 |         $this->setAdminUser();
 | 
        
           |  |  | 263 |   | 
        
           |  |  | 264 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 265 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 266 |         $user2 = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 267 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 268 |         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 269 |   | 
        
           |  |  | 270 |         $feedback = $this->getDataGenerator()->create_module('feedback', array('course' => $course->id,
 | 
        
           |  |  | 271 |             'timeclose' => time() - DAYSECS));
 | 
        
           |  |  | 272 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 273 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 274 |         $this->setUser($user2);
 | 
        
           |  |  | 275 |   | 
        
           |  |  | 276 |         // User2 checking their events.
 | 
        
           |  |  | 277 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user2->id);
 | 
        
           |  |  | 278 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 279 |   | 
        
           |  |  | 280 |         // User2 checking $user's events.
 | 
        
           |  |  | 281 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user->id);
 | 
        
           |  |  | 282 |   | 
        
           |  |  | 283 |         // No event on the dashboard if feedback is closed.
 | 
        
           |  |  | 284 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 285 |     }
 | 
        
           |  |  | 286 |   | 
        
           |  |  | 287 |     /**
 | 
        
           |  |  | 288 |      * Test calendar event action open in future.
 | 
        
           |  |  | 289 |      *
 | 
        
           |  |  | 290 |      * @throws coding_exception
 | 
        
           |  |  | 291 |      */
 | 
        
           |  |  | 292 |     public function test_feedback_core_calendar_provide_event_action_open_in_future() {
 | 
        
           |  |  | 293 |         $this->resetAfterTest();
 | 
        
           |  |  | 294 |         $this->setAdminUser();
 | 
        
           |  |  | 295 |   | 
        
           |  |  | 296 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 297 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id,
 | 
        
           |  |  | 298 |                 'timeopen' => time() + DAYSECS]);
 | 
        
           |  |  | 299 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 300 |   | 
        
           |  |  | 301 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 302 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 303 |   | 
        
           |  |  | 304 |         $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 | 
        
           |  |  | 305 |         $this->assertEquals(get_string('answerquestions', 'feedback'), $actionevent->get_name());
 | 
        
           |  |  | 306 |         $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 | 
        
           |  |  | 307 |         $this->assertEquals(1, $actionevent->get_item_count());
 | 
        
           |  |  | 308 |         $this->assertFalse($actionevent->is_actionable());
 | 
        
           |  |  | 309 |     }
 | 
        
           |  |  | 310 |   | 
        
           |  |  | 311 |     /**
 | 
        
           |  |  | 312 |      * Test calendar event action open in future, viewed by a different user.
 | 
        
           |  |  | 313 |      *
 | 
        
           |  |  | 314 |      * @throws coding_exception
 | 
        
           |  |  | 315 |      */
 | 
        
           |  |  | 316 |     public function test_feedback_core_calendar_provide_event_action_open_in_future_for_user() {
 | 
        
           |  |  | 317 |         global $DB;
 | 
        
           |  |  | 318 |   | 
        
           |  |  | 319 |         $this->resetAfterTest();
 | 
        
           |  |  | 320 |         $this->setAdminUser();
 | 
        
           |  |  | 321 |   | 
        
           |  |  | 322 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 323 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 324 |         $user2 = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 325 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 326 |         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 327 |   | 
        
           |  |  | 328 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id,
 | 
        
           |  |  | 329 |             'timeopen' => time() + DAYSECS]);
 | 
        
           |  |  | 330 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 331 |   | 
        
           |  |  | 332 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 333 |         $this->setUser($user2);
 | 
        
           |  |  | 334 |   | 
        
           |  |  | 335 |         // User2 checking their events.
 | 
        
           |  |  | 336 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user2->id);
 | 
        
           |  |  | 337 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 338 |   | 
        
           |  |  | 339 |         // User2 checking $user's events.
 | 
        
           |  |  | 340 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user->id);
 | 
        
           |  |  | 341 |   | 
        
           |  |  | 342 |         $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 | 
        
           |  |  | 343 |         $this->assertEquals(get_string('answerquestions', 'feedback'), $actionevent->get_name());
 | 
        
           |  |  | 344 |         $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 | 
        
           |  |  | 345 |         $this->assertEquals(1, $actionevent->get_item_count());
 | 
        
           |  |  | 346 |         $this->assertFalse($actionevent->is_actionable());
 | 
        
           |  |  | 347 |     }
 | 
        
           |  |  | 348 |   | 
        
           |  |  | 349 |     /**
 | 
        
           |  |  | 350 |      * Test calendar event with no time specified.
 | 
        
           |  |  | 351 |      *
 | 
        
           |  |  | 352 |      * @throws coding_exception
 | 
        
           |  |  | 353 |      */
 | 
        
           |  |  | 354 |     public function test_feedback_core_calendar_provide_event_action_no_time_specified() {
 | 
        
           |  |  | 355 |         $this->resetAfterTest();
 | 
        
           |  |  | 356 |         $this->setAdminUser();
 | 
        
           |  |  | 357 |   | 
        
           |  |  | 358 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 359 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
 | 
        
           |  |  | 360 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 361 |   | 
        
           |  |  | 362 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 363 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 364 |   | 
        
           |  |  | 365 |         $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 | 
        
           |  |  | 366 |         $this->assertEquals(get_string('answerquestions', 'feedback'), $actionevent->get_name());
 | 
        
           |  |  | 367 |         $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 | 
        
           |  |  | 368 |         $this->assertEquals(1, $actionevent->get_item_count());
 | 
        
           |  |  | 369 |         $this->assertTrue($actionevent->is_actionable());
 | 
        
           |  |  | 370 |     }
 | 
        
           |  |  | 371 |   | 
        
           |  |  | 372 |     /**
 | 
        
           |  |  | 373 |      * Test calendar event with no time specified, viewed by a different user.
 | 
        
           |  |  | 374 |      *
 | 
        
           |  |  | 375 |      * @throws coding_exception
 | 
        
           |  |  | 376 |      */
 | 
        
           |  |  | 377 |     public function test_feedback_core_calendar_provide_event_action_no_time_specified_for_user() {
 | 
        
           |  |  | 378 |         global $DB;
 | 
        
           |  |  | 379 |   | 
        
           |  |  | 380 |         $this->resetAfterTest();
 | 
        
           |  |  | 381 |         $this->setAdminUser();
 | 
        
           |  |  | 382 |   | 
        
           |  |  | 383 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 384 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 385 |         $user2 = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 386 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 387 |         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 388 |   | 
        
           |  |  | 389 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
 | 
        
           |  |  | 390 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 391 |   | 
        
           |  |  | 392 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 393 |         $this->setUser($user2);
 | 
        
           |  |  | 394 |   | 
        
           |  |  | 395 |         // User2 checking their events.
 | 
        
           |  |  | 396 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user2->id);
 | 
        
           |  |  | 397 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 398 |   | 
        
           |  |  | 399 |         // User2 checking $user's events.
 | 
        
           |  |  | 400 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user->id);
 | 
        
           |  |  | 401 |   | 
        
           |  |  | 402 |         $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 | 
        
           |  |  | 403 |         $this->assertEquals(get_string('answerquestions', 'feedback'), $actionevent->get_name());
 | 
        
           |  |  | 404 |         $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 | 
        
           |  |  | 405 |         $this->assertEquals(1, $actionevent->get_item_count());
 | 
        
           |  |  | 406 |         $this->assertTrue($actionevent->is_actionable());
 | 
        
           |  |  | 407 |     }
 | 
        
           |  |  | 408 |   | 
        
           |  |  | 409 |     /**
 | 
        
           |  |  | 410 |      * A user that can not submit feedback should not have an action.
 | 
        
           |  |  | 411 |      */
 | 
        
           |  |  | 412 |     public function test_feedback_core_calendar_provide_event_action_can_not_submit() {
 | 
        
           |  |  | 413 |         global $DB;
 | 
        
           |  |  | 414 |   | 
        
           |  |  | 415 |         $this->resetAfterTest();
 | 
        
           |  |  | 416 |         $this->setAdminUser();
 | 
        
           |  |  | 417 |   | 
        
           |  |  | 418 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 419 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 420 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 421 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
 | 
        
           |  |  | 422 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 423 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 424 |         $context = \context_module::instance($cm->id);
 | 
        
           |  |  | 425 |         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 426 |   | 
        
           |  |  | 427 |         $this->setUser($user);
 | 
        
           |  |  | 428 |         assign_capability('mod/feedback:complete', CAP_PROHIBIT, $studentrole->id, $context);
 | 
        
           |  |  | 429 |   | 
        
           |  |  | 430 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 431 |         $action = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 432 |   | 
        
           |  |  | 433 |         $this->assertNull($action);
 | 
        
           |  |  | 434 |     }
 | 
        
           |  |  | 435 |   | 
        
           |  |  | 436 |     /**
 | 
        
           |  |  | 437 |      * A user that can not submit feedback should not have an action, viewed by a different user.
 | 
        
           |  |  | 438 |      */
 | 
        
           |  |  | 439 |     public function test_feedback_core_calendar_provide_event_action_can_not_submit_for_user() {
 | 
        
           |  |  | 440 |         global $DB;
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 |         $this->resetAfterTest();
 | 
        
           |  |  | 443 |         $this->setAdminUser();
 | 
        
           |  |  | 444 |   | 
        
           |  |  | 445 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 446 |         $user2 = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 447 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 448 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 449 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
 | 
        
           |  |  | 450 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 451 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 452 |         $context = \context_module::instance($cm->id);
 | 
        
           |  |  | 453 |         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id, 'manual');
 | 
        
           |  |  | 454 |   | 
        
           |  |  | 455 |         assign_capability('mod/feedback:complete', CAP_PROHIBIT, $studentrole->id, $context);
 | 
        
           |  |  | 456 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 457 |         $this->setUser($user2);
 | 
        
           |  |  | 458 |   | 
        
           |  |  | 459 |         // User2 checking their events.
 | 
        
           |  |  | 460 |   | 
        
           |  |  | 461 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user2->id);
 | 
        
           |  |  | 462 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 463 |   | 
        
           |  |  | 464 |         // User2 checking $user's events.
 | 
        
           |  |  | 465 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user->id);
 | 
        
           |  |  | 466 |   | 
        
           |  |  | 467 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 468 |     }
 | 
        
           |  |  | 469 |   | 
        
           |  |  | 470 |     /**
 | 
        
           |  |  | 471 |      * A user that has already submitted feedback should not have an action.
 | 
        
           |  |  | 472 |      */
 | 
        
           |  |  | 473 |     public function test_feedback_core_calendar_provide_event_action_already_submitted() {
 | 
        
           |  |  | 474 |         global $DB;
 | 
        
           |  |  | 475 |   | 
        
           |  |  | 476 |         $this->resetAfterTest();
 | 
        
           |  |  | 477 |         $this->setAdminUser();
 | 
        
           |  |  | 478 |   | 
        
           |  |  | 479 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 480 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 481 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 482 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
 | 
        
           |  |  | 483 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 484 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 485 |         $context = \context_module::instance($cm->id);
 | 
        
           |  |  | 486 |   | 
        
           |  |  | 487 |         $this->setUser($user);
 | 
        
           |  |  | 488 |   | 
        
           |  |  | 489 |         $record = [
 | 
        
           |  |  | 490 |             'feedback' => $feedback->id,
 | 
        
           |  |  | 491 |             'userid' => $user->id,
 | 
        
           |  |  | 492 |             'timemodified' => time(),
 | 
        
           |  |  | 493 |             'random_response' => 0,
 | 
        
           |  |  | 494 |             'anonymous_response' => FEEDBACK_ANONYMOUS_NO,
 | 
        
           |  |  | 495 |             'courseid' => 0,
 | 
        
           |  |  | 496 |         ];
 | 
        
           |  |  | 497 |         $DB->insert_record('feedback_completed', (object) $record);
 | 
        
           |  |  | 498 |   | 
        
           |  |  | 499 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 500 |         $action = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 501 |   | 
        
           |  |  | 502 |         $this->assertNull($action);
 | 
        
           |  |  | 503 |     }
 | 
        
           |  |  | 504 |   | 
        
           |  |  | 505 |     /**
 | 
        
           |  |  | 506 |      * A user that has already submitted feedback should not have an action, viewed by a different user.
 | 
        
           |  |  | 507 |      */
 | 
        
           |  |  | 508 |     public function test_feedback_core_calendar_provide_event_action_already_submitted_for_user() {
 | 
        
           |  |  | 509 |         global $DB;
 | 
        
           |  |  | 510 |   | 
        
           |  |  | 511 |         $this->resetAfterTest();
 | 
        
           |  |  | 512 |         $this->setAdminUser();
 | 
        
           |  |  | 513 |   | 
        
           |  |  | 514 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 515 |         $user2 = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 516 |         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 | 
        
           |  |  | 517 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 518 |         $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
 | 
        
           |  |  | 519 |         $event = $this->create_action_event($course->id, $feedback->id, FEEDBACK_EVENT_TYPE_OPEN);
 | 
        
           |  |  | 520 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 521 |         $context = \context_module::instance($cm->id);
 | 
        
           |  |  | 522 |   | 
        
           |  |  | 523 |         $this->setUser($user);
 | 
        
           |  |  | 524 |   | 
        
           |  |  | 525 |         $record = [
 | 
        
           |  |  | 526 |             'feedback' => $feedback->id,
 | 
        
           |  |  | 527 |             'userid' => $user->id,
 | 
        
           |  |  | 528 |             'timemodified' => time(),
 | 
        
           |  |  | 529 |             'random_response' => 0,
 | 
        
           |  |  | 530 |             'anonymous_response' => FEEDBACK_ANONYMOUS_NO,
 | 
        
           |  |  | 531 |             'courseid' => 0,
 | 
        
           |  |  | 532 |         ];
 | 
        
           |  |  | 533 |         $DB->insert_record('feedback_completed', (object) $record);
 | 
        
           |  |  | 534 |   | 
        
           |  |  | 535 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 536 |         $this->setUser($user2);
 | 
        
           |  |  | 537 |   | 
        
           |  |  | 538 |         // User2 checking their events.
 | 
        
           |  |  | 539 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user2->id);
 | 
        
           |  |  | 540 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 541 |   | 
        
           |  |  | 542 |         // User2 checking $user's events.
 | 
        
           |  |  | 543 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $user->id);
 | 
        
           |  |  | 544 |   | 
        
           |  |  | 545 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 546 |     }
 | 
        
           |  |  | 547 |   | 
        
           |  |  | 548 |     public function test_feedback_core_calendar_provide_event_action_already_completed() {
 | 
        
           |  |  | 549 |         $this->resetAfterTest();
 | 
        
           |  |  | 550 |         set_config('enablecompletion', 1);
 | 
        
           |  |  | 551 |         $this->setAdminUser();
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 |         // Create the activity.
 | 
        
           |  |  | 554 |         $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
 | 
        
           |  |  | 555 |         $feedback = $this->getDataGenerator()->create_module('feedback', array('course' => $course->id),
 | 
        
           |  |  | 556 |             array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
 | 
        
           |  |  | 557 |   | 
        
           |  |  | 558 |         // Get some additional data.
 | 
        
           |  |  | 559 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 560 |   | 
        
           |  |  | 561 |         // Create a calendar event.
 | 
        
           |  |  | 562 |         $event = $this->create_action_event($course->id, $feedback->id,
 | 
        
           |  |  | 563 |             \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 | 
        
           |  |  | 564 |   | 
        
           |  |  | 565 |         // Mark the activity as completed.
 | 
        
           |  |  | 566 |         $completion = new \completion_info($course);
 | 
        
           |  |  | 567 |         $completion->set_module_viewed($cm);
 | 
        
           |  |  | 568 |   | 
        
           |  |  | 569 |         // Create an action factory.
 | 
        
           |  |  | 570 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 571 |   | 
        
           |  |  | 572 |         // Decorate action event.
 | 
        
           |  |  | 573 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory);
 | 
        
           |  |  | 574 |   | 
        
           |  |  | 575 |         // Ensure result was null.
 | 
        
           |  |  | 576 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 577 |     }
 | 
        
           |  |  | 578 |   | 
        
           |  |  | 579 |     public function test_feedback_core_calendar_provide_event_action_already_completed_for_user() {
 | 
        
           |  |  | 580 |         $this->resetAfterTest();
 | 
        
           |  |  | 581 |         set_config('enablecompletion', 1);
 | 
        
           |  |  | 582 |         $this->setAdminUser();
 | 
        
           |  |  | 583 |   | 
        
           |  |  | 584 |         // Create the activity.
 | 
        
           |  |  | 585 |         $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
 | 
        
           |  |  | 586 |         $feedback = $this->getDataGenerator()->create_module('feedback', array('course' => $course->id),
 | 
        
           |  |  | 587 |             array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
 | 
        
           |  |  | 588 |   | 
        
           |  |  | 589 |         // Enrol a student in the course.
 | 
        
           |  |  | 590 |         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 | 
        
           |  |  | 591 |   | 
        
           |  |  | 592 |         // Get some additional data.
 | 
        
           |  |  | 593 |         $cm = get_coursemodule_from_instance('feedback', $feedback->id);
 | 
        
           |  |  | 594 |   | 
        
           |  |  | 595 |         // Create a calendar event.
 | 
        
           |  |  | 596 |         $event = $this->create_action_event($course->id, $feedback->id,
 | 
        
           |  |  | 597 |             \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 | 
        
           |  |  | 598 |   | 
        
           |  |  | 599 |         // Mark the activity as completed for the student.
 | 
        
           |  |  | 600 |         $completion = new \completion_info($course);
 | 
        
           |  |  | 601 |         $completion->set_module_viewed($cm, $student->id);
 | 
        
           |  |  | 602 |   | 
        
           |  |  | 603 |         // Create an action factory.
 | 
        
           |  |  | 604 |         $factory = new \core_calendar\action_factory();
 | 
        
           |  |  | 605 |   | 
        
           |  |  | 606 |         // Decorate action event for the student.
 | 
        
           |  |  | 607 |         $actionevent = mod_feedback_core_calendar_provide_event_action($event, $factory, $student->id);
 | 
        
           |  |  | 608 |   | 
        
           |  |  | 609 |         // Ensure result was null.
 | 
        
           |  |  | 610 |         $this->assertNull($actionevent);
 | 
        
           |  |  | 611 |     }
 | 
        
           |  |  | 612 |   | 
        
           |  |  | 613 |     /**
 | 
        
           |  |  | 614 |      * Creates an action event.
 | 
        
           |  |  | 615 |      *
 | 
        
           |  |  | 616 |      * @param int $courseid The course id.
 | 
        
           |  |  | 617 |      * @param int $instanceid The feedback id.
 | 
        
           |  |  | 618 |      * @param string $eventtype The event type. eg. FEEDBACK_EVENT_TYPE_OPEN.
 | 
        
           |  |  | 619 |      * @return bool|calendar_event
 | 
        
           |  |  | 620 |      */
 | 
        
           |  |  | 621 |     private function create_action_event($courseid, $instanceid, $eventtype) {
 | 
        
           |  |  | 622 |         $event = new \stdClass();
 | 
        
           |  |  | 623 |         $event->name = 'Calendar event';
 | 
        
           |  |  | 624 |         $event->modulename = 'feedback';
 | 
        
           |  |  | 625 |         $event->courseid = $courseid;
 | 
        
           |  |  | 626 |         $event->instance = $instanceid;
 | 
        
           |  |  | 627 |         $event->type = CALENDAR_EVENT_TYPE_ACTION;
 | 
        
           |  |  | 628 |         $event->eventtype = $eventtype;
 | 
        
           |  |  | 629 |         $event->timestart = time();
 | 
        
           |  |  | 630 |   | 
        
           |  |  | 631 |         return \calendar_event::create($event);
 | 
        
           |  |  | 632 |     }
 | 
        
           |  |  | 633 |   | 
        
           |  |  | 634 |     /**
 | 
        
           |  |  | 635 |      * Test the callback responsible for returning the completion rule descriptions.
 | 
        
           |  |  | 636 |      * This function should work given either an instance of the module (cm_info), such as when checking the active rules,
 | 
        
           |  |  | 637 |      * or if passed a stdClass of similar structure, such as when checking the the default completion settings for a mod type.
 | 
        
           |  |  | 638 |      */
 | 
        
           |  |  | 639 |     public function test_mod_feedback_completion_get_active_rule_descriptions() {
 | 
        
           |  |  | 640 |         $this->resetAfterTest();
 | 
        
           |  |  | 641 |         $this->setAdminUser();
 | 
        
           |  |  | 642 |   | 
        
           |  |  | 643 |         // Two activities, both with automatic completion. One has the 'completionsubmit' rule, one doesn't.
 | 
        
           |  |  | 644 |         $course = $this->getDataGenerator()->create_course(['enablecompletion' => 2]);
 | 
        
           |  |  | 645 |         $feedback1 = $this->getDataGenerator()->create_module('feedback', [
 | 
        
           |  |  | 646 |             'course' => $course->id,
 | 
        
           |  |  | 647 |             'completion' => 2,
 | 
        
           |  |  | 648 |             'completionsubmit' => 1
 | 
        
           |  |  | 649 |         ]);
 | 
        
           |  |  | 650 |         $feedback2 = $this->getDataGenerator()->create_module('feedback', [
 | 
        
           |  |  | 651 |             'course' => $course->id,
 | 
        
           |  |  | 652 |             'completion' => 2,
 | 
        
           |  |  | 653 |             'completionsubmit' => 0
 | 
        
           |  |  | 654 |         ]);
 | 
        
           |  |  | 655 |         $cm1 = \cm_info::create(get_coursemodule_from_instance('feedback', $feedback1->id));
 | 
        
           |  |  | 656 |         $cm2 = \cm_info::create(get_coursemodule_from_instance('feedback', $feedback2->id));
 | 
        
           |  |  | 657 |   | 
        
           |  |  | 658 |         // Data for the stdClass input type.
 | 
        
           |  |  | 659 |         // This type of input would occur when checking the default completion rules for an activity type, where we don't have
 | 
        
           |  |  | 660 |         // any access to cm_info, rather the input is a stdClass containing completion and customdata attributes, just like cm_info.
 | 
        
           |  |  | 661 |         $moddefaults = new \stdClass();
 | 
        
           |  |  | 662 |         $moddefaults->customdata = ['customcompletionrules' => ['completionsubmit' => 1]];
 | 
        
           |  |  | 663 |         $moddefaults->completion = 2;
 | 
        
           |  |  | 664 |   | 
        
           |  |  | 665 |         $activeruledescriptions = [get_string('completionsubmit', 'feedback')];
 | 
        
           |  |  | 666 |         $this->assertEquals(mod_feedback_get_completion_active_rule_descriptions($cm1), $activeruledescriptions);
 | 
        
           |  |  | 667 |         $this->assertEquals(mod_feedback_get_completion_active_rule_descriptions($cm2), []);
 | 
        
           |  |  | 668 |         $this->assertEquals(mod_feedback_get_completion_active_rule_descriptions($moddefaults), $activeruledescriptions);
 | 
        
           |  |  | 669 |         $this->assertEquals(mod_feedback_get_completion_active_rule_descriptions(new \stdClass()), []);
 | 
        
           |  |  | 670 |     }
 | 
        
           |  |  | 671 |   | 
        
           |  |  | 672 |     /**
 | 
        
           |  |  | 673 |      * An unknown event should not have min or max restrictions.
 | 
        
           |  |  | 674 |      */
 | 
        
           |  |  | 675 |     public function test_get_valid_event_timestart_range_unknown_event() {
 | 
        
           |  |  | 676 |         global $CFG, $DB;
 | 
        
           |  |  | 677 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 678 |   | 
        
           |  |  | 679 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 680 |         $this->setAdminUser();
 | 
        
           |  |  | 681 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 682 |         $course = $generator->create_course();
 | 
        
           |  |  | 683 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 684 |         $timeopen = time();
 | 
        
           |  |  | 685 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 686 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 687 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 688 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 689 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 690 |   | 
        
           |  |  | 691 |         $event = new \calendar_event([
 | 
        
           |  |  | 692 |             'name' => 'Test event',
 | 
        
           |  |  | 693 |             'description' => '',
 | 
        
           |  |  | 694 |             'format' => 1,
 | 
        
           |  |  | 695 |             'courseid' => $course->id,
 | 
        
           |  |  | 696 |             'groupid' => 0,
 | 
        
           |  |  | 697 |             'userid' => 2,
 | 
        
           |  |  | 698 |             'modulename' => 'feedback',
 | 
        
           |  |  | 699 |             'instance' => $feedback->id,
 | 
        
           |  |  | 700 |             'eventtype' => 'SOME UNKNOWN EVENT',
 | 
        
           |  |  | 701 |             'timestart' => $timeopen,
 | 
        
           |  |  | 702 |             'timeduration' => 86400,
 | 
        
           |  |  | 703 |             'visible' => 1
 | 
        
           |  |  | 704 |         ]);
 | 
        
           |  |  | 705 |   | 
        
           |  |  | 706 |         list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
 | 
        
           |  |  | 707 |         $this->assertNull($min);
 | 
        
           |  |  | 708 |         $this->assertNull($max);
 | 
        
           |  |  | 709 |     }
 | 
        
           |  |  | 710 |   | 
        
           |  |  | 711 |     /**
 | 
        
           |  |  | 712 |      * A FEEDBACK_EVENT_TYPE_OPEN should have a max timestart equal to the activity
 | 
        
           |  |  | 713 |      * close time.
 | 
        
           |  |  | 714 |      */
 | 
        
           |  |  | 715 |     public function test_get_valid_event_timestart_range_event_type_open() {
 | 
        
           |  |  | 716 |         global $CFG, $DB;
 | 
        
           |  |  | 717 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 718 |   | 
        
           |  |  | 719 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 720 |         $this->setAdminUser();
 | 
        
           |  |  | 721 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 722 |         $course = $generator->create_course();
 | 
        
           |  |  | 723 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 724 |         $timeopen = time();
 | 
        
           |  |  | 725 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 726 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 727 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 728 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 729 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 730 |   | 
        
           |  |  | 731 |         $event = new \calendar_event([
 | 
        
           |  |  | 732 |             'name' => 'Test event',
 | 
        
           |  |  | 733 |             'description' => '',
 | 
        
           |  |  | 734 |             'format' => 1,
 | 
        
           |  |  | 735 |             'courseid' => $course->id,
 | 
        
           |  |  | 736 |             'groupid' => 0,
 | 
        
           |  |  | 737 |             'userid' => 2,
 | 
        
           |  |  | 738 |             'modulename' => 'feedback',
 | 
        
           |  |  | 739 |             'instance' => $feedback->id,
 | 
        
           |  |  | 740 |             'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
 | 
        
           |  |  | 741 |             'timestart' => $timeopen,
 | 
        
           |  |  | 742 |             'timeduration' => 86400,
 | 
        
           |  |  | 743 |             'visible' => 1
 | 
        
           |  |  | 744 |         ]);
 | 
        
           |  |  | 745 |   | 
        
           |  |  | 746 |         list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
 | 
        
           |  |  | 747 |         $this->assertNull($min);
 | 
        
           |  |  | 748 |         $this->assertEquals($timeclose, $max[0]);
 | 
        
           |  |  | 749 |         $this->assertNotEmpty($max[1]);
 | 
        
           |  |  | 750 |     }
 | 
        
           |  |  | 751 |   | 
        
           |  |  | 752 |     /**
 | 
        
           |  |  | 753 |      * A FEEDBACK_EVENT_TYPE_OPEN should not have a max timestamp if the activity
 | 
        
           |  |  | 754 |      * doesn't have a close date.
 | 
        
           |  |  | 755 |      */
 | 
        
           |  |  | 756 |     public function test_get_valid_event_timestart_range_event_type_open_no_close() {
 | 
        
           |  |  | 757 |         global $CFG, $DB;
 | 
        
           |  |  | 758 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 759 |   | 
        
           |  |  | 760 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 761 |         $this->setAdminUser();
 | 
        
           |  |  | 762 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 763 |         $course = $generator->create_course();
 | 
        
           |  |  | 764 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 765 |         $timeopen = time();
 | 
        
           |  |  | 766 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 767 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 768 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 769 |         $feedback->timeclose = 0;
 | 
        
           |  |  | 770 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 771 |   | 
        
           |  |  | 772 |         $event = new \calendar_event([
 | 
        
           |  |  | 773 |             'name' => 'Test event',
 | 
        
           |  |  | 774 |             'description' => '',
 | 
        
           |  |  | 775 |             'format' => 1,
 | 
        
           |  |  | 776 |             'courseid' => $course->id,
 | 
        
           |  |  | 777 |             'groupid' => 0,
 | 
        
           |  |  | 778 |             'userid' => 2,
 | 
        
           |  |  | 779 |             'modulename' => 'feedback',
 | 
        
           |  |  | 780 |             'instance' => $feedback->id,
 | 
        
           |  |  | 781 |             'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
 | 
        
           |  |  | 782 |             'timestart' => $timeopen,
 | 
        
           |  |  | 783 |             'timeduration' => 86400,
 | 
        
           |  |  | 784 |             'visible' => 1
 | 
        
           |  |  | 785 |         ]);
 | 
        
           |  |  | 786 |   | 
        
           |  |  | 787 |         list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
 | 
        
           |  |  | 788 |         $this->assertNull($min);
 | 
        
           |  |  | 789 |         $this->assertNull($max);
 | 
        
           |  |  | 790 |     }
 | 
        
           |  |  | 791 |   | 
        
           |  |  | 792 |     /**
 | 
        
           |  |  | 793 |      * A FEEDBACK_EVENT_TYPE_CLOSE should have a min timestart equal to the activity
 | 
        
           |  |  | 794 |      * open time.
 | 
        
           |  |  | 795 |      */
 | 
        
           |  |  | 796 |     public function test_get_valid_event_timestart_range_event_type_close() {
 | 
        
           |  |  | 797 |         global $CFG, $DB;
 | 
        
           |  |  | 798 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 799 |   | 
        
           |  |  | 800 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 801 |         $this->setAdminUser();
 | 
        
           |  |  | 802 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 803 |         $course = $generator->create_course();
 | 
        
           |  |  | 804 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 805 |         $timeopen = time();
 | 
        
           |  |  | 806 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 807 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 808 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 809 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 810 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 811 |   | 
        
           |  |  | 812 |         $event = new \calendar_event([
 | 
        
           |  |  | 813 |             'name' => 'Test event',
 | 
        
           |  |  | 814 |             'description' => '',
 | 
        
           |  |  | 815 |             'format' => 1,
 | 
        
           |  |  | 816 |             'courseid' => $course->id,
 | 
        
           |  |  | 817 |             'groupid' => 0,
 | 
        
           |  |  | 818 |             'userid' => 2,
 | 
        
           |  |  | 819 |             'modulename' => 'feedback',
 | 
        
           |  |  | 820 |             'instance' => $feedback->id,
 | 
        
           |  |  | 821 |             'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
 | 
        
           |  |  | 822 |             'timestart' => $timeopen,
 | 
        
           |  |  | 823 |             'timeduration' => 86400,
 | 
        
           |  |  | 824 |             'visible' => 1
 | 
        
           |  |  | 825 |         ]);
 | 
        
           |  |  | 826 |   | 
        
           |  |  | 827 |         list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
 | 
        
           |  |  | 828 |         $this->assertEquals($timeopen, $min[0]);
 | 
        
           |  |  | 829 |         $this->assertNotEmpty($min[1]);
 | 
        
           |  |  | 830 |         $this->assertNull($max);
 | 
        
           |  |  | 831 |     }
 | 
        
           |  |  | 832 |   | 
        
           |  |  | 833 |     /**
 | 
        
           |  |  | 834 |      * A FEEDBACK_EVENT_TYPE_CLOSE should not have a minimum timestamp if the activity
 | 
        
           |  |  | 835 |      * doesn't have an open date.
 | 
        
           |  |  | 836 |      */
 | 
        
           |  |  | 837 |     public function test_get_valid_event_timestart_range_event_type_close_no_open() {
 | 
        
           |  |  | 838 |         global $CFG, $DB;
 | 
        
           |  |  | 839 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 840 |   | 
        
           |  |  | 841 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 842 |         $this->setAdminUser();
 | 
        
           |  |  | 843 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 844 |         $course = $generator->create_course();
 | 
        
           |  |  | 845 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 846 |         $timeopen = time();
 | 
        
           |  |  | 847 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 848 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 849 |         $feedback->timeopen = 0;
 | 
        
           |  |  | 850 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 851 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 852 |   | 
        
           |  |  | 853 |         $event = new \calendar_event([
 | 
        
           |  |  | 854 |             'name' => 'Test event',
 | 
        
           |  |  | 855 |             'description' => '',
 | 
        
           |  |  | 856 |             'format' => 1,
 | 
        
           |  |  | 857 |             'courseid' => $course->id,
 | 
        
           |  |  | 858 |             'groupid' => 0,
 | 
        
           |  |  | 859 |             'userid' => 2,
 | 
        
           |  |  | 860 |             'modulename' => 'feedback',
 | 
        
           |  |  | 861 |             'instance' => $feedback->id,
 | 
        
           |  |  | 862 |             'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
 | 
        
           |  |  | 863 |             'timestart' => $timeopen,
 | 
        
           |  |  | 864 |             'timeduration' => 86400,
 | 
        
           |  |  | 865 |             'visible' => 1
 | 
        
           |  |  | 866 |         ]);
 | 
        
           |  |  | 867 |   | 
        
           |  |  | 868 |         list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
 | 
        
           |  |  | 869 |         $this->assertNull($min);
 | 
        
           |  |  | 870 |         $this->assertNull($max);
 | 
        
           |  |  | 871 |     }
 | 
        
           |  |  | 872 |   | 
        
           |  |  | 873 |     /**
 | 
        
           |  |  | 874 |      * An unkown event type should not change the feedback instance.
 | 
        
           |  |  | 875 |      */
 | 
        
           |  |  | 876 |     public function test_mod_feedback_core_calendar_event_timestart_updated_unknown_event() {
 | 
        
           |  |  | 877 |         global $CFG, $DB;
 | 
        
           |  |  | 878 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 879 |   | 
        
           |  |  | 880 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 881 |         $this->setAdminUser();
 | 
        
           |  |  | 882 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 883 |         $course = $generator->create_course();
 | 
        
           |  |  | 884 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 885 |         $timeopen = time();
 | 
        
           |  |  | 886 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 887 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 888 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 889 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 890 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 891 |   | 
        
           |  |  | 892 |         // Create a valid event.
 | 
        
           |  |  | 893 |         $event = new \calendar_event([
 | 
        
           |  |  | 894 |             'name' => 'Test event',
 | 
        
           |  |  | 895 |             'description' => '',
 | 
        
           |  |  | 896 |             'format' => 1,
 | 
        
           |  |  | 897 |             'courseid' => $course->id,
 | 
        
           |  |  | 898 |             'groupid' => 0,
 | 
        
           |  |  | 899 |             'userid' => 2,
 | 
        
           |  |  | 900 |             'modulename' => 'feedback',
 | 
        
           |  |  | 901 |             'instance' => $feedback->id,
 | 
        
           |  |  | 902 |             'eventtype' => FEEDBACK_EVENT_TYPE_OPEN . "SOMETHING ELSE",
 | 
        
           |  |  | 903 |             'timestart' => 1,
 | 
        
           |  |  | 904 |             'timeduration' => 86400,
 | 
        
           |  |  | 905 |             'visible' => 1
 | 
        
           |  |  | 906 |         ]);
 | 
        
           |  |  | 907 |   | 
        
           |  |  | 908 |         mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
 | 
        
           |  |  | 909 |   | 
        
           |  |  | 910 |         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
 | 
        
           |  |  | 911 |         $this->assertEquals($timeopen, $feedback->timeopen);
 | 
        
           |  |  | 912 |         $this->assertEquals($timeclose, $feedback->timeclose);
 | 
        
           |  |  | 913 |     }
 | 
        
           |  |  | 914 |   | 
        
           |  |  | 915 |     /**
 | 
        
           |  |  | 916 |      * A FEEDBACK_EVENT_TYPE_OPEN event should update the timeopen property of
 | 
        
           |  |  | 917 |      * the feedback activity.
 | 
        
           |  |  | 918 |      */
 | 
        
           |  |  | 919 |     public function test_mod_feedback_core_calendar_event_timestart_updated_open_event() {
 | 
        
           |  |  | 920 |         global $CFG, $DB;
 | 
        
           |  |  | 921 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 922 |   | 
        
           |  |  | 923 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 924 |         $this->setAdminUser();
 | 
        
           |  |  | 925 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 926 |         $course = $generator->create_course();
 | 
        
           |  |  | 927 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 928 |         $timeopen = time();
 | 
        
           |  |  | 929 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 930 |         $timemodified = 1;
 | 
        
           |  |  | 931 |         $newtimeopen = $timeopen - DAYSECS;
 | 
        
           |  |  | 932 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 933 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 934 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 935 |         $feedback->timemodified = $timemodified;
 | 
        
           |  |  | 936 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 937 |   | 
        
           |  |  | 938 |         // Create a valid event.
 | 
        
           |  |  | 939 |         $event = new \calendar_event([
 | 
        
           |  |  | 940 |             'name' => 'Test event',
 | 
        
           |  |  | 941 |             'description' => '',
 | 
        
           |  |  | 942 |             'format' => 1,
 | 
        
           |  |  | 943 |             'courseid' => $course->id,
 | 
        
           |  |  | 944 |             'groupid' => 0,
 | 
        
           |  |  | 945 |             'userid' => 2,
 | 
        
           |  |  | 946 |             'modulename' => 'feedback',
 | 
        
           |  |  | 947 |             'instance' => $feedback->id,
 | 
        
           |  |  | 948 |             'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
 | 
        
           |  |  | 949 |             'timestart' => $newtimeopen,
 | 
        
           |  |  | 950 |             'timeduration' => 86400,
 | 
        
           |  |  | 951 |             'visible' => 1
 | 
        
           |  |  | 952 |         ]);
 | 
        
           |  |  | 953 |   | 
        
           |  |  | 954 |         mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
 | 
        
           |  |  | 955 |   | 
        
           |  |  | 956 |         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
 | 
        
           |  |  | 957 |         // Ensure the timeopen property matches the event timestart.
 | 
        
           |  |  | 958 |         $this->assertEquals($newtimeopen, $feedback->timeopen);
 | 
        
           |  |  | 959 |         // Ensure the timeclose isn't changed.
 | 
        
           |  |  | 960 |         $this->assertEquals($timeclose, $feedback->timeclose);
 | 
        
           |  |  | 961 |         // Ensure the timemodified property has been changed.
 | 
        
           |  |  | 962 |         $this->assertNotEquals($timemodified, $feedback->timemodified);
 | 
        
           |  |  | 963 |     }
 | 
        
           |  |  | 964 |   | 
        
           |  |  | 965 |     /**
 | 
        
           |  |  | 966 |      * A FEEDBACK_EVENT_TYPE_CLOSE event should update the timeclose property of
 | 
        
           |  |  | 967 |      * the feedback activity.
 | 
        
           |  |  | 968 |      */
 | 
        
           |  |  | 969 |     public function test_mod_feedback_core_calendar_event_timestart_updated_close_event() {
 | 
        
           |  |  | 970 |         global $CFG, $DB;
 | 
        
           |  |  | 971 |         require_once($CFG->dirroot . "/calendar/lib.php");
 | 
        
           |  |  | 972 |   | 
        
           |  |  | 973 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 974 |         $this->setAdminUser();
 | 
        
           |  |  | 975 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 976 |         $course = $generator->create_course();
 | 
        
           |  |  | 977 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 978 |         $timeopen = time();
 | 
        
           |  |  | 979 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 980 |         $timemodified = 1;
 | 
        
           |  |  | 981 |         $newtimeclose = $timeclose + DAYSECS;
 | 
        
           |  |  | 982 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 983 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 984 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 985 |         $feedback->timemodified = $timemodified;
 | 
        
           |  |  | 986 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 987 |   | 
        
           |  |  | 988 |         // Create a valid event.
 | 
        
           |  |  | 989 |         $event = new \calendar_event([
 | 
        
           |  |  | 990 |             'name' => 'Test event',
 | 
        
           |  |  | 991 |             'description' => '',
 | 
        
           |  |  | 992 |             'format' => 1,
 | 
        
           |  |  | 993 |             'courseid' => $course->id,
 | 
        
           |  |  | 994 |             'groupid' => 0,
 | 
        
           |  |  | 995 |             'userid' => 2,
 | 
        
           |  |  | 996 |             'modulename' => 'feedback',
 | 
        
           |  |  | 997 |             'instance' => $feedback->id,
 | 
        
           |  |  | 998 |             'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
 | 
        
           |  |  | 999 |             'timestart' => $newtimeclose,
 | 
        
           |  |  | 1000 |             'timeduration' => 86400,
 | 
        
           |  |  | 1001 |             'visible' => 1
 | 
        
           |  |  | 1002 |         ]);
 | 
        
           |  |  | 1003 |   | 
        
           |  |  | 1004 |         mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
 | 
        
           |  |  | 1005 |   | 
        
           |  |  | 1006 |         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
 | 
        
           |  |  | 1007 |         // Ensure the timeclose property matches the event timestart.
 | 
        
           |  |  | 1008 |         $this->assertEquals($newtimeclose, $feedback->timeclose);
 | 
        
           |  |  | 1009 |         // Ensure the timeopen isn't changed.
 | 
        
           |  |  | 1010 |         $this->assertEquals($timeopen, $feedback->timeopen);
 | 
        
           |  |  | 1011 |         // Ensure the timemodified property has been changed.
 | 
        
           |  |  | 1012 |         $this->assertNotEquals($timemodified, $feedback->timemodified);
 | 
        
           |  |  | 1013 |     }
 | 
        
           |  |  | 1014 |   | 
        
           |  |  | 1015 |     /**
 | 
        
           |  |  | 1016 |      * If a student somehow finds a way to update the calendar event
 | 
        
           |  |  | 1017 |      * then the callback should not be executed to update the activity
 | 
        
           |  |  | 1018 |      * properties as well because that would be a security issue.
 | 
        
           |  |  | 1019 |      */
 | 
        
           |  |  | 1020 |     public function test_student_role_cant_update_time_close_event() {
 | 
        
           |  |  | 1021 |         global $CFG, $DB;
 | 
        
           |  |  | 1022 |         require_once($CFG->dirroot . '/calendar/lib.php');
 | 
        
           |  |  | 1023 |   | 
        
           |  |  | 1024 |         $this->resetAfterTest();
 | 
        
           |  |  | 1025 |         $this->setAdminUser();
 | 
        
           |  |  | 1026 |   | 
        
           |  |  | 1027 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 1028 |         $user = $generator->create_user();
 | 
        
           |  |  | 1029 |         $course = $generator->create_course();
 | 
        
           |  |  | 1030 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 1031 |         $roleid = $generator->create_role();
 | 
        
           |  |  | 1032 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 1033 |         $timeopen = time();
 | 
        
           |  |  | 1034 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 1035 |         $timemodified = 1;
 | 
        
           |  |  | 1036 |         $newtimeclose = $timeclose + DAYSECS;
 | 
        
           |  |  | 1037 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 1038 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 1039 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 1040 |         $feedback->timemodified = $timemodified;
 | 
        
           |  |  | 1041 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 1042 |   | 
        
           |  |  | 1043 |         $generator->enrol_user($user->id, $course->id, 'student');
 | 
        
           |  |  | 1044 |         $generator->role_assign($roleid, $user->id, $context->id);
 | 
        
           |  |  | 1045 |   | 
        
           |  |  | 1046 |         // Create a valid event.
 | 
        
           |  |  | 1047 |         $event = new \calendar_event([
 | 
        
           |  |  | 1048 |             'name' => 'Test event',
 | 
        
           |  |  | 1049 |             'description' => '',
 | 
        
           |  |  | 1050 |             'format' => 1,
 | 
        
           |  |  | 1051 |             'courseid' => $course->id,
 | 
        
           |  |  | 1052 |             'groupid' => 0,
 | 
        
           |  |  | 1053 |             'userid' => $user->id,
 | 
        
           |  |  | 1054 |             'modulename' => 'feedback',
 | 
        
           |  |  | 1055 |             'instance' => $feedback->id,
 | 
        
           |  |  | 1056 |             'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
 | 
        
           |  |  | 1057 |             'timestart' => $newtimeclose,
 | 
        
           |  |  | 1058 |             'timeduration' => 86400,
 | 
        
           |  |  | 1059 |             'visible' => 1
 | 
        
           |  |  | 1060 |         ]);
 | 
        
           |  |  | 1061 |   | 
        
           |  |  | 1062 |         assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 | 
        
           |  |  | 1063 |         assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $roleid, $context, true);
 | 
        
           |  |  | 1064 |   | 
        
           |  |  | 1065 |         $this->setUser($user);
 | 
        
           |  |  | 1066 |   | 
        
           |  |  | 1067 |         mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
 | 
        
           |  |  | 1068 |   | 
        
           |  |  | 1069 |         $newfeedback = $DB->get_record('feedback', ['id' => $feedback->id]);
 | 
        
           |  |  | 1070 |         // The activity shouldn't have been updated because the user
 | 
        
           |  |  | 1071 |         // doesn't have permissions to do it.
 | 
        
           |  |  | 1072 |         $this->assertEquals($timeclose, $newfeedback->timeclose);
 | 
        
           |  |  | 1073 |     }
 | 
        
           |  |  | 1074 |   | 
        
           |  |  | 1075 |     /**
 | 
        
           |  |  | 1076 |      * The activity should update if a teacher modifies the calendar
 | 
        
           |  |  | 1077 |      * event.
 | 
        
           |  |  | 1078 |      */
 | 
        
           |  |  | 1079 |     public function test_teacher_role_can_update_time_close_event() {
 | 
        
           |  |  | 1080 |         global $CFG, $DB;
 | 
        
           |  |  | 1081 |         require_once($CFG->dirroot . '/calendar/lib.php');
 | 
        
           |  |  | 1082 |   | 
        
           |  |  | 1083 |         $this->resetAfterTest();
 | 
        
           |  |  | 1084 |         $this->setAdminUser();
 | 
        
           |  |  | 1085 |   | 
        
           |  |  | 1086 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 1087 |         $user = $generator->create_user();
 | 
        
           |  |  | 1088 |         $course = $generator->create_course();
 | 
        
           |  |  | 1089 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 1090 |         $roleid = $generator->create_role();
 | 
        
           |  |  | 1091 |         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 1092 |         $timeopen = time();
 | 
        
           |  |  | 1093 |         $timeclose = $timeopen + DAYSECS;
 | 
        
           |  |  | 1094 |         $timemodified = 1;
 | 
        
           |  |  | 1095 |         $newtimeclose = $timeclose + DAYSECS;
 | 
        
           |  |  | 1096 |         $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
 | 
        
           |  |  | 1097 |         $feedback->timeopen = $timeopen;
 | 
        
           |  |  | 1098 |         $feedback->timeclose = $timeclose;
 | 
        
           |  |  | 1099 |         $feedback->timemodified = $timemodified;
 | 
        
           |  |  | 1100 |         $DB->update_record('feedback', $feedback);
 | 
        
           |  |  | 1101 |   | 
        
           |  |  | 1102 |         $generator->enrol_user($user->id, $course->id, 'teacher');
 | 
        
           |  |  | 1103 |         $generator->role_assign($roleid, $user->id, $context->id);
 | 
        
           |  |  | 1104 |   | 
        
           |  |  | 1105 |         // Create a valid event.
 | 
        
           |  |  | 1106 |         $event = new \calendar_event([
 | 
        
           |  |  | 1107 |             'name' => 'Test event',
 | 
        
           |  |  | 1108 |             'description' => '',
 | 
        
           |  |  | 1109 |             'format' => 1,
 | 
        
           |  |  | 1110 |             'courseid' => $course->id,
 | 
        
           |  |  | 1111 |             'groupid' => 0,
 | 
        
           |  |  | 1112 |             'userid' => $user->id,
 | 
        
           |  |  | 1113 |             'modulename' => 'feedback',
 | 
        
           |  |  | 1114 |             'instance' => $feedback->id,
 | 
        
           |  |  | 1115 |             'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
 | 
        
           |  |  | 1116 |             'timestart' => $newtimeclose,
 | 
        
           |  |  | 1117 |             'timeduration' => 86400,
 | 
        
           |  |  | 1118 |             'visible' => 1
 | 
        
           |  |  | 1119 |         ]);
 | 
        
           |  |  | 1120 |   | 
        
           |  |  | 1121 |         assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 | 
        
           |  |  | 1122 |         assign_capability('moodle/course:manageactivities', CAP_ALLOW, $roleid, $context, true);
 | 
        
           |  |  | 1123 |   | 
        
           |  |  | 1124 |         $this->setUser($user);
 | 
        
           |  |  | 1125 |   | 
        
           |  |  | 1126 |         $sink = $this->redirectEvents();
 | 
        
           |  |  | 1127 |   | 
        
           |  |  | 1128 |         mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
 | 
        
           |  |  | 1129 |   | 
        
           |  |  | 1130 |         $triggeredevents = $sink->get_events();
 | 
        
           |  |  | 1131 |         $moduleupdatedevents = array_filter($triggeredevents, function($e) {
 | 
        
           |  |  | 1132 |             return is_a($e, 'core\event\course_module_updated');
 | 
        
           |  |  | 1133 |         });
 | 
        
           |  |  | 1134 |   | 
        
           |  |  | 1135 |         $newfeedback = $DB->get_record('feedback', ['id' => $feedback->id]);
 | 
        
           |  |  | 1136 |         // The activity should have been updated because the user
 | 
        
           |  |  | 1137 |         // has permissions to do it.
 | 
        
           |  |  | 1138 |         $this->assertEquals($newtimeclose, $newfeedback->timeclose);
 | 
        
           |  |  | 1139 |         // A course_module_updated event should be fired if the module
 | 
        
           |  |  | 1140 |         // was successfully modified.
 | 
        
           |  |  | 1141 |         $this->assertNotEmpty($moduleupdatedevents);
 | 
        
           |  |  | 1142 |     }
 | 
        
           |  |  | 1143 |   | 
        
           |  |  | 1144 |     /**
 | 
        
           |  |  | 1145 |      * A user who does not have capabilities to add events to the calendar should be able to create an feedback.
 | 
        
           |  |  | 1146 |      */
 | 
        
           |  |  | 1147 |     public function test_creation_with_no_calendar_capabilities() {
 | 
        
           |  |  | 1148 |         $this->resetAfterTest();
 | 
        
           |  |  | 1149 |         $course = self::getDataGenerator()->create_course();
 | 
        
           |  |  | 1150 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 1151 |         $user = self::getDataGenerator()->create_and_enrol($course, 'editingteacher');
 | 
        
           |  |  | 1152 |         $roleid = self::getDataGenerator()->create_role();
 | 
        
           |  |  | 1153 |         self::getDataGenerator()->role_assign($roleid, $user->id, $context->id);
 | 
        
           |  |  | 1154 |         assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
 | 
        
           |  |  | 1155 |         $generator = self::getDataGenerator()->get_plugin_generator('mod_feedback');
 | 
        
           |  |  | 1156 |         // Create an instance as a user without the calendar capabilities.
 | 
        
           |  |  | 1157 |         $this->setUser($user);
 | 
        
           |  |  | 1158 |         $time = time();
 | 
        
           |  |  | 1159 |         $params = array(
 | 
        
           |  |  | 1160 |             'course' => $course->id,
 | 
        
           |  |  | 1161 |             'timeopen' => $time + 200,
 | 
        
           |  |  | 1162 |             'timeclose' => $time + 2000,
 | 
        
           |  |  | 1163 |         );
 | 
        
           |  |  | 1164 |         $generator->create_instance($params);
 | 
        
           |  |  | 1165 |     }
 | 
        
           |  |  | 1166 | }
 |