Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 403] [Versions 39 and 311]

   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  namespace tool_monitor;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  require_once($CFG->dirroot . '/blog/locallib.php');
  23  require_once($CFG->dirroot . '/blog/lib.php');
  24  
  25  /**
  26   * Unit tests for event observers.
  27   *
  28   * @package    tool_monitor
  29   * @category   test
  30   * @copyright  2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class eventobservers_test extends \advanced_testcase {
  34      /**
  35       * Set up method.
  36       */
  37      public function setUp(): void {
  38          // Enable monitor.
  39          set_config('enablemonitor', 1, 'tool_monitor');
  40      }
  41  
  42      /**
  43       * Test observer for course delete event.
  44       */
  45      public function test_course_deleted() {
  46          global $DB;
  47  
  48          $this->setAdminUser();
  49          $this->resetAfterTest(true);
  50  
  51          $user = $this->getDataGenerator()->create_user();
  52          $course1 = $this->getDataGenerator()->create_course();
  53          $course2 = $this->getDataGenerator()->create_course();
  54          $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
  55  
  56          $rule = new \stdClass();
  57          $rule->userid = $user->id;
  58          $rule->courseid = $course1->id;
  59          $rule->plugin = 'test';
  60  
  61          $sub = new \stdClass();
  62          $sub->courseid = $course1->id;
  63          $sub->userid = $user->id;
  64  
  65          // Add 10 rules for this course with subscriptions.
  66          for ($i = 0; $i < 10; $i++) {
  67              $createdrule = $monitorgenerator->create_rule($rule);
  68              $sub->ruleid = $createdrule->id;
  69              $monitorgenerator->create_subscription($sub);
  70          }
  71  
  72          // Add 10 random rules for course 2.
  73          $rule->courseid = $course2->id;
  74          for ($i = 0; $i < 10; $i++) {
  75              $createdrule = $monitorgenerator->create_rule($rule);
  76              $sub->courseid = $rule->courseid;
  77              $sub->ruleid = $createdrule->id;
  78              $monitorgenerator->create_subscription($sub);
  79          }
  80  
  81          // Add a site rule.
  82          $rule = new \stdClass();
  83          $rule->userid = $user->id;
  84          $rule->courseid = 0;
  85          $rule->plugin = 'core';
  86          $monitorgenerator->create_rule($rule);
  87  
  88          // Verify that if we do not specify that we do not want the site rules, they are returned.
  89          $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id);
  90          $this->assertCount(11, $courserules);
  91  
  92          // Verify data before course delete.
  93          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
  94          $this->assertCount(20, $totalrules);
  95          $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
  96          $this->assertCount(10, $courserules);
  97          $this->assertEquals(20, $DB->count_records('tool_monitor_subscriptions'));
  98          $coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
  99          $this->assertCount(10, $coursesubs);
 100  
 101          // Let us delete the course now.
 102          delete_course($course1->id, false);
 103  
 104          // Confirm the site rule still exists.
 105          $this->assertEquals(1, $DB->count_records('tool_monitor_rules', array('courseid' => 0)));
 106  
 107          // Verify data after course delete.
 108          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 109          $this->assertCount(10, $totalrules);
 110          $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
 111          $this->assertCount(0, $courserules); // Making sure all rules are deleted.
 112          $this->assertEquals(10, $DB->count_records('tool_monitor_subscriptions'));
 113          $coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
 114          $this->assertCount(0, $coursesubs); // Making sure all subscriptions are deleted.
 115      }
 116  
 117      /**
 118       * This tests if writing of the events to the table tool_monitor_events is working fine.
 119       */
 120      public function test_flush() {
 121          global $DB;
 122  
 123          $this->resetAfterTest();
 124  
 125          // Create the necessary items for testing.
 126          $user = $this->getDataGenerator()->create_user();
 127          $course = $this->getDataGenerator()->create_course();
 128          $course2 = $this->getDataGenerator()->create_course();
 129          $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 130  
 131          // Fire a bunch of events.
 132          // Trigger a bunch of other events.
 133          $eventparams = array(
 134              'context' => \context_course::instance($course->id)
 135          );
 136          for ($i = 0; $i < 5; $i++) {
 137              \core\event\course_viewed::create($eventparams)->trigger();
 138              \mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
 139              \mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
 140          }
 141  
 142          // Confirm that nothing was stored in the tool_monitor_events table
 143          // as we do not have any subscriptions associated for the above events.
 144          $this->assertEquals(0, $DB->count_records('tool_monitor_events'));
 145  
 146          // Now, let's create a rule so an event can be stored.
 147          $rule = new \stdClass();
 148          $rule->courseid = $course->id;
 149          $rule->plugin = 'mod_book';
 150          $rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
 151          $rule = $monitorgenerator->create_rule($rule);
 152  
 153          // Let's subscribe to this rule.
 154          $sub = new \stdClass;
 155          $sub->courseid = $course->id;
 156          $sub->ruleid = $rule->id;
 157          $sub->userid = $user->id;
 158          $monitorgenerator->create_subscription($sub);
 159  
 160          // Again, let's just fire more events to make sure they still aren't stored.
 161          for ($i = 0; $i < 5; $i++) {
 162              \core\event\course_viewed::create($eventparams)->trigger();
 163              \mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
 164              \mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
 165          }
 166  
 167          // Fire the event we want to capture.
 168          $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
 169          $event->trigger();
 170  
 171          // Check that the event data is valid.
 172          $events = $DB->get_records('tool_monitor_events');
 173          $this->assertEquals(1, count($events));
 174          $monitorevent = array_pop($events);
 175          $this->assertEquals($event->eventname, $monitorevent->eventname);
 176          $this->assertEquals($event->contextid, $monitorevent->contextid);
 177          $this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
 178          $this->assertEquals($event->get_url()->out(), $monitorevent->link);
 179          $this->assertEquals($event->courseid, $monitorevent->courseid);
 180          $this->assertEquals($event->timecreated, $monitorevent->timecreated);
 181  
 182          // Remove the stored events.
 183          $DB->delete_records('tool_monitor_events');
 184  
 185          // Now, let's create a site wide rule.
 186          $rule = new \stdClass();
 187          $rule->courseid = 0;
 188          $rule->plugin = 'mod_book';
 189          $rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
 190          $rule = $monitorgenerator->create_rule($rule);
 191  
 192          // Let's subscribe to this rule.
 193          $sub = new \stdClass;
 194          $sub->courseid = 0;
 195          $sub->ruleid = $rule->id;
 196          $sub->userid = $user->id;
 197          $monitorgenerator->create_subscription($sub);
 198  
 199          // Fire the event we want to capture - but in a different course.
 200          $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course2);
 201          $event->trigger();
 202  
 203          // Check that the event data is valid.
 204          $events = $DB->get_records('tool_monitor_events');
 205          $this->assertEquals(1, count($events));
 206          $monitorevent = array_pop($events);
 207          $this->assertEquals($event->eventname, $monitorevent->eventname);
 208          $this->assertEquals($event->contextid, $monitorevent->contextid);
 209          $this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
 210          $this->assertEquals($event->get_url()->out(), $monitorevent->link);
 211          $this->assertEquals($event->courseid, $monitorevent->courseid);
 212          $this->assertEquals($event->timecreated, $monitorevent->timecreated);
 213      }
 214  
 215      /**
 216       * Test the notification sending features.
 217       */
 218      public function test_process_event() {
 219  
 220          global $DB, $USER;
 221  
 222          $this->resetAfterTest();
 223          $this->setAdminUser();
 224          $msgsink = $this->redirectMessages();
 225  
 226          // Generate data.
 227          $course = $this->getDataGenerator()->create_course();
 228          $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 229  
 230          $rulerecord = new \stdClass();
 231          $rulerecord->courseid = $course->id;
 232          $rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
 233          $rulerecord->frequency = 1;
 234  
 235          $rule = $toolgenerator->create_rule($rulerecord);
 236  
 237          $subrecord = new \stdClass();
 238          $subrecord->courseid = $course->id;
 239          $subrecord->ruleid = $rule->id;
 240          $subrecord->userid = $USER->id;
 241          $toolgenerator->create_subscription($subrecord);
 242  
 243          $recordexists = $DB->record_exists('task_adhoc', array('component' => 'tool_monitor'));
 244          $this->assertFalse($recordexists);
 245  
 246          // Now let us trigger the event.
 247          $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
 248          $event->trigger();
 249  
 250          $this->verify_processed_data($msgsink);
 251  
 252          // Clean up.
 253          \tool_monitor\rule_manager::delete_rule($rule->id);
 254          $DB->delete_records('tool_monitor_events');
 255  
 256          // Let us create a rule with more than 1 frequency.
 257          $rulerecord->frequency = 5;
 258          $rule = $toolgenerator->create_rule($rulerecord);
 259          $subrecord->ruleid = $rule->id;
 260          $toolgenerator->create_subscription($subrecord);
 261  
 262          // Let us trigger events.
 263          for ($i = 0; $i < 5; $i++) {
 264              $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
 265              $event->trigger();
 266              if ($i != 4) {
 267                  $this->verify_message_not_sent_yet($msgsink);
 268              }
 269          }
 270  
 271          $this->verify_processed_data($msgsink);
 272  
 273          // Clean up.
 274          \tool_monitor\rule_manager::delete_rule($rule->id);
 275          $DB->delete_records('tool_monitor_events');
 276  
 277          // Now let us create a rule specific to a module instance.
 278          $cm = new \stdClass();
 279          $cm->course = $course->id;
 280          $book = $this->getDataGenerator()->create_module('book', $cm);
 281          $rulerecord->eventname = '\mod_book\event\course_module_viewed';
 282          $rulerecord->cmid = $book->cmid;
 283          $rule = $toolgenerator->create_rule($rulerecord);
 284          $subrecord->ruleid = $rule->id;
 285          $toolgenerator->create_subscription($subrecord);
 286  
 287          // Let us trigger events.
 288          $params = array(
 289              'context' => \context_module::instance($book->cmid),
 290              'objectid' => $book->id
 291          );
 292          for ($i = 0; $i < 5; $i++) {
 293              $event = \mod_book\event\course_module_viewed::create($params);
 294              $event->trigger();
 295              if ($i != 4) {
 296                  $this->verify_message_not_sent_yet($msgsink);
 297              }
 298          }
 299  
 300          $this->verify_processed_data($msgsink);
 301  
 302          // Clean up.
 303          \tool_monitor\rule_manager::delete_rule($rule->id);
 304          $DB->delete_records('tool_monitor_events');
 305  
 306          // Now let us create a rule for event that happens in category context events.
 307          $rulerecord->eventname = '\core\event\course_category_created';
 308          $rulerecord->courseid = 0;
 309          $rule = $toolgenerator->create_rule($rulerecord);
 310          $subrecord->courseid = 0;
 311          $subrecord->ruleid = $rule->id;
 312          $toolgenerator->create_subscription($subrecord);
 313  
 314          // Let us trigger events.
 315          for ($i = 0; $i < 5; $i++) {
 316              $this->getDataGenerator()->create_category();
 317              if ($i != 4) {
 318                  $this->verify_message_not_sent_yet($msgsink);
 319              }
 320          }
 321          $this->verify_processed_data($msgsink);
 322  
 323          // Clean up.
 324          \tool_monitor\rule_manager::delete_rule($rule->id);
 325          $DB->delete_records('tool_monitor_events');
 326  
 327          // Now let us create a rule at site level.
 328          $rulerecord->eventname = '\core\event\blog_entry_created';
 329          $rulerecord->courseid = 0;
 330          $rule = $toolgenerator->create_rule($rulerecord);
 331          $subrecord->courseid = 0;
 332          $subrecord->ruleid = $rule->id;
 333          $toolgenerator->create_subscription($subrecord);
 334  
 335          // Let us trigger events.
 336          $blog = new \blog_entry();
 337          $blog->subject = "Subject of blog";
 338          $blog->userid = $USER->id;
 339          $states = \blog_entry::get_applicable_publish_states();
 340          $blog->publishstate = reset($states);
 341          for ($i = 0; $i < 5; $i++) {
 342              $newblog = fullclone($blog);
 343              $newblog->add();
 344              if ($i != 4) {
 345                  $this->verify_message_not_sent_yet($msgsink);
 346              }
 347          }
 348  
 349          $this->verify_processed_data($msgsink);
 350      }
 351  
 352      /**
 353       * Test that same events are not used twice to calculate conditions for a single subscription.
 354       */
 355      public function test_multiple_notification_not_sent() {
 356          global $USER;
 357  
 358          $this->resetAfterTest();
 359          $this->setAdminUser();
 360          $messagesink = $this->redirectMessages();
 361  
 362          // Generate data.
 363          $course = $this->getDataGenerator()->create_course();
 364          $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 365  
 366          $rulerecord = new \stdClass();
 367          $rulerecord->courseid = $course->id;
 368          $rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
 369          $rulerecord->frequency = 5;
 370  
 371          $rule = $toolgenerator->create_rule($rulerecord);
 372  
 373          $subrecord = new \stdClass();
 374          $subrecord->courseid = $course->id;
 375          $subrecord->ruleid = $rule->id;
 376          $subrecord->userid = $USER->id;
 377          $toolgenerator->create_subscription($subrecord);
 378  
 379          for ($i = 0; $i < 7; $i++) {
 380              // Now let us trigger 7 instances of the event.
 381              $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
 382              $event->trigger();
 383              $this->waitForSecond(); // Add a second delay, to prevent time collisions.
 384          }
 385          $this->run_adhock_tasks();
 386          $messages = $messagesink->get_messages();
 387          $this->assertCount(1, $messages); // There should be only one message not 3.
 388          for ($i = 0; $i < 3; $i++) {
 389              // Now let us trigger 5 more instances of the event.
 390              $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
 391              $event->trigger();
 392          }
 393  
 394          $this->run_adhock_tasks();
 395          $messages = $messagesink->get_messages();
 396          $this->assertCount(2, $messages); // There should be two messages now.
 397      }
 398  
 399      /**
 400       * Run adhoc tasks.
 401       */
 402      protected function run_adhock_tasks() {
 403          while ($task = \core\task\manager::get_next_adhoc_task(time())) {
 404              $task->execute();
 405              \core\task\manager::adhoc_task_complete($task);
 406          }
 407          $this->expectOutputRegex("/^Sending message to the user with id \d+ for the subscription with id \d+\.\.\..Sent./ms");
 408      }
 409  
 410      /**
 411       * Verify that task was scheduled and a message was sent as expected.
 412       *
 413       * @param phpunit_message_sink $msgsink Message sink
 414       */
 415      protected function verify_processed_data(\phpunit_message_sink $msgsink) {
 416          global $DB, $USER;
 417  
 418          $recordexists = $DB->count_records('task_adhoc', array('component' => 'tool_monitor'));
 419          $this->assertEquals(1, $recordexists); // We should have an adhock task now to send notifications.
 420          $this->run_adhock_tasks();
 421          $this->assertEquals(1, $msgsink->count());
 422          $msgs = $msgsink->get_messages();
 423          $msg = array_pop($msgs);
 424          $this->assertEquals($USER->id, $msg->useridto);
 425          $this->assertEquals(1, $msg->notification);
 426          $msgsink->clear();
 427      }
 428  
 429      /**
 430       * Verify that a message was not sent.
 431       *
 432       * @param phpunit_message_sink $msgsink Message sink
 433       */
 434      protected function verify_message_not_sent_yet(\phpunit_message_sink $msgsink) {
 435          $msgs = $msgsink->get_messages();
 436          $this->assertCount(0, $msgs);
 437          $msgsink->clear();
 438      }
 439  
 440      /**
 441       * Tests for replace_placeholders method.
 442       */
 443      public function test_replace_placeholders() {
 444          global $USER;
 445  
 446          $this->resetAfterTest();
 447          $this->setAdminUser();
 448          $msgsink = $this->redirectMessages();
 449  
 450          // Generate data.
 451          $course = $this->getDataGenerator()->create_course();
 452          $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 453          $context = \context_user::instance($USER->id, IGNORE_MISSING);
 454  
 455          // Creating book.
 456          $cm = new \stdClass();
 457          $cm->course = $course->id;
 458          $book = $this->getDataGenerator()->create_module('book', $cm);
 459  
 460          // Creating rule.
 461          $rulerecord = new \stdClass();
 462          $rulerecord->courseid = $course->id;
 463          $rulerecord->eventname = '\mod_book\event\course_module_viewed';
 464          $rulerecord->cmid = $book->cmid;
 465          $rulerecord->frequency = 1;
 466          $rulerecord->template = '## {link} ##
 467  
 468  * {modulelink}
 469  * __{rulename}__
 470  * {description}
 471  * {eventname}';
 472          $rulerecord->templateformat = FORMAT_MARKDOWN;
 473  
 474          $rule = $toolgenerator->create_rule($rulerecord);
 475  
 476          // Creating subscription.
 477          $subrecord = new \stdClass();
 478          $subrecord->courseid = $course->id;
 479          $subrecord->ruleid = $rule->id;
 480          $subrecord->userid = $USER->id;
 481          $toolgenerator->create_subscription($subrecord);
 482  
 483          // Now let us trigger the event.
 484          $params = array(
 485              'context' => \context_module::instance($book->cmid),
 486              'objectid' => $book->id
 487          );
 488  
 489          $event = \mod_book\event\course_module_viewed::create($params);
 490          $event->trigger();
 491          $this->run_adhock_tasks();
 492          $msgs = $msgsink->get_messages();
 493          $msg = array_pop($msgs);
 494  
 495          $modurl = new \moodle_url('/mod/book/view.php', array('id' => $book->cmid));
 496  
 497          $this->assertMatchesRegularExpression('~<h2>.*' . preg_quote($event->get_url()->out(), '~') . '.*</h2>~',
 498              $msg->fullmessagehtml);
 499          $this->assertMatchesRegularExpression('~<li>.*' . preg_quote($modurl->out(), '~') . '.*</li>~', $msg->fullmessagehtml);
 500          $this->assertStringContainsString('<li><strong>'.$rule->get_name($context).'</strong></li>', $msg->fullmessagehtml);
 501          $this->assertStringContainsString('<li>'.$rule->get_description($context).'</li>', $msg->fullmessagehtml);
 502          $this->assertStringContainsString('<li>'.$rule->get_event_name().'</li>', $msg->fullmessagehtml);
 503  
 504          $this->assertEquals(FORMAT_PLAIN, $msg->fullmessageformat);
 505          $this->assertStringNotContainsString('<h2>', $msg->fullmessage);
 506          $this->assertStringNotContainsString('##', $msg->fullmessage);
 507          $this->assertStringContainsString(strtoupper($event->get_url()->out()), $msg->fullmessage);
 508          $this->assertStringContainsString('* '.$modurl->out(), $msg->fullmessage);
 509          $this->assertStringContainsString('* '.strtoupper($rule->get_name($context)), $msg->fullmessage);
 510          $this->assertStringContainsString('* '.$rule->get_description($context), $msg->fullmessage);
 511          $this->assertStringContainsString('* '.$rule->get_event_name(), $msg->fullmessage);
 512      }
 513  
 514      /**
 515       * Test observer for user delete event.
 516       */
 517      public function test_user_deleted() {
 518          global $DB;
 519  
 520          $this->setAdminUser();
 521          $this->resetAfterTest(true);
 522  
 523          $user = $this->getDataGenerator()->create_user();
 524          $course1 = $this->getDataGenerator()->create_course();
 525          $course2 = $this->getDataGenerator()->create_course();
 526          $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 527  
 528          $rule = new \stdClass();
 529          $rule->userid = $user->id;
 530          $rule->courseid = $course1->id;
 531          $rule->plugin = 'test';
 532  
 533          $sub = new \stdClass();
 534          $sub->courseid = $course1->id;
 535          $sub->userid = $user->id;
 536  
 537          // Add 10 rules for this course with subscriptions.
 538          for ($i = 0; $i < 10; $i++) {
 539              $createdrule = $monitorgenerator->create_rule($rule);
 540              $sub->ruleid = $createdrule->id;
 541              $monitorgenerator->create_subscription($sub);
 542          }
 543  
 544          // Add 10 random rules for course 2.
 545          $rule->courseid = $course2->id;
 546          for ($i = 0; $i < 10; $i++) {
 547              $createdrule = $monitorgenerator->create_rule($rule);
 548              $sub->courseid = $rule->courseid;
 549              $sub->ruleid = $createdrule->id;
 550              $monitorgenerator->create_subscription($sub);
 551          }
 552  
 553          // Verify data before user delete.
 554          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 555          $this->assertCount(20, $totalrules);
 556          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 557          $this->assertCount(20, $totalsubs);
 558  
 559          // Let us delete the user now.
 560          delete_user($user);
 561  
 562          // Verify data after course delete.
 563          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 564          $this->assertCount(20, $totalrules);
 565          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 566          $this->assertCount(0, $totalsubs); // Make sure all subscriptions are deleted.
 567      }
 568  
 569      /**
 570       * Test observer for course module delete event.
 571       */
 572      public function test_course_module_deleted() {
 573          global $DB;
 574  
 575          $this->setAdminUser();
 576          $this->resetAfterTest(true);
 577  
 578          $user = $this->getDataGenerator()->create_user();
 579          $course1 = $this->getDataGenerator()->create_course();
 580          $course2 = $this->getDataGenerator()->create_course();
 581          $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 582  
 583          // Now let us create a rule specific to a module instance.
 584          $cm = new \stdClass();
 585          $cm->course = $course1->id;
 586          $book = $this->getDataGenerator()->create_module('book', $cm);
 587  
 588          $rule = new \stdClass();
 589          $rule->userid = $user->id;
 590          $rule->courseid = $course1->id;
 591          $rule->plugin = 'test';
 592  
 593          $sub = new \stdClass();
 594          $sub->courseid = $course1->id;
 595          $sub->userid = $user->id;
 596          $sub->cmid = $book->cmid;
 597  
 598          // Add 10 rules for this course with subscriptions for this module.
 599          for ($i = 0; $i < 10; $i++) {
 600              $createdrule = $monitorgenerator->create_rule($rule);
 601              $sub->ruleid = $createdrule->id;
 602              $monitorgenerator->create_subscription($sub);
 603          }
 604  
 605          // Add 10 random rules for course 2.
 606          $rule->courseid = $course2->id;
 607          for ($i = 0; $i < 10; $i++) {
 608              $createdrule = $monitorgenerator->create_rule($rule);
 609              $sub->courseid = $rule->courseid;
 610              $sub->ruleid = $createdrule->id;
 611              $sub->cmid = 0;
 612              $monitorgenerator->create_subscription($sub);
 613          }
 614  
 615          // Verify data before module delete.
 616          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 617          $this->assertCount(20, $totalrules);
 618          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 619          $this->assertCount(20, $totalsubs);
 620  
 621          // Let us delete the user now.
 622          course_delete_module($book->cmid);
 623  
 624          // Verify data after course delete.
 625          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 626          $this->assertCount(20, $totalrules);
 627          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 628          $this->assertCount(10, $totalsubs); // Make sure only relevant subscriptions are deleted.
 629      }
 630  
 631  }