Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 311 and 401] [Versions 401 and 402] [Versions 401 and 403]

   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  /**
  18   * Contains the event tests for the module assign.
  19   *
  20   * @package   mod_assign
  21   * @copyright 2014 Adrian Greeve <adrian@moodle.com>
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace mod_assign\event;
  26  
  27  use mod_assign_test_generator;
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  global $CFG;
  32  require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
  33  require_once($CFG->dirroot . '/mod/assign/tests/fixtures/event_mod_assign_fixtures.php');
  34  require_once($CFG->dirroot . '/mod/assign/locallib.php');
  35  
  36  /**
  37   * Contains the event tests for the module assign.
  38   *
  39   * @package   mod_assign
  40   * @copyright 2014 Adrian Greeve <adrian@moodle.com>
  41   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class events_test extends \advanced_testcase {
  44      // Use the generator helper.
  45      use mod_assign_test_generator;
  46  
  47      /**
  48       * Basic tests for the submission_created() abstract class.
  49       */
  50      public function test_base_event() {
  51          $this->resetAfterTest();
  52  
  53          $course = $this->getDataGenerator()->create_course();
  54          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  55          $instance = $generator->create_instance(array('course' => $course->id));
  56          $modcontext = \context_module::instance($instance->cmid);
  57  
  58          $data = array(
  59              'context' => $modcontext,
  60          );
  61  
  62          $event = \mod_assign_unittests\event\nothing_happened::create($data);
  63          $assign = $event->get_assign();
  64          $this->assertDebuggingCalled();
  65          $this->assertInstanceOf('assign', $assign);
  66  
  67          $event = \mod_assign_unittests\event\nothing_happened::create($data);
  68          $event->set_assign($assign);
  69          $assign2 = $event->get_assign();
  70          $this->assertDebuggingNotCalled();
  71          $this->assertSame($assign, $assign2);
  72      }
  73  
  74      /**
  75       * Basic tests for the submission_created() abstract class.
  76       */
  77      public function test_submission_created() {
  78          $this->resetAfterTest();
  79  
  80          $course = $this->getDataGenerator()->create_course();
  81          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  82          $instance = $generator->create_instance(array('course' => $course->id));
  83          $modcontext = \context_module::instance($instance->cmid);
  84  
  85          // Standard Event parameters.
  86          $params = array(
  87              'context' => $modcontext,
  88              'courseid' => $course->id
  89          );
  90  
  91          $eventinfo = $params;
  92          $eventinfo['other'] = array(
  93              'submissionid' => '17',
  94              'submissionattempt' => 0,
  95              'submissionstatus' => 'submitted'
  96          );
  97  
  98          $sink = $this->redirectEvents();
  99          $event = \mod_assign_unittests\event\submission_created::create($eventinfo);
 100          $event->trigger();
 101          $result = $sink->get_events();
 102          $event = reset($result);
 103          $sink->close();
 104  
 105          $this->assertEquals($modcontext->id, $event->contextid);
 106          $this->assertEquals($course->id, $event->courseid);
 107  
 108          // Check that an error occurs when teamsubmission is not set.
 109          try {
 110              \mod_assign_unittests\event\submission_created::create($params);
 111              $this->fail('Other must contain the key submissionid.');
 112          } catch (\Exception $e) {
 113              $this->assertInstanceOf('coding_exception', $e);
 114          }
 115          // Check that the submission status debugging is fired.
 116          $subinfo = $params;
 117          $subinfo['other'] = array('submissionid' => '23');
 118          try {
 119              \mod_assign_unittests\event\submission_created::create($subinfo);
 120              $this->fail('Other must contain the key submissionattempt.');
 121          } catch (\Exception $e) {
 122              $this->assertInstanceOf('coding_exception', $e);
 123          }
 124  
 125          $subinfo['other'] = array('submissionattempt' => '0');
 126          try {
 127              \mod_assign_unittests\event\submission_created::create($subinfo);
 128              $this->fail('Other must contain the key submissionstatus.');
 129          } catch (\Exception $e) {
 130              $this->assertInstanceOf('coding_exception', $e);
 131          }
 132      }
 133  
 134      /**
 135       * Basic tests for the submission_updated() abstract class.
 136       */
 137      public function test_submission_updated() {
 138          $this->resetAfterTest();
 139  
 140          $course = $this->getDataGenerator()->create_course();
 141          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 142          $instance = $generator->create_instance(array('course' => $course->id));
 143          $modcontext = \context_module::instance($instance->cmid);
 144  
 145          // Standard Event parameters.
 146          $params = array(
 147              'context' => $modcontext,
 148              'courseid' => $course->id
 149          );
 150  
 151          $eventinfo = $params;
 152          $eventinfo['other'] = array(
 153              'submissionid' => '17',
 154              'submissionattempt' => 0,
 155              'submissionstatus' => 'submitted'
 156          );
 157  
 158          $sink = $this->redirectEvents();
 159          $event = \mod_assign_unittests\event\submission_updated::create($eventinfo);
 160          $event->trigger();
 161          $result = $sink->get_events();
 162          $event = reset($result);
 163          $sink->close();
 164  
 165          $this->assertEquals($modcontext->id, $event->contextid);
 166          $this->assertEquals($course->id, $event->courseid);
 167  
 168          // Check that an error occurs when teamsubmission is not set.
 169          try {
 170              \mod_assign_unittests\event\submission_created::create($params);
 171              $this->fail('Other must contain the key submissionid.');
 172          } catch (\Exception $e) {
 173              $this->assertInstanceOf('coding_exception', $e);
 174          }
 175          // Check that the submission status debugging is fired.
 176          $subinfo = $params;
 177          $subinfo['other'] = array('submissionid' => '23');
 178          try {
 179              \mod_assign_unittests\event\submission_created::create($subinfo);
 180              $this->fail('Other must contain the key submissionattempt.');
 181          } catch (\Exception $e) {
 182              $this->assertInstanceOf('coding_exception', $e);
 183          }
 184  
 185          $subinfo['other'] = array('submissionattempt' => '0');
 186          try {
 187              \mod_assign_unittests\event\submission_created::create($subinfo);
 188              $this->fail('Other must contain the key submissionstatus.');
 189          } catch (\Exception $e) {
 190              $this->assertInstanceOf('coding_exception', $e);
 191          }
 192      }
 193  
 194      /**
 195       * Test submission_removed event.
 196       *
 197       * @covers \mod_assign\event\submission_removed
 198       */
 199      public function test_submission_removed() {
 200          $this->resetAfterTest();
 201  
 202          $course = $this->getDataGenerator()->create_course();
 203          $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 204          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 205  
 206          $assign = $this->create_instance($course);
 207          $this->add_submission($student, $assign);
 208          $submission = $assign->get_user_submission($student->id, 0);
 209  
 210          $sink = $this->redirectEvents();
 211          $assign->remove_submission($student->id);
 212          $events = $sink->get_events();
 213          $this->assertCount(2, $events);
 214          $event = $events[0];
 215          $this->assertInstanceOf('mod_assign\event\submission_removed', $event);
 216          $this->assertEquals($assign->get_context(), $event->get_context());
 217          $this->assertEquals($submission->id, $event->objectid);
 218          $this->assertEquals($student->id, $event->relateduserid);
 219          $this->assertEquals($submission->id, $event->other['submissionid']);
 220          $this->assertEquals(0, $event->other['submissionattempt']);
 221          $this->assertEquals(ASSIGN_SUBMISSION_STATUS_NEW, $event->other['submissionstatus']);
 222          $this->assertEquals(0, $event->other['groupid']);
 223          $this->assertEquals(null, $event->other['groupname']);
 224          $sink->close();
 225      }
 226  
 227      /**
 228       * Test submission_removed event when a team submission is removed.
 229       *
 230       * @covers \mod_assign\event\submission_removed
 231       */
 232      public function test_team_submission_removed() {
 233          $this->resetAfterTest();
 234  
 235          $course = $this->getDataGenerator()->create_course();
 236          $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 237          $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 238  
 239          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 240          groups_add_member($group, $student);
 241  
 242          $otherstudent = $this->getDataGenerator()->create_and_enrol($course, 'student');
 243          groups_add_member($group, $otherstudent);
 244  
 245          $assign = $this->create_instance($course, [
 246              'teamsubmission' => 1,
 247          ]);
 248          $this->add_submission($student, $assign);
 249          $submission = $assign->get_group_submission($student->id, 0, true);
 250  
 251          $sink = $this->redirectEvents();
 252          $assign->remove_submission($student->id);
 253          $events = $sink->get_events();
 254          $this->assertCount(2, $events);
 255          $event = $events[0];
 256          $this->assertInstanceOf('mod_assign\event\submission_removed', $event);
 257          $this->assertEquals($assign->get_context(), $event->get_context());
 258          $this->assertEquals($submission->id, $event->objectid);
 259          $this->assertEquals(null, $event->relateduserid);
 260          $this->assertEquals($submission->id, $event->other['submissionid']);
 261          $this->assertEquals(0, $event->other['submissionattempt']);
 262          $this->assertEquals(ASSIGN_SUBMISSION_STATUS_NEW, $event->other['submissionstatus']);
 263          $this->assertEquals($group->id, $event->other['groupid']);
 264          $this->assertEquals($group->name, $event->other['groupname']);
 265          $sink->close();
 266      }
 267  
 268      public function test_extension_granted() {
 269          $this->resetAfterTest();
 270  
 271          $course = $this->getDataGenerator()->create_course();
 272          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 273          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 274  
 275          $this->setUser($teacher);
 276  
 277          $now = time();
 278          $tomorrow = $now + DAYSECS;
 279          $yesterday = $now - DAYSECS;
 280  
 281          $assign = $this->create_instance($course, [
 282              'duedate' => $yesterday,
 283              'cutoffdate' => $yesterday,
 284          ]);
 285          $sink = $this->redirectEvents();
 286  
 287          $assign->testable_save_user_extension($student->id, $tomorrow);
 288  
 289          $events = $sink->get_events();
 290          $this->assertCount(1, $events);
 291          $event = reset($events);
 292          $this->assertInstanceOf('\mod_assign\event\extension_granted', $event);
 293          $this->assertEquals($assign->get_context(), $event->get_context());
 294          $this->assertEquals($assign->get_instance()->id, $event->objectid);
 295          $this->assertEquals($student->id, $event->relateduserid);
 296  
 297          $expected = array(
 298              $assign->get_course()->id,
 299              'assign',
 300              'grant extension',
 301              'view.php?id=' . $assign->get_course_module()->id,
 302              $student->id,
 303              $assign->get_course_module()->id
 304          );
 305          $this->assertEventLegacyLogData($expected, $event);
 306          $sink->close();
 307      }
 308  
 309      public function test_submission_locked() {
 310          $this->resetAfterTest();
 311  
 312          $course = $this->getDataGenerator()->create_course();
 313          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 314          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 315  
 316          $teacher->ignoresesskey = true;
 317          $this->setUser($teacher);
 318  
 319          $assign = $this->create_instance($course);
 320          $sink = $this->redirectEvents();
 321  
 322          $assign->lock_submission($student->id);
 323  
 324          $events = $sink->get_events();
 325          $this->assertCount(1, $events);
 326          $event = reset($events);
 327          $this->assertInstanceOf('\mod_assign\event\submission_locked', $event);
 328          $this->assertEquals($assign->get_context(), $event->get_context());
 329          $this->assertEquals($assign->get_instance()->id, $event->objectid);
 330          $this->assertEquals($student->id, $event->relateduserid);
 331          $expected = array(
 332              $assign->get_course()->id,
 333              'assign',
 334              'lock submission',
 335              'view.php?id=' . $assign->get_course_module()->id,
 336              get_string('locksubmissionforstudent', 'assign', array('id' => $student->id,
 337                  'fullname' => fullname($student))),
 338              $assign->get_course_module()->id
 339          );
 340          $this->assertEventLegacyLogData($expected, $event);
 341          $sink->close();
 342      }
 343  
 344      public function test_identities_revealed() {
 345          $this->resetAfterTest();
 346  
 347          $course = $this->getDataGenerator()->create_course();
 348          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 349  
 350          $teacher->ignoresesskey = true;
 351          $this->setUser($teacher);
 352  
 353          $assign = $this->create_instance($course, ['blindmarking' => 1]);
 354          $sink = $this->redirectEvents();
 355  
 356          $assign->reveal_identities();
 357  
 358          $events = $sink->get_events();
 359          $eventscount = 0;
 360  
 361          foreach ($events as $event) {
 362              if ($event instanceof \mod_assign\event\identities_revealed) {
 363                  $eventscount++;
 364                  $this->assertInstanceOf('\mod_assign\event\identities_revealed', $event);
 365                  $this->assertEquals($assign->get_context(), $event->get_context());
 366                  $this->assertEquals($assign->get_instance()->id, $event->objectid);
 367                  $expected = array(
 368                      $assign->get_course()->id,
 369                      'assign',
 370                      'reveal identities',
 371                      'view.php?id=' . $assign->get_course_module()->id,
 372                      get_string('revealidentities', 'assign'),
 373                      $assign->get_course_module()->id
 374                  );
 375                  $this->assertEventLegacyLogData($expected, $event);
 376              }
 377          }
 378  
 379          $this->assertEquals(1, $eventscount);
 380          $sink->close();
 381      }
 382  
 383      /**
 384       * Test the submission_status_viewed event.
 385       */
 386      public function test_submission_status_viewed() {
 387          global $PAGE;
 388          $this->resetAfterTest();
 389  
 390          $course = $this->getDataGenerator()->create_course();
 391          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 392  
 393          $this->setUser($teacher);
 394  
 395          $assign = $this->create_instance($course);
 396  
 397          // We need to set the URL in order to view the feedback.
 398          $PAGE->set_url('/a_url');
 399  
 400          // Trigger and capture the event.
 401          $sink = $this->redirectEvents();
 402          $assign->view();
 403          $events = $sink->get_events();
 404          $this->assertCount(1, $events);
 405          $event = reset($events);
 406  
 407          // Check that the event contains the expected values.
 408          $this->assertInstanceOf('\mod_assign\event\submission_status_viewed', $event);
 409          $this->assertEquals($assign->get_context(), $event->get_context());
 410          $expected = array(
 411              $assign->get_course()->id,
 412              'assign',
 413              'view',
 414              'view.php?id=' . $assign->get_course_module()->id,
 415              get_string('viewownsubmissionstatus', 'assign'),
 416              $assign->get_course_module()->id
 417          );
 418          $this->assertEventLegacyLogData($expected, $event);
 419          $this->assertEventContextNotUsed($event);
 420      }
 421  
 422      /**
 423       * Test submission_status_updated event when a submission is updated.
 424       *
 425       * @covers \mod_assign\event\submission_status_updated
 426       */
 427      public function test_submission_status_updated_on_update() {
 428          $this->resetAfterTest();
 429  
 430          $course = $this->getDataGenerator()->create_course();
 431          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 432          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 433  
 434          $this->setUser($teacher);
 435  
 436          $assign = $this->create_instance($course);
 437          $submission = $assign->get_user_submission($student->id, true);
 438          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 439          $assign->testable_update_submission($submission, $student->id, true, false);
 440  
 441          $sink = $this->redirectEvents();
 442          $assign->revert_to_draft($student->id);
 443  
 444          $events = $sink->get_events();
 445          $this->assertCount(2, $events);
 446          $event = $events[1];
 447          $this->assertInstanceOf('\mod_assign\event\submission_status_updated', $event);
 448          $this->assertEquals($assign->get_context(), $event->get_context());
 449          $this->assertEquals($submission->id, $event->objectid);
 450          $this->assertEquals($student->id, $event->relateduserid);
 451          $this->assertEquals(ASSIGN_SUBMISSION_STATUS_DRAFT, $event->other['newstatus']);
 452          $expected = array(
 453              $assign->get_course()->id,
 454              'assign',
 455              'revert submission to draft',
 456              'view.php?id=' . $assign->get_course_module()->id,
 457              get_string('reverttodraftforstudent', 'assign', array('id' => $student->id,
 458                  'fullname' => fullname($student))),
 459              $assign->get_course_module()->id
 460          );
 461          $this->assertEventLegacyLogData($expected, $event);
 462          $sink->close();
 463      }
 464  
 465      /**
 466       * Test submission_status_updated event when a submission is removed.
 467       *
 468       * @covers \mod_assign\event\submission_status_updated
 469       */
 470      public function test_submission_status_updated_on_remove() {
 471          $this->resetAfterTest();
 472  
 473          $course = $this->getDataGenerator()->create_course();
 474          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 475          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 476  
 477          $assign = $this->create_instance($course);
 478          $this->add_submission($student, $assign);
 479          $submission = $assign->get_user_submission($student->id, false);
 480  
 481          $sink = $this->redirectEvents();
 482          $assign->remove_submission($student->id);
 483  
 484          $events = $sink->get_events();
 485          $this->assertCount(2, $events);
 486  
 487          $event = $events[1];
 488          $this->assertInstanceOf('\mod_assign\event\submission_status_updated', $event);
 489          $this->assertEquals($assign->get_context(), $event->get_context());
 490          $this->assertEquals($submission->id, $event->objectid);
 491          $this->assertEquals($student->id, $event->relateduserid);
 492          $this->assertEquals(ASSIGN_SUBMISSION_STATUS_NEW, $event->other['newstatus']);
 493          $expected = [
 494              $assign->get_course()->id,
 495              'assign',
 496              'revert submission to draft',
 497              'view.php?id=' . $assign->get_course_module()->id,
 498              get_string('reverttodraftforstudent', 'assign', ['id' => $student->id,
 499                  'fullname' => fullname($student)]),
 500              $assign->get_course_module()->id
 501          ];
 502          $this->assertEventLegacyLogData($expected, $event);
 503          $sink->close();
 504      }
 505  
 506      /**
 507       * Test submission_status_updated event when a team submission is removed.
 508       *
 509       * @covers \mod_assign\event\submission_status_updated
 510       */
 511      public function test_team_submission_status_updated_on_remove() {
 512          $this->resetAfterTest();
 513  
 514          $course = $this->getDataGenerator()->create_course();
 515          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 516          $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 517  
 518          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 519          groups_add_member($group, $student);
 520  
 521          $otherstudent = $this->getDataGenerator()->create_and_enrol($course, 'student');
 522          groups_add_member($group, $otherstudent);
 523  
 524          $assign = $this->create_instance($course, [
 525              'teamsubmission' => 1,
 526          ]);
 527          $this->add_submission($student, $assign);
 528          $submission = $assign->get_group_submission($student->id, 0, false);
 529  
 530          $sink = $this->redirectEvents();
 531          $assign->remove_submission($student->id);
 532  
 533          $events = $sink->get_events();
 534          $this->assertCount(2, $events);
 535  
 536          $event = $events[1];
 537          $this->assertInstanceOf('\mod_assign\event\submission_status_updated', $event);
 538          $this->assertEquals($assign->get_context(), $event->get_context());
 539          $this->assertEquals($submission->id, $event->objectid);
 540          $this->assertEquals(null, $event->relateduserid);
 541          $this->assertEquals(ASSIGN_SUBMISSION_STATUS_NEW, $event->other['newstatus']);
 542          $expected = [
 543              $course->id,
 544              'assign',
 545              'revert submission to draft',
 546              'view.php?id=' . $assign->get_course_module()->id,
 547              get_string('reverttodraftforgroup', 'assign', $group->id),
 548              $assign->get_course_module()->id
 549          ];
 550          $this->assertEventLegacyLogData($expected, $event);
 551          $sink->close();
 552      }
 553  
 554      public function test_marker_updated() {
 555          $this->resetAfterTest();
 556  
 557          $course = $this->getDataGenerator()->create_course();
 558          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 559          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 560  
 561          $teacher->ignoresesskey = true;
 562          $this->setUser($teacher);
 563  
 564          $assign = $this->create_instance($course);
 565  
 566          $sink = $this->redirectEvents();
 567          $assign->testable_process_set_batch_marking_allocation($student->id, $teacher->id);
 568  
 569          $events = $sink->get_events();
 570          $this->assertCount(1, $events);
 571          $event = reset($events);
 572          $this->assertInstanceOf('\mod_assign\event\marker_updated', $event);
 573          $this->assertEquals($assign->get_context(), $event->get_context());
 574          $this->assertEquals($assign->get_instance()->id, $event->objectid);
 575          $this->assertEquals($student->id, $event->relateduserid);
 576          $this->assertEquals($teacher->id, $event->userid);
 577          $this->assertEquals($teacher->id, $event->other['markerid']);
 578          $expected = array(
 579              $assign->get_course()->id,
 580              'assign',
 581              'set marking allocation',
 582              'view.php?id=' . $assign->get_course_module()->id,
 583              get_string('setmarkerallocationforlog', 'assign', array('id' => $student->id,
 584                  'fullname' => fullname($student), 'marker' => fullname($teacher))),
 585              $assign->get_course_module()->id
 586          );
 587          $this->assertEventLegacyLogData($expected, $event);
 588          $sink->close();
 589      }
 590  
 591      public function test_workflow_state_updated() {
 592          $this->resetAfterTest();
 593  
 594          $course = $this->getDataGenerator()->create_course();
 595          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 596          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 597  
 598          $teacher->ignoresesskey = true;
 599          $this->setUser($teacher);
 600  
 601          $assign = $this->create_instance($course);
 602  
 603          // Test process_set_batch_marking_workflow_state.
 604          $sink = $this->redirectEvents();
 605          $assign->testable_process_set_batch_marking_workflow_state($student->id, ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW);
 606  
 607          $events = $sink->get_events();
 608          $eventcount = 0;
 609          foreach ($events as $event) {
 610              if ($event instanceof \mod_assign\event\submission_graded) {
 611                  $eventcount++;
 612                  $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
 613                  $this->assertEquals($assign->get_context(), $event->get_context());
 614              }
 615              if ($event instanceof \mod_assign\event\workflow_state_updated) {
 616                  $eventcount++;
 617                  $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
 618                  $this->assertEquals($assign->get_context(), $event->get_context());
 619                  $this->assertEquals($assign->get_instance()->id, $event->objectid);
 620                  $this->assertEquals($student->id, $event->relateduserid);
 621                  $this->assertEquals($teacher->id, $event->userid);
 622                  $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW, $event->other['newstate']);
 623                  $expected = array(
 624                      $assign->get_course()->id,
 625                      'assign',
 626                      'set marking workflow state',
 627                      'view.php?id=' . $assign->get_course_module()->id,
 628                      get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $student->id,
 629                          'fullname' => fullname($student), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW)),
 630                      $assign->get_course_module()->id
 631                  );
 632                  $this->assertEventLegacyLogData($expected, $event);
 633              }
 634          }
 635          $this->assertEquals(2, $eventcount);
 636          $sink->close();
 637  
 638          // Test setting workflow state in apply_grade_to_user.
 639          $sink = $this->redirectEvents();
 640          $data = new \stdClass();
 641          $data->grade = '50.0';
 642          $data->workflowstate = 'readyforrelease';
 643          $assign->testable_apply_grade_to_user($data, $student->id, 0);
 644  
 645          $events = $sink->get_events();
 646          $this->assertCount(4, $events);
 647          $event = reset($events);
 648          $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
 649          $this->assertEquals($assign->get_context(), $event->get_context());
 650          $this->assertEquals($assign->get_instance()->id, $event->objectid);
 651          $this->assertEquals($student->id, $event->relateduserid);
 652          $this->assertEquals($teacher->id, $event->userid);
 653          $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE, $event->other['newstate']);
 654          $expected = array(
 655              $assign->get_course()->id,
 656              'assign',
 657              'set marking workflow state',
 658              'view.php?id=' . $assign->get_course_module()->id,
 659              get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $student->id,
 660                  'fullname' => fullname($student), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE)),
 661              $assign->get_course_module()->id
 662          );
 663          $this->assertEventLegacyLogData($expected, $event);
 664          $sink->close();
 665  
 666          // Test setting workflow state in process_save_quick_grades.
 667          $sink = $this->redirectEvents();
 668  
 669          $data = array(
 670              'grademodified_' . $student->id => time(),
 671              'gradeattempt_' . $student->id => '',
 672              'quickgrade_' . $student->id => '60.0',
 673              'quickgrade_' . $student->id . '_workflowstate' => 'inmarking'
 674          );
 675          $assign->testable_process_save_quick_grades($data);
 676  
 677          $events = $sink->get_events();
 678          $this->assertCount(4, $events);
 679          $event = reset($events);
 680          $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
 681          $this->assertEquals($assign->get_context(), $event->get_context());
 682          $this->assertEquals($assign->get_instance()->id, $event->objectid);
 683          $this->assertEquals($student->id, $event->relateduserid);
 684          $this->assertEquals($teacher->id, $event->userid);
 685          $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_INMARKING, $event->other['newstate']);
 686          $expected = array(
 687              $assign->get_course()->id,
 688              'assign',
 689              'set marking workflow state',
 690              'view.php?id=' . $assign->get_course_module()->id,
 691              get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $student->id,
 692                  'fullname' => fullname($student), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_INMARKING)),
 693              $assign->get_course_module()->id
 694          );
 695          $this->assertEventLegacyLogData($expected, $event);
 696          $sink->close();
 697      }
 698  
 699      public function test_submission_duplicated() {
 700          $this->resetAfterTest();
 701  
 702          $course = $this->getDataGenerator()->create_course();
 703          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 704  
 705          $this->setUser($student);
 706  
 707          $assign = $this->create_instance($course);
 708          $submission1 = $assign->get_user_submission($student->id, true, 0);
 709          $submission2 = $assign->get_user_submission($student->id, true, 1);
 710          $submission2->status = ASSIGN_SUBMISSION_STATUS_REOPENED;
 711          $assign->testable_update_submission($submission2, $student->id, time(), $assign->get_instance()->teamsubmission);
 712  
 713          $sink = $this->redirectEvents();
 714          $notices = null;
 715          $assign->copy_previous_attempt($notices);
 716  
 717          $events = $sink->get_events();
 718          $this->assertCount(1, $events);
 719          $event = reset($events);
 720          $this->assertInstanceOf('\mod_assign\event\submission_duplicated', $event);
 721          $this->assertEquals($assign->get_context(), $event->get_context());
 722          $this->assertEquals($submission2->id, $event->objectid);
 723          $this->assertEquals($student->id, $event->userid);
 724          $submission2->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
 725          $expected = array(
 726              $assign->get_course()->id,
 727              'assign',
 728              'submissioncopied',
 729              'view.php?id=' . $assign->get_course_module()->id,
 730              $assign->testable_format_submission_for_log($submission2),
 731              $assign->get_course_module()->id
 732          );
 733          $this->assertEventLegacyLogData($expected, $event);
 734          $sink->close();
 735      }
 736  
 737      public function test_submission_unlocked() {
 738          $this->resetAfterTest();
 739  
 740          $course = $this->getDataGenerator()->create_course();
 741          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 742          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 743  
 744          $teacher->ignoresesskey = true;
 745          $this->setUser($teacher);
 746  
 747          $assign = $this->create_instance($course);
 748          $sink = $this->redirectEvents();
 749  
 750          $assign->unlock_submission($student->id);
 751  
 752          $events = $sink->get_events();
 753          $this->assertCount(1, $events);
 754          $event = reset($events);
 755          $this->assertInstanceOf('\mod_assign\event\submission_unlocked', $event);
 756          $this->assertEquals($assign->get_context(), $event->get_context());
 757          $this->assertEquals($assign->get_instance()->id, $event->objectid);
 758          $this->assertEquals($student->id, $event->relateduserid);
 759          $expected = array(
 760              $assign->get_course()->id,
 761              'assign',
 762              'unlock submission',
 763              'view.php?id=' . $assign->get_course_module()->id,
 764              get_string('unlocksubmissionforstudent', 'assign', array('id' => $student->id,
 765                  'fullname' => fullname($student))),
 766              $assign->get_course_module()->id
 767          );
 768          $this->assertEventLegacyLogData($expected, $event);
 769          $sink->close();
 770      }
 771  
 772      public function test_submission_graded() {
 773          $this->resetAfterTest();
 774  
 775          $course = $this->getDataGenerator()->create_course();
 776          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 777          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 778  
 779          $teacher->ignoresesskey = true;
 780          $this->setUser($teacher);
 781  
 782          $assign = $this->create_instance($course);
 783  
 784          // Test apply_grade_to_user.
 785          $sink = $this->redirectEvents();
 786  
 787          $data = new \stdClass();
 788          $data->grade = '50.0';
 789          $assign->testable_apply_grade_to_user($data, $student->id, 0);
 790          $grade = $assign->get_user_grade($student->id, false, 0);
 791  
 792          $events = $sink->get_events();
 793          $this->assertCount(3, $events);
 794          $event = $events[2];
 795          $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
 796          $this->assertEquals($assign->get_context(), $event->get_context());
 797          $this->assertEquals($grade->id, $event->objectid);
 798          $this->assertEquals($student->id, $event->relateduserid);
 799          $expected = array(
 800              $assign->get_course()->id,
 801              'assign',
 802              'grade submission',
 803              'view.php?id=' . $assign->get_course_module()->id,
 804              $assign->format_grade_for_log($grade),
 805              $assign->get_course_module()->id
 806          );
 807          $this->assertEventLegacyLogData($expected, $event);
 808          $sink->close();
 809  
 810          // Test process_save_quick_grades.
 811          $sink = $this->redirectEvents();
 812  
 813          $grade = $assign->get_user_grade($student->id, false);
 814          $data = array(
 815              'grademodified_' . $student->id => time(),
 816              'gradeattempt_' . $student->id => $grade->attemptnumber,
 817              'quickgrade_' . $student->id => '60.0'
 818          );
 819          $assign->testable_process_save_quick_grades($data);
 820          $grade = $assign->get_user_grade($student->id, false);
 821          $this->assertEquals(60.0, $grade->grade);
 822  
 823          $events = $sink->get_events();
 824          $this->assertCount(3, $events);
 825          $event = $events[2];
 826          $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
 827          $this->assertEquals($assign->get_context(), $event->get_context());
 828          $this->assertEquals($grade->id, $event->objectid);
 829          $this->assertEquals($student->id, $event->relateduserid);
 830          $expected = array(
 831              $assign->get_course()->id,
 832              'assign',
 833              'grade submission',
 834              'view.php?id=' . $assign->get_course_module()->id,
 835              $assign->format_grade_for_log($grade),
 836              $assign->get_course_module()->id
 837          );
 838          $this->assertEventLegacyLogData($expected, $event);
 839          $sink->close();
 840  
 841          // Test update_grade.
 842          $sink = $this->redirectEvents();
 843          $data = clone($grade);
 844          $data->grade = '50.0';
 845          $assign->update_grade($data);
 846          $grade = $assign->get_user_grade($student->id, false, 0);
 847          $this->assertEquals(50.0, $grade->grade);
 848          $events = $sink->get_events();
 849  
 850          $this->assertCount(3, $events);
 851          $event = $events[2];
 852          $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
 853          $this->assertEquals($assign->get_context(), $event->get_context());
 854          $this->assertEquals($grade->id, $event->objectid);
 855          $this->assertEquals($student->id, $event->relateduserid);
 856          $expected = array(
 857              $assign->get_course()->id,
 858              'assign',
 859              'grade submission',
 860              'view.php?id=' . $assign->get_course_module()->id,
 861              $assign->format_grade_for_log($grade),
 862              $assign->get_course_module()->id
 863          );
 864          $this->assertEventLegacyLogData($expected, $event);
 865          $sink->close();
 866      }
 867  
 868      /**
 869       * Test the submission_viewed event.
 870       */
 871      public function test_submission_viewed() {
 872          global $PAGE;
 873  
 874          $this->resetAfterTest();
 875  
 876          $course = $this->getDataGenerator()->create_course();
 877          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 878          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 879  
 880          $this->setUser($teacher);
 881  
 882          $assign = $this->create_instance($course);
 883          $submission = $assign->get_user_submission($student->id, true);
 884  
 885          // We need to set the URL in order to view the submission.
 886          $PAGE->set_url('/a_url');
 887          // A hack - these variables are used by the view_plugin_content function to
 888          // determine what we actually want to view - would usually be set in URL.
 889          global $_POST;
 890          $_POST['plugin'] = 'comments';
 891          $_POST['sid'] = $submission->id;
 892  
 893          // Trigger and capture the event.
 894          $sink = $this->redirectEvents();
 895          $assign->view('viewpluginassignsubmission');
 896          $events = $sink->get_events();
 897          $this->assertCount(1, $events);
 898          $event = reset($events);
 899  
 900          // Check that the event contains the expected values.
 901          $this->assertInstanceOf('\mod_assign\event\submission_viewed', $event);
 902          $this->assertEquals($assign->get_context(), $event->get_context());
 903          $this->assertEquals($submission->id, $event->objectid);
 904          $expected = array(
 905              $assign->get_course()->id,
 906              'assign',
 907              'view submission',
 908              'view.php?id=' . $assign->get_course_module()->id,
 909              get_string('viewsubmissionforuser', 'assign', $student->id),
 910              $assign->get_course_module()->id
 911          );
 912          $this->assertEventLegacyLogData($expected, $event);
 913          $this->assertEventContextNotUsed($event);
 914      }
 915  
 916      /**
 917       * Test the feedback_viewed event.
 918       */
 919      public function test_feedback_viewed() {
 920          global $DB, $PAGE;
 921  
 922          $this->resetAfterTest();
 923  
 924          $course = $this->getDataGenerator()->create_course();
 925          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 926          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 927  
 928          $this->setUser($teacher);
 929  
 930          $assign = $this->create_instance($course);
 931          $submission = $assign->get_user_submission($student->id, true);
 932  
 933          // Insert a grade for this submission.
 934          $grade = new \stdClass();
 935          $grade->assignment = $assign->get_instance()->id;
 936          $grade->userid = $student->id;
 937          $gradeid = $DB->insert_record('assign_grades', $grade);
 938  
 939          // We need to set the URL in order to view the feedback.
 940          $PAGE->set_url('/a_url');
 941          // A hack - these variables are used by the view_plugin_content function to
 942          // determine what we actually want to view - would usually be set in URL.
 943          global $_POST;
 944          $_POST['plugin'] = 'comments';
 945          $_POST['gid'] = $gradeid;
 946          $_POST['sid'] = $submission->id;
 947  
 948          // Trigger and capture the event.
 949          $sink = $this->redirectEvents();
 950          $assign->view('viewpluginassignfeedback');
 951          $events = $sink->get_events();
 952          $this->assertCount(1, $events);
 953          $event = reset($events);
 954  
 955          // Check that the event contains the expected values.
 956          $this->assertInstanceOf('\mod_assign\event\feedback_viewed', $event);
 957          $this->assertEquals($assign->get_context(), $event->get_context());
 958          $this->assertEquals($gradeid, $event->objectid);
 959          $expected = array(
 960              $assign->get_course()->id,
 961              'assign',
 962              'view feedback',
 963              'view.php?id=' . $assign->get_course_module()->id,
 964              get_string('viewfeedbackforuser', 'assign', $student->id),
 965              $assign->get_course_module()->id
 966          );
 967          $this->assertEventLegacyLogData($expected, $event);
 968          $this->assertEventContextNotUsed($event);
 969      }
 970  
 971      /**
 972       * Test the grading_form_viewed event.
 973       */
 974      public function test_grading_form_viewed() {
 975          global $PAGE;
 976  
 977          $this->resetAfterTest();
 978  
 979          $course = $this->getDataGenerator()->create_course();
 980          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 981          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 982  
 983          $this->setUser($teacher);
 984  
 985          $assign = $this->create_instance($course);
 986  
 987          // We need to set the URL in order to view the feedback.
 988          $PAGE->set_url('/a_url');
 989          // A hack - this variable is used by the view_single_grade_page function.
 990          global $_POST;
 991          $_POST['rownum'] = 1;
 992          $_POST['userid'] = $student->id;
 993  
 994          // Trigger and capture the event.
 995          $sink = $this->redirectEvents();
 996          $assign->view('grade');
 997          $events = $sink->get_events();
 998          $this->assertCount(1, $events);
 999          $event = reset($events);
1000  
1001          // Check that the event contains the expected values.
1002          $this->assertInstanceOf('\mod_assign\event\grading_form_viewed', $event);
1003          $this->assertEquals($assign->get_context(), $event->get_context());
1004          $expected = array(
1005              $assign->get_course()->id,
1006              'assign',
1007              'view grading form',
1008              'view.php?id=' . $assign->get_course_module()->id,
1009              get_string('viewgradingformforstudent', 'assign', array('id' => $student->id,
1010                  'fullname' => fullname($student))),
1011              $assign->get_course_module()->id
1012          );
1013          $this->assertEventLegacyLogData($expected, $event);
1014          $this->assertEventContextNotUsed($event);
1015      }
1016  
1017      /**
1018       * Test the grading_table_viewed event.
1019       */
1020      public function test_grading_table_viewed() {
1021          global $PAGE;
1022  
1023          $this->resetAfterTest();
1024  
1025          $course = $this->getDataGenerator()->create_course();
1026          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
1027          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1028  
1029          $this->setUser($teacher);
1030  
1031          $assign = $this->create_instance($course);
1032  
1033          // We need to set the URL in order to view the feedback.
1034          $PAGE->set_url('/a_url');
1035          // A hack - this variable is used by the view_single_grade_page function.
1036          global $_POST;
1037          $_POST['rownum'] = 1;
1038          $_POST['userid'] = $student->id;
1039  
1040          // Trigger and capture the event.
1041          $sink = $this->redirectEvents();
1042          $assign->view('grading');
1043          $events = $sink->get_events();
1044          $this->assertCount(1, $events);
1045          $event = reset($events);
1046  
1047          // Check that the event contains the expected values.
1048          $this->assertInstanceOf('\mod_assign\event\grading_table_viewed', $event);
1049          $this->assertEquals($assign->get_context(), $event->get_context());
1050          $expected = array(
1051              $assign->get_course()->id,
1052              'assign',
1053              'view submission grading table',
1054              'view.php?id=' . $assign->get_course_module()->id,
1055              get_string('viewsubmissiongradingtable', 'assign'),
1056              $assign->get_course_module()->id
1057          );
1058          $this->assertEventLegacyLogData($expected, $event);
1059          $this->assertEventContextNotUsed($event);
1060      }
1061  
1062      /**
1063       * Test the submission_form_viewed event.
1064       */
1065      public function test_submission_form_viewed() {
1066          global $PAGE;
1067  
1068          $this->resetAfterTest();
1069  
1070          $course = $this->getDataGenerator()->create_course();
1071          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1072  
1073          $this->setUser($student);
1074  
1075          $assign = $this->create_instance($course);
1076  
1077          // We need to set the URL in order to view the submission form.
1078          $PAGE->set_url('/a_url');
1079  
1080          // Trigger and capture the event.
1081          $sink = $this->redirectEvents();
1082          $assign->view('editsubmission');
1083          $events = $sink->get_events();
1084          $this->assertCount(1, $events);
1085          $event = reset($events);
1086  
1087          // Check that the event contains the expected values.
1088          $this->assertInstanceOf('\mod_assign\event\submission_form_viewed', $event);
1089          $this->assertEquals($assign->get_context(), $event->get_context());
1090          $expected = array(
1091              $assign->get_course()->id,
1092              'assign',
1093              'view submit assignment form',
1094              'view.php?id=' . $assign->get_course_module()->id,
1095              get_string('editsubmission', 'assign'),
1096              $assign->get_course_module()->id
1097          );
1098          $this->assertEventLegacyLogData($expected, $event);
1099          $this->assertEventContextNotUsed($event);
1100      }
1101  
1102      /**
1103       * Test the submission_form_viewed event.
1104       */
1105      public function test_submission_confirmation_form_viewed() {
1106          global $PAGE;
1107  
1108          $this->resetAfterTest();
1109  
1110          $course = $this->getDataGenerator()->create_course();
1111          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1112  
1113          $this->setUser($student);
1114  
1115          $assign = $this->create_instance($course);
1116  
1117          // We need to set the URL in order to view the submission form.
1118          $PAGE->set_url('/a_url');
1119  
1120          // Trigger and capture the event.
1121          $sink = $this->redirectEvents();
1122          $assign->view('submit');
1123          $events = $sink->get_events();
1124          $this->assertCount(1, $events);
1125          $event = reset($events);
1126  
1127          // Check that the event contains the expected values.
1128          $this->assertInstanceOf('\mod_assign\event\submission_confirmation_form_viewed', $event);
1129          $this->assertEquals($assign->get_context(), $event->get_context());
1130          $expected = array(
1131              $assign->get_course()->id,
1132              'assign',
1133              'view confirm submit assignment form',
1134              'view.php?id=' . $assign->get_course_module()->id,
1135              get_string('viewownsubmissionform', 'assign'),
1136              $assign->get_course_module()->id
1137          );
1138          $this->assertEventLegacyLogData($expected, $event);
1139          $this->assertEventContextNotUsed($event);
1140      }
1141  
1142      /**
1143       * Test the reveal_identities_confirmation_page_viewed event.
1144       */
1145      public function test_reveal_identities_confirmation_page_viewed() {
1146          global $PAGE;
1147          $this->resetAfterTest();
1148  
1149          // Set to the admin user so we have the permission to reveal identities.
1150          $this->setAdminUser();
1151  
1152          $course = $this->getDataGenerator()->create_course();
1153          $assign = $this->create_instance($course);
1154  
1155          // We need to set the URL in order to view the submission form.
1156          $PAGE->set_url('/a_url');
1157  
1158          // Trigger and capture the event.
1159          $sink = $this->redirectEvents();
1160          $assign->view('revealidentities');
1161          $events = $sink->get_events();
1162          $this->assertCount(1, $events);
1163          $event = reset($events);
1164  
1165          // Check that the event contains the expected values.
1166          $this->assertInstanceOf('\mod_assign\event\reveal_identities_confirmation_page_viewed', $event);
1167          $this->assertEquals($assign->get_context(), $event->get_context());
1168          $expected = array(
1169              $assign->get_course()->id,
1170              'assign',
1171              'view',
1172              'view.php?id=' . $assign->get_course_module()->id,
1173              get_string('viewrevealidentitiesconfirm', 'assign'),
1174              $assign->get_course_module()->id
1175          );
1176          $this->assertEventLegacyLogData($expected, $event);
1177          $this->assertEventContextNotUsed($event);
1178      }
1179  
1180      /**
1181       * Test the statement_accepted event.
1182       */
1183      public function test_statement_accepted() {
1184          // We want to be a student so we can submit assignments.
1185          $this->resetAfterTest();
1186  
1187          $course = $this->getDataGenerator()->create_course();
1188          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1189  
1190          $this->setUser($student);
1191  
1192          // We do not want to send any messages to the student during the PHPUNIT test.
1193          set_config('submissionreceipts', false, 'assign');
1194  
1195          $assign = $this->create_instance($course);
1196  
1197          // Create the data we want to pass to the submit_for_grading function.
1198          $data = new \stdClass();
1199          $data->submissionstatement = 'We are the Borg. You will be assimilated. Resistance is futile. - do you agree
1200              to these terms?';
1201  
1202          // Trigger and capture the event.
1203          $sink = $this->redirectEvents();
1204          $assign->submit_for_grading($data, array());
1205          $events = $sink->get_events();
1206          $event = reset($events);
1207  
1208          // Check that the event contains the expected values.
1209          $this->assertInstanceOf('\mod_assign\event\statement_accepted', $event);
1210          $this->assertEquals($assign->get_context(), $event->get_context());
1211          $expected = array(
1212              $assign->get_course()->id,
1213              'assign',
1214              'submission statement accepted',
1215              'view.php?id=' . $assign->get_course_module()->id,
1216              get_string('submissionstatementacceptedlog',
1217                  'mod_assign',
1218                  fullname($student)),
1219              $assign->get_course_module()->id
1220          );
1221          $this->assertEventLegacyLogData($expected, $event);
1222          $this->assertEventContextNotUsed($event);
1223  
1224          // Enable the online text submission plugin.
1225          $submissionplugins = $assign->get_submission_plugins();
1226          foreach ($submissionplugins as $plugin) {
1227              if ($plugin->get_type() === 'onlinetext') {
1228                  $plugin->enable();
1229                  break;
1230              }
1231          }
1232  
1233          // Create the data we want to pass to the save_submission function.
1234          $data = new \stdClass();
1235          $data->onlinetext_editor = array(
1236              'text' => 'Online text',
1237              'format' => FORMAT_HTML,
1238              'itemid' => file_get_unused_draft_itemid()
1239          );
1240          $data->submissionstatement = 'We are the Borg. You will be assimilated. Resistance is futile. - do you agree
1241              to these terms?';
1242  
1243          // Trigger and capture the event.
1244          $sink = $this->redirectEvents();
1245          $assign->save_submission($data, $notices);
1246          $events = $sink->get_events();
1247          $event = $events[2];
1248  
1249          // Check that the event contains the expected values.
1250          $this->assertInstanceOf('\mod_assign\event\statement_accepted', $event);
1251          $this->assertEquals($assign->get_context(), $event->get_context());
1252          $this->assertEventLegacyLogData($expected, $event);
1253          $this->assertEventContextNotUsed($event);
1254      }
1255  
1256      /**
1257       * Test the batch_set_workflow_state_viewed event.
1258       */
1259      public function test_batch_set_workflow_state_viewed() {
1260          $this->resetAfterTest();
1261  
1262          $course = $this->getDataGenerator()->create_course();
1263          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1264          $assign = $this->create_instance($course);
1265  
1266          // Trigger and capture the event.
1267          $sink = $this->redirectEvents();
1268          $assign->testable_view_batch_set_workflow_state($student->id);
1269          $events = $sink->get_events();
1270          $event = reset($events);
1271  
1272          // Check that the event contains the expected values.
1273          $this->assertInstanceOf('\mod_assign\event\batch_set_workflow_state_viewed', $event);
1274          $this->assertEquals($assign->get_context(), $event->get_context());
1275          $expected = array(
1276              $assign->get_course()->id,
1277              'assign',
1278              'view batch set marking workflow state',
1279              'view.php?id=' . $assign->get_course_module()->id,
1280              get_string('viewbatchsetmarkingworkflowstate', 'assign'),
1281              $assign->get_course_module()->id
1282          );
1283          $this->assertEventLegacyLogData($expected, $event);
1284          $this->assertEventContextNotUsed($event);
1285      }
1286  
1287      /**
1288       * Test the batch_set_marker_allocation_viewed event.
1289       */
1290      public function test_batch_set_marker_allocation_viewed() {
1291          $this->resetAfterTest();
1292  
1293          $course = $this->getDataGenerator()->create_course();
1294          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1295          $assign = $this->create_instance($course);
1296  
1297          // Trigger and capture the event.
1298          $sink = $this->redirectEvents();
1299          $assign->testable_view_batch_markingallocation($student->id);
1300          $events = $sink->get_events();
1301          $event = reset($events);
1302  
1303          // Check that the event contains the expected values.
1304          $this->assertInstanceOf('\mod_assign\event\batch_set_marker_allocation_viewed', $event);
1305          $this->assertEquals($assign->get_context(), $event->get_context());
1306          $expected = array(
1307              $assign->get_course()->id,
1308              'assign',
1309              'view batch set marker allocation',
1310              'view.php?id=' . $assign->get_course_module()->id,
1311              get_string('viewbatchmarkingallocation', 'assign'),
1312              $assign->get_course_module()->id
1313          );
1314          $this->assertEventLegacyLogData($expected, $event);
1315          $this->assertEventContextNotUsed($event);
1316      }
1317  
1318      /**
1319       * Test the user override created event.
1320       *
1321       * There is no external API for creating a user override, so the unit test will simply
1322       * create and trigger the event and ensure the event data is returned as expected.
1323       */
1324      public function test_user_override_created() {
1325          $this->resetAfterTest();
1326  
1327          $course = $this->getDataGenerator()->create_course();
1328          $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1329  
1330          $params = array(
1331              'objectid' => 1,
1332              'relateduserid' => 2,
1333              'context' => \context_module::instance($assign->cmid),
1334              'other' => array(
1335                  'assignid' => $assign->id
1336              )
1337          );
1338          $event = \mod_assign\event\user_override_created::create($params);
1339  
1340          // Trigger and capture the event.
1341          $sink = $this->redirectEvents();
1342          $event->trigger();
1343          $events = $sink->get_events();
1344          $event = reset($events);
1345  
1346          // Check that the event data is valid.
1347          $this->assertInstanceOf('\mod_assign\event\user_override_created', $event);
1348          $this->assertEquals(\context_module::instance($assign->cmid), $event->get_context());
1349          $this->assertEventContextNotUsed($event);
1350      }
1351  
1352      /**
1353       * Test the group override created event.
1354       *
1355       * There is no external API for creating a group override, so the unit test will simply
1356       * create and trigger the event and ensure the event data is returned as expected.
1357       */
1358      public function test_group_override_created() {
1359          $this->resetAfterTest();
1360  
1361          $course = $this->getDataGenerator()->create_course();
1362          $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1363  
1364          $params = array(
1365              'objectid' => 1,
1366              'context' => \context_module::instance($assign->cmid),
1367              'other' => array(
1368                  'assignid' => $assign->id,
1369                  'groupid' => 2
1370              )
1371          );
1372          $event = \mod_assign\event\group_override_created::create($params);
1373  
1374          // Trigger and capture the event.
1375          $sink = $this->redirectEvents();
1376          $event->trigger();
1377          $events = $sink->get_events();
1378          $event = reset($events);
1379  
1380          // Check that the event data is valid.
1381          $this->assertInstanceOf('\mod_assign\event\group_override_created', $event);
1382          $this->assertEquals(\context_module::instance($assign->cmid), $event->get_context());
1383          $this->assertEventContextNotUsed($event);
1384      }
1385  
1386      /**
1387       * Test the user override updated event.
1388       *
1389       * There is no external API for updating a user override, so the unit test will simply
1390       * create and trigger the event and ensure the event data is returned as expected.
1391       */
1392      public function test_user_override_updated() {
1393          $this->resetAfterTest();
1394  
1395          $course = $this->getDataGenerator()->create_course();
1396          $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1397  
1398          $params = array(
1399              'objectid' => 1,
1400              'relateduserid' => 2,
1401              'context' => \context_module::instance($assign->cmid),
1402              'other' => array(
1403                  'assignid' => $assign->id
1404              )
1405          );
1406          $event = \mod_assign\event\user_override_updated::create($params);
1407  
1408          // Trigger and capture the event.
1409          $sink = $this->redirectEvents();
1410          $event->trigger();
1411          $events = $sink->get_events();
1412          $event = reset($events);
1413  
1414          // Check that the event data is valid.
1415          $this->assertInstanceOf('\mod_assign\event\user_override_updated', $event);
1416          $this->assertEquals(\context_module::instance($assign->cmid), $event->get_context());
1417          $this->assertEventContextNotUsed($event);
1418      }
1419  
1420      /**
1421       * Test the group override updated event.
1422       *
1423       * There is no external API for updating a group override, so the unit test will simply
1424       * create and trigger the event and ensure the event data is returned as expected.
1425       */
1426      public function test_group_override_updated() {
1427          $this->resetAfterTest();
1428  
1429          $course = $this->getDataGenerator()->create_course();
1430          $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1431  
1432          $params = array(
1433              'objectid' => 1,
1434              'context' => \context_module::instance($assign->cmid),
1435              'other' => array(
1436                  'assignid' => $assign->id,
1437                  'groupid' => 2
1438              )
1439          );
1440          $event = \mod_assign\event\group_override_updated::create($params);
1441  
1442          // Trigger and capture the event.
1443          $sink = $this->redirectEvents();
1444          $event->trigger();
1445          $events = $sink->get_events();
1446          $event = reset($events);
1447  
1448          // Check that the event data is valid.
1449          $this->assertInstanceOf('\mod_assign\event\group_override_updated', $event);
1450          $this->assertEquals(\context_module::instance($assign->cmid), $event->get_context());
1451          $this->assertEventContextNotUsed($event);
1452      }
1453  
1454      /**
1455       * Test the user override deleted event.
1456       */
1457      public function test_user_override_deleted() {
1458          global $DB;
1459          $this->resetAfterTest();
1460  
1461          $course = $this->getDataGenerator()->create_course();
1462          $assigninstance = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1463          $cm = get_coursemodule_from_instance('assign', $assigninstance->id, $course->id);
1464          $context = \context_module::instance($cm->id);
1465          $assign = new \assign($context, $cm, $course);
1466  
1467          // Create an override.
1468          $override = new \stdClass();
1469          $override->assign = $assigninstance->id;
1470          $override->userid = 2;
1471          $override->id = $DB->insert_record('assign_overrides', $override);
1472  
1473          // Trigger and capture the event.
1474          $sink = $this->redirectEvents();
1475          $assign->delete_override($override->id);
1476          $events = $sink->get_events();
1477          $event = reset($events);
1478  
1479          // Check that the event data is valid.
1480          $this->assertInstanceOf('\mod_assign\event\user_override_deleted', $event);
1481          $this->assertEquals(\context_module::instance($cm->id), $event->get_context());
1482          $this->assertEventContextNotUsed($event);
1483      }
1484  
1485      /**
1486       * Test the group override deleted event.
1487       */
1488      public function test_group_override_deleted() {
1489          global $DB;
1490          $this->resetAfterTest();
1491  
1492          $course = $this->getDataGenerator()->create_course();
1493          $assigninstance = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1494          $cm = get_coursemodule_from_instance('assign', $assigninstance->id, $course->id);
1495          $context = \context_module::instance($cm->id);
1496          $assign = new \assign($context, $cm, $course);
1497  
1498          // Create an override.
1499          $override = new \stdClass();
1500          $override->assign = $assigninstance->id;
1501          $override->groupid = 2;
1502          $override->id = $DB->insert_record('assign_overrides', $override);
1503  
1504          // Trigger and capture the event.
1505          $sink = $this->redirectEvents();
1506          $assign->delete_override($override->id);
1507          $events = $sink->get_events();
1508          $event = reset($events);
1509  
1510          // Check that the event data is valid.
1511          $this->assertInstanceOf('\mod_assign\event\group_override_deleted', $event);
1512          $this->assertEquals(\context_module::instance($cm->id), $event->get_context());
1513          $this->assertEventContextNotUsed($event);
1514      }
1515  
1516      /**
1517       * Test the course module viewed event.
1518       */
1519      public function test_course_module_viewed() {
1520          $this->resetAfterTest();
1521  
1522          $course = $this->getDataGenerator()->create_course();
1523          $assign = $this->create_instance($course);
1524  
1525          $context = $assign->get_context();
1526  
1527          $params = array(
1528              'context' => $context,
1529              'objectid' => $assign->get_instance()->id
1530          );
1531  
1532          $event = \mod_assign\event\course_module_viewed::create($params);
1533  
1534          // Trigger and capture the event.
1535          $sink = $this->redirectEvents();
1536          $event->trigger();
1537          $events = $sink->get_events();
1538          $this->assertCount(1, $events);
1539          $event = reset($events);
1540  
1541          // Check that the event contains the expected values.
1542          $this->assertInstanceOf('\mod_assign\event\course_module_viewed', $event);
1543          $this->assertEquals($context, $event->get_context());
1544      }
1545  
1546      /**
1547       * Test that all events generated with blindmarking enabled are anonymous
1548       */
1549      public function test_anonymous_events() {
1550          $this->resetAfterTest();
1551  
1552          $course = $this->getDataGenerator()->create_course();
1553          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
1554          $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
1555          $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
1556  
1557          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1558          $instance = $generator->create_instance(array('course' => $course->id, 'blindmarking' => 1));
1559  
1560          $cm = get_coursemodule_from_instance('assign', $instance->id, $course->id);
1561          $context = \context_module::instance($cm->id);
1562          $assign = new \assign($context, $cm, $course);
1563  
1564          $this->setUser($teacher);
1565          $sink = $this->redirectEvents();
1566  
1567          $assign->lock_submission($student1->id);
1568  
1569          $events = $sink->get_events();
1570          $event = reset($events);
1571  
1572          $this->assertTrue((bool)$event->anonymous);
1573  
1574          $assign->reveal_identities();
1575          $sink = $this->redirectEvents();
1576          $assign->lock_submission($student2->id);
1577  
1578          $events = $sink->get_events();
1579          $event = reset($events);
1580  
1581          $this->assertFalse((bool)$event->anonymous);
1582      }
1583  
1584  }