Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403] [Versions 402 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  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(['fullname' => 'Observed course', 'shortname' => 'obscourse']);
 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          $cm->name = 'Observed book';
 459          $book = $this->getDataGenerator()->create_module('book', $cm);
 460  
 461          // Creating rule.
 462          $rulerecord = new \stdClass();
 463          $rulerecord->courseid = $course->id;
 464          $rulerecord->eventname = '\mod_book\event\course_module_viewed';
 465          $rulerecord->cmid = $book->cmid;
 466          $rulerecord->frequency = 1;
 467          $rulerecord->template = '## {link} ##
 468  
 469  * {modulelink}
 470  * __{rulename}__
 471  * {description}
 472  * {eventname}
 473  * {modulename}
 474  * {coursefullname}
 475  * {courseshortname}';
 476          $rulerecord->templateformat = FORMAT_MARKDOWN;
 477  
 478          $rule = $toolgenerator->create_rule($rulerecord);
 479  
 480          // Creating subscription.
 481          $subrecord = new \stdClass();
 482          $subrecord->courseid = $course->id;
 483          $subrecord->ruleid = $rule->id;
 484          $subrecord->userid = $USER->id;
 485          $toolgenerator->create_subscription($subrecord);
 486  
 487          // Now let us trigger the event.
 488          $params = array(
 489              'context' => \context_module::instance($book->cmid),
 490              'objectid' => $book->id
 491          );
 492  
 493          $event = \mod_book\event\course_module_viewed::create($params);
 494          $event->trigger();
 495          $this->run_adhock_tasks();
 496          $msgs = $msgsink->get_messages();
 497          $msg = array_pop($msgs);
 498  
 499          $modurl = new \moodle_url('/mod/book/view.php', array('id' => $book->cmid));
 500  
 501          $this->assertMatchesRegularExpression('~<h2>.*' . preg_quote($event->get_url()->out(), '~') . '.*</h2>~',
 502              $msg->fullmessagehtml);
 503          $this->assertMatchesRegularExpression('~<li>.*' . preg_quote($modurl->out(), '~') . '.*</li>~', $msg->fullmessagehtml);
 504          $this->assertStringContainsString('<li><strong>'.$rule->get_name($context).'</strong></li>', $msg->fullmessagehtml);
 505          $this->assertStringContainsString('<li>'.$rule->get_description($context).'</li>', $msg->fullmessagehtml);
 506          $this->assertStringContainsString('<li>'.$rule->get_event_name().'</li>', $msg->fullmessagehtml);
 507          $this->assertStringContainsString('<li>' . $cm->name . '</li>', $msg->fullmessagehtml);
 508          $this->assertStringContainsString('<li>' . $course->fullname . '</li>', $msg->fullmessagehtml);
 509          $this->assertStringContainsString('<li>' . $course->shortname . '</li>', $msg->fullmessagehtml);
 510  
 511          $this->assertEquals(FORMAT_PLAIN, $msg->fullmessageformat);
 512          $this->assertStringNotContainsString('<h2>', $msg->fullmessage);
 513          $this->assertStringNotContainsString('##', $msg->fullmessage);
 514          $this->assertStringContainsString(strtoupper($event->get_url()->out()), $msg->fullmessage);
 515          $this->assertStringContainsString('* '.$modurl->out(), $msg->fullmessage);
 516          $this->assertStringContainsString('* '.strtoupper($rule->get_name($context)), $msg->fullmessage);
 517          $this->assertStringContainsString('* '.$rule->get_description($context), $msg->fullmessage);
 518          $this->assertStringContainsString('* '.$rule->get_event_name(), $msg->fullmessage);
 519          $this->assertStringContainsString('* ' . $cm->name, $msg->fullmessage);
 520          $this->assertStringContainsString('* ' . $course->fullname, $msg->fullmessage);
 521          $this->assertStringContainsString('* ' . $course->shortname, $msg->fullmessage);
 522  
 523      }
 524  
 525      /**
 526       * Test observer for user delete event.
 527       */
 528      public function test_user_deleted() {
 529          global $DB;
 530  
 531          $this->setAdminUser();
 532          $this->resetAfterTest(true);
 533  
 534          $user = $this->getDataGenerator()->create_user();
 535          $course1 = $this->getDataGenerator()->create_course();
 536          $course2 = $this->getDataGenerator()->create_course();
 537          $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 538  
 539          $rule = new \stdClass();
 540          $rule->userid = $user->id;
 541          $rule->courseid = $course1->id;
 542          $rule->plugin = 'test';
 543  
 544          $sub = new \stdClass();
 545          $sub->courseid = $course1->id;
 546          $sub->userid = $user->id;
 547  
 548          // Add 10 rules for this course with subscriptions.
 549          for ($i = 0; $i < 10; $i++) {
 550              $createdrule = $monitorgenerator->create_rule($rule);
 551              $sub->ruleid = $createdrule->id;
 552              $monitorgenerator->create_subscription($sub);
 553          }
 554  
 555          // Add 10 random rules for course 2.
 556          $rule->courseid = $course2->id;
 557          for ($i = 0; $i < 10; $i++) {
 558              $createdrule = $monitorgenerator->create_rule($rule);
 559              $sub->courseid = $rule->courseid;
 560              $sub->ruleid = $createdrule->id;
 561              $monitorgenerator->create_subscription($sub);
 562          }
 563  
 564          // Verify data before user delete.
 565          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 566          $this->assertCount(20, $totalrules);
 567          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 568          $this->assertCount(20, $totalsubs);
 569  
 570          // Let us delete the user now.
 571          delete_user($user);
 572  
 573          // Verify data after course delete.
 574          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 575          $this->assertCount(20, $totalrules);
 576          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 577          $this->assertCount(0, $totalsubs); // Make sure all subscriptions are deleted.
 578      }
 579  
 580      /**
 581       * Test observer for course module delete event.
 582       */
 583      public function test_course_module_deleted() {
 584          global $DB;
 585  
 586          $this->setAdminUser();
 587          $this->resetAfterTest(true);
 588  
 589          $user = $this->getDataGenerator()->create_user();
 590          $course1 = $this->getDataGenerator()->create_course();
 591          $course2 = $this->getDataGenerator()->create_course();
 592          $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
 593  
 594          // Now let us create a rule specific to a module instance.
 595          $cm = new \stdClass();
 596          $cm->course = $course1->id;
 597          $book = $this->getDataGenerator()->create_module('book', $cm);
 598  
 599          $rule = new \stdClass();
 600          $rule->userid = $user->id;
 601          $rule->courseid = $course1->id;
 602          $rule->plugin = 'test';
 603  
 604          $sub = new \stdClass();
 605          $sub->courseid = $course1->id;
 606          $sub->userid = $user->id;
 607          $sub->cmid = $book->cmid;
 608  
 609          // Add 10 rules for this course with subscriptions for this module.
 610          for ($i = 0; $i < 10; $i++) {
 611              $createdrule = $monitorgenerator->create_rule($rule);
 612              $sub->ruleid = $createdrule->id;
 613              $monitorgenerator->create_subscription($sub);
 614          }
 615  
 616          // Add 10 random rules for course 2.
 617          $rule->courseid = $course2->id;
 618          for ($i = 0; $i < 10; $i++) {
 619              $createdrule = $monitorgenerator->create_rule($rule);
 620              $sub->courseid = $rule->courseid;
 621              $sub->ruleid = $createdrule->id;
 622              $sub->cmid = 0;
 623              $monitorgenerator->create_subscription($sub);
 624          }
 625  
 626          // Verify data before module delete.
 627          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 628          $this->assertCount(20, $totalrules);
 629          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 630          $this->assertCount(20, $totalsubs);
 631  
 632          // Let us delete the user now.
 633          course_delete_module($book->cmid);
 634  
 635          // Verify data after course delete.
 636          $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
 637          $this->assertCount(20, $totalrules);
 638          $totalsubs = $DB->get_records('tool_monitor_subscriptions');
 639          $this->assertCount(10, $totalsubs); // Make sure only relevant subscriptions are deleted.
 640      }
 641  
 642  }