first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,28 @@
@tool @tool_monitor
Feature: In a course administration page, navigate through report page, test for course event monitor page
In order to navigate through report page
As an admin
Go to course administration -> reports -> Event monitoring rules
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode | enablecompletion |
| Course 1 | C1 | 0 | 1 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| admin | C1 | editingteacher |
| student1 | C1 | student |
@javascript
Scenario: Selector should be available in the course event monitoring page
Given I log in as "admin"
And I navigate to "Reports > Event monitoring rules" in site administration
And I click on "Enable" "link"
And I am on "Course 1" course homepage
When I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
Then "Report type" "field" should exist
And I should see "Event monitoring rules" in the "Report type" "field"
@@ -0,0 +1,19 @@
@tool @tool_monitor
Feature: Enable/disable managment of the event monitor
In order to manage event monitoring
As an admin
I need to enable/disable it
Scenario: Tool is disabled by default.
Given I log in as "admin"
When I navigate to "Reports > Event monitoring rules" in site administration
Then I should see "Event monitoring is currently disabled"
And I should see "Enable"
And I should not see "Add a new rule"
And I click on "Enable" "link"
And I should see "Event monitoring is currently enabled"
And I should see "Disable"
And I should see "Add a new rule"
And I click on "Disable" "link"
And I should see "Event monitoring is currently disabled"
And I should not see "Add a new rule"
+169
View File
@@ -0,0 +1,169 @@
@javascript @tool @tool_monitor @tool_monitor_rules
Feature: tool_monitor_rule
In order to manage rules
As an admin
I need to create a rule, edit a rule, duplicate a rule and delete a rule
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I log in as "admin"
And I navigate to "Reports > Event monitoring rules" in site administration
And I click on "Enable" "link"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
And I press "Add a new rule"
And I set the following fields to these values:
| name | New rule course level |
| plugin | Forum |
| eventname | Post created |
| id_description | I want a rule to monitor posts created on a forum |
| frequency | 1 |
| minutes | 1 |
| Notification message | The forum post was created. {modulelink} |
And I press "Save changes"
And I navigate to "Reports > Event monitoring rules" in site administration
And I press "Add a new rule"
And I set the following fields to these values:
| name | New rule site level |
| plugin | Forum |
| eventname | Post created |
| id_description | I want a rule to monitor posts created on a forum |
| frequency | 1 |
| minutes | 1 |
| Notification message | The forum post was created. {modulelink} |
And I press "Save changes"
And I log out
Scenario: Add a rule on course level
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
When I press "Add a new rule"
And I set the following fields to these values:
| name | New rule |
| plugin | Forum |
| eventname | Post created |
| id_description | I want a rule to monitor posts created on a forum |
| frequency | 1 |
| minutes | 1 |
| Notification message | The forum post was created. {modulelink} |
And I press "Save changes"
Then "New rule" row "Course" column of "toolmonitorrules_table" table should contain "Course 1"
And I should see "I want a rule to monitor posts created on a forum"
And I should see "Forum"
And I should see "Post created"
And I should see "1 time(s) in 1 minute(s)"
Scenario: Delete a rule on course level
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
When I click on "Delete rule" "link"
Then I should see "Are you sure you want to delete the rule \"New rule course level\"?"
And I press "Continue"
And I should see "Rule successfully deleted"
And I should not see "New rule course level"
Scenario: Edit a rule on course level
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
When I click on "Edit rule" "link"
And I set the following fields to these values:
| name | New rule quiz |
| plugin | Quiz |
| eventname | Quiz attempt deleted |
| id_description | I want a rule to monitor quiz attempts deleted |
| frequency | 5 |
| minutes | 5 |
| Notification message | Quiz attempt deleted. {modulelink} |
And I press "Save changes"
Then I should see "New rule quiz"
And I should see "I want a rule to monitor quiz attempts deleted"
And I should see "Quiz attempt deleted"
And I should see "5 time(s) in 5 minute(s)"
Scenario: Duplicate a rule on course level
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
When I click on "Duplicate rule" "link" in the "New rule course level" "table_row"
Then I should see "Rule successfully duplicated"
And "#toolmonitorrules_r1" "css_element" should appear before "#toolmonitorrules_r2" "css_element"
And I should see "New rule"
And I should see "I want a rule to monitor posts created on a forum"
And I should see "Forum"
And I should see "Post created"
And I should see "1 time(s) in 1 minute(s)"
Scenario: Add a rule on site level
Given I log in as "admin"
And I navigate to "Reports > Event monitoring rules" in site administration
When I press "Add a new rule"
And I set the following fields to these values:
| name | New rule |
| plugin | Forum |
| eventname | Post created |
| id_description | I want a rule to monitor posts created on a forum |
| frequency | 1 |
| minutes | 1 |
| Notification message | The forum post was created. {modulelink} |
And I press "Save changes"
Then "New rule" row "Course" column of "toolmonitorrules_table" table should contain "Site"
And I should see "I want a rule to monitor posts created on a forum"
And I should see "Forum"
And I should see "Post created"
And I should see "1 time(s) in 1 minute(s)"
Scenario: Delete a rule on site level
Given I log in as "admin"
And I navigate to "Reports > Event monitoring rules" in site administration
When I click on "Delete rule" "link"
Then I should see "Are you sure you want to delete the rule \"New rule site level\"?"
And I press "Continue"
And I should see "Rule successfully deleted"
And I should not see "New rule site level"
Scenario: Edit a rule on site level
Given I log in as "admin"
And I navigate to "Reports > Event monitoring rules" in site administration
When I click on "Edit rule" "link"
And I set the following fields to these values:
| name | New Rule Quiz |
| plugin | Quiz |
| eventname | Quiz attempt deleted |
| id_description | I want a rule to monitor quiz attempts deleted |
| frequency | 5 |
| minutes | 5 |
| Notification message | Quiz attempt deleted. {modulelink} |
And I press "Save changes"
Then I should see "New Rule Quiz"
And I should see "I want a rule to monitor quiz attempts deleted"
And I should see "Quiz attempt deleted"
And I should see "5 time(s) in 5 minute(s)"
Scenario: Duplicate a rule on site level
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
When I click on "Duplicate rule" "link" in the "New rule site level" "table_row"
Then I should see "Rule successfully duplicated"
And "#toolmonitorrules_r2" "css_element" should appear after "#toolmonitorrules_r1" "css_element"
And I should see "I want a rule to monitor posts created on a forum"
And I should see "Forum"
And I should see "Post created"
And I should see "1 time(s) in 1 minute(s)"
@@ -0,0 +1,29 @@
@tool @tool_monitor @javascript
Feature: Verify the breadcrumbs in different event monitor site administration pages
Whenever I navigate to event monitoring page in site administration
As an admin
The breadcrumbs should be visible
Whenever I land on pages to add a new rule, edit rule or delete rule
As an admin
The breadcrumbs should be visible
Background:
Given I log in as "admin"
Scenario: Verify the breadcrumbs in event monitoring page by visiting add a new rule, edit a rule and delete rule pages as an admin
Given I navigate to "Reports > Event monitoring rules" in site administration
And I click on "Enable" "link"
When I click on "Add a new rule" "link"
Then "Add a new rule" "text" should exist in the ".breadcrumb" "css_element"
And "Event monitoring rules" "link" should exist in the ".breadcrumb" "css_element"
And I set the field "Rule name" to "Testing1"
And I set the field "Area to monitor" to "Subsystem (core)"
And I set the field "Event" to "Allow role override"
And I press "Save changes"
And I click on "Edit rule" "link"
And "Edit rule" "text" should exist in the ".breadcrumb" "css_element"
And "Event monitoring rules" "link" should exist in the ".breadcrumb" "css_element"
And I press "Cancel"
And I click on "Delete rule" "link"
And "Delete rule" "text" should exist in the ".breadcrumb" "css_element"
And "Event monitoring rules" "link" should exist in the ".breadcrumb" "css_element"
@@ -0,0 +1,181 @@
@javascript @tool @tool_monitor @tool_monitor_subscriptions
Feature: tool_monitor_subscriptions
In order to monitor events and receive notifications
As an user
I need to create a new rule, subscribe to it, receive notification and delete subscription
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
| Course 2 | C2 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| teacher2 | Teacher | 2 | teacher2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| teacher1 | C2 | teacher |
| teacher2 | C1 | teacher |
| teacher2 | C2 | editingteacher |
And I log in as "admin"
And I navigate to "Reports > Event monitoring rules" in site administration
And I click on "Enable" "link"
And I am on "Course 1" course homepage
And I navigate to "Reports" in current page administration
And I click on "Event monitoring rules" "link"
And I press "Add a new rule"
And I set the following fields to these values:
| name | New rule course level |
| plugin | Subsystem (core) |
| eventname | Course viewed |
| id_description | I want a rule to monitor when a course is viewed. |
| frequency | 1 |
| minutes | 1 |
| Notification message | The course was viewed. {modulelink} |
And I press "Save changes"
And I navigate to "Reports > Event monitoring rules" in site administration
And I press "Add a new rule"
And I set the following fields to these values:
| name | New rule site level |
| plugin | Subsystem (core) |
| eventname | Course viewed |
| id_description | I want a rule to monitor when a course is viewed. |
| frequency | 1 |
| minutes | 1 |
| Notification message | The course was viewed. {modulelink} |
And I press "Save changes"
And I navigate to "Users > Permissions > Define roles" in site administration
And I follow "Non-editing teacher"
And I press "Edit"
And I click on "tool/monitor:managerules" "checkbox"
And I press "Save changes"
And I log out
Scenario: Subscribe to a rule on course level
Given I log in as "teacher1"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
When I follow "Subscribe to rule \"New rule course level\""
Then I should see "Subscription successfully created"
And "#toolmonitorsubs_r0" "css_element" should exist
Scenario: Delete a subscription on course level
Given I log in as "teacher1"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I follow "Subscribe to rule \"New rule course level\""
And I should see "Subscription successfully created"
When I click on "Delete subscription" "link" in the "New rule course level" "table_row"
And I should see "Are you sure you want to delete the subscription to the rule \"New rule course level\"?"
And I press "Continue"
Then I should see "Subscription successfully removed"
And "#toolmonitorsubs_r0" "css_element" should not exist
Scenario: Subscribe to a rule on site level
Given I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Acceptance test site"
When I follow "Subscribe to rule \"New rule site level\""
Then I should see "Subscription successfully created"
And "#toolmonitorsubs_r0" "css_element" should exist
Scenario: Delete a subscription on site level
Given I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Acceptance test site"
And I follow "Subscribe to rule \"New rule site level\""
And I should see "Subscription successfully created"
And "#toolmonitorsubs_r0" "css_element" should exist
When I click on "Delete subscription" "link" in the "New rule site level" "table_row"
And I should see "Are you sure you want to delete the subscription to the rule \"New rule site level\"?"
And I press "Continue"
Then I should see "Subscription successfully removed"
And "#toolmonitorsubs_r0" "css_element" should not exist
@_bug_phantomjs
Scenario: Receiving notification on site level
Given I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Acceptance test site"
And I follow "Subscribe to rule \"New rule site level\""
And I should see "Subscription successfully created"
And "#toolmonitorsubs_r0" "css_element" should exist
And I am on site homepage
And I trigger cron
And I am on site homepage
When I click on ".popover-region-notifications" "css_element"
And I click on "View full notification" "link" in the ".popover-region-notifications" "css_element"
Then I should see "New rule site level"
And I should see "The course was viewed"
@_bug_phantomjs
Scenario: Receiving notification on course level
Given I log in as "teacher1"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I follow "Subscribe to rule \"New rule course level\""
And I should see "Subscription successfully created"
And "#toolmonitorsubs_r0" "css_element" should exist
And I am on "Course 1" course homepage
And I trigger cron
And I am on site homepage
When I click on ".popover-region-notifications" "css_element"
And I click on "View full notification" "link" in the ".popover-region-notifications" "css_element"
Then I should see "New rule course level"
And I should see "The course was viewed"
Scenario: Navigating via quick link to rules
Given I log in as "admin"
And I follow "Preferences" in the user menu
When I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
Then I should see "You can manage rules from the Event monitoring rules page."
And I click on "Event monitoring rules" "link" in the "region-main" "region"
And I should see "You can subscribe to rules from the Event monitoring page."
And I log out
And I log in as "teacher1"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I should see "You can manage rules from the Event monitoring rules page."
And I click on "Event monitoring rules" "link" in the "region-main" "region"
And I should see "You can subscribe to rules from the Event monitoring page."
And I click on "//a[text()='Event monitoring']" "xpath_element"
And the field "courseid" matches value "Course 1"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I should not see "You can manage rules from the Event monitoring rules page."
And I log out
And I log in as "teacher2"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I should not see "You can manage rules the from the Event monitoring rules page."
Scenario: No manage rules link when user does not have permission
Given the following "role capability" exists:
| role | teacher |
| tool/monitor:managerules | prohibit |
And I log in as "teacher1"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
When I set the field "Select a course" to "Course 1"
Then I should see "You can manage rules from the Event monitoring rules page."
And I set the field "Select a course" to "Course 2"
And I should not see "You can manage rules from the Event monitoring rules page."
And I log out
And I log in as "teacher2"
And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I should not see "You can manage rules from the Event monitoring rules page."
And I set the field "Select a course" to "Course 2"
And I should see "You can manage rules from the Event monitoring rules page."
@@ -0,0 +1,344 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Events tests.
*
* @package tool_monitor
* @category test
* @copyright 2014 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_monitor\event;
/**
* Tests that the tool_monitor events are valid and triggered correctly.
*/
class events_test extends \advanced_testcase {
/**
* Tests set up.
*/
public function setUp(): void {
set_config('enablemonitor', 1, 'tool_monitor');
$this->resetAfterTest();
}
/**
* Test the rule created event.
*/
public function test_rule_created(): void {
// Create the items we need to create a rule.
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
// Create the variables for the rule we want to create.
$ruledata = new \stdClass();
$ruledata->userid = $user->id;
$ruledata->courseid = $course->id;
$ruledata->plugin = 'mod_assign';
$ruledata->eventname = '\mod_assign\event\submission_viewed';
$ruledata->description = 'Rule description';
$ruledata->descriptionformat = FORMAT_HTML;
$ruledata->template = 'A message template';
$ruledata->templateformat = FORMAT_HTML;
$ruledata->frequency = 1;
$ruledata->timewindow = 60;
// Trigger and capture the event.
$sink = $this->redirectEvents();
$rule = \tool_monitor\rule_manager::add_rule($ruledata);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event contains the expected values.
$this->assertInstanceOf('\tool_monitor\event\rule_created', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEquals($rule->id, $event->objectid);
$this->assertEventContextNotUsed($event);
// Now let's add a system rule (courseid = 0).
$ruledata->courseid = 0;
// Trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\rule_manager::add_rule($ruledata);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event uses the system context.
$this->assertInstanceOf('\tool_monitor\event\rule_created', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
}
/**
* Test the rule updated event.
*/
public function test_rule_updated(): void {
// Create the items we need.
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$course = $this->getDataGenerator()->create_course();
// Create the rule we are going to update.
$createrule = new \stdClass();
$createrule->courseid = $course->id;
$rule = $monitorgenerator->create_rule($createrule);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$updaterule = new \stdClass();
$updaterule->id = $rule->id;
\tool_monitor\rule_manager::update_rule($updaterule);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event contains the expected values.
$this->assertInstanceOf('\tool_monitor\event\rule_updated', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEquals($rule->id, $event->objectid);
$this->assertEventContextNotUsed($event);
// Now let's update a system rule (courseid = 0).
$createrule->courseid = 0;
$rule = $monitorgenerator->create_rule($createrule);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$updaterule = new \stdClass();
$updaterule->id = $rule->id;
\tool_monitor\rule_manager::update_rule($updaterule);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event uses the system context.
$this->assertInstanceOf('\tool_monitor\event\rule_updated', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
}
/**
* Test the rule deleted event.
*/
public function test_rule_deleted(): void {
// Create the items we need.
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$course = $this->getDataGenerator()->create_course();
// Create the rule we are going to delete.
$createrule = new \stdClass();
$createrule->courseid = $course->id;
$rule = $monitorgenerator->create_rule($createrule);
// Trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\rule_manager::delete_rule($rule->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event contains the expected values.
$this->assertInstanceOf('\tool_monitor\event\rule_deleted', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEquals($rule->id, $event->objectid);
$this->assertEventContextNotUsed($event);
// Now let's delete a system rule (courseid = 0).
$createrule = new \stdClass();
$createrule->courseid = 0;
$rule = $monitorgenerator->create_rule($createrule);
// Trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\rule_manager::delete_rule($rule->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event uses the system context.
$this->assertInstanceOf('\tool_monitor\event\rule_deleted', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
}
/**
* Test the subscription created event.
*/
public function test_subscription_created(): void {
// Create the items we need to test this.
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule to subscribe to.
$rule = $monitorgenerator->create_rule();
// Trigger and capture the event.
$sink = $this->redirectEvents();
$subscriptionid = \tool_monitor\subscription_manager::create_subscription($rule->id, $course->id, 0, $user->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event contains the expected values.
$this->assertInstanceOf('\tool_monitor\event\subscription_created', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEquals($subscriptionid, $event->objectid);
$this->assertEventContextNotUsed($event);
// Create a system subscription - trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\subscription_manager::create_subscription($rule->id, 0, 0, $user->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event uses the system context.
$this->assertInstanceOf('\tool_monitor\event\subscription_created', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
}
/**
* Test the subscription deleted event.
*/
public function test_subscription_deleted(): void {
// Create the items we need to test this.
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule to subscribe to.
$rule = $monitorgenerator->create_rule();
$sub = new \stdClass();
$sub->courseid = $course->id;
$sub->userid = $user->id;
$sub->ruleid = $rule->id;
// Create the subscription we are going to delete.
$subscription = $monitorgenerator->create_subscription($sub);
// Trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\subscription_manager::delete_subscription($subscription->id, false);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event contains the expected values.
$this->assertInstanceOf('\tool_monitor\event\subscription_deleted', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEquals($subscription->id, $event->objectid);
$this->assertEventContextNotUsed($event);
// Now let's delete a system subscription.
$sub = new \stdClass();
$sub->courseid = 0;
$sub->userid = $user->id;
$sub->ruleid = $rule->id;
// Create the subscription we are going to delete.
$subscription = $monitorgenerator->create_subscription($sub);
// Trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\subscription_manager::delete_subscription($subscription->id, false);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event uses the system context.
$this->assertInstanceOf('\tool_monitor\event\subscription_deleted', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
// Now, create a bunch of subscriptions for the rule we created.
$subids = array();
$sub->courseid = $course->id;
for ($i = 1; $i <= 10; $i++) {
$sub->userid = $i;
$subscription = $monitorgenerator->create_subscription($sub);
$subids[$subscription->id] = $subscription;
}
// Trigger and capture the events.
$sink = $this->redirectEvents();
\tool_monitor\subscription_manager::remove_all_subscriptions_for_rule($rule->id);
$events = $sink->get_events();
// Check that there were 10 events in total.
$this->assertCount(10, $events);
// Get all the events and ensure they are valid.
foreach ($events as $event) {
$this->assertInstanceOf('\tool_monitor\event\subscription_deleted', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEventContextNotUsed($event);
$this->assertArrayHasKey($event->objectid, $subids);
unset($subids[$event->objectid]);
}
// We should have found all the subscriptions.
$this->assertEmpty($subids);
}
/**
* Test the subscription criteria met event.
*/
public function test_subscription_criteria_met(): void {
// Create the items we need to test this.
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$book = $this->getDataGenerator()->create_module('book', array('course' => $course->id));
$bookgenerator = $this->getDataGenerator()->get_plugin_generator('mod_book');
$chapter = $bookgenerator->create_chapter(array('bookid' => $book->id));
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule we want to subscribe to.
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = $course->id;
$rule->plugin = 'mod_book';
$rule->eventname = '\mod_book\event\chapter_viewed';
$rule->frequency = 1;
$rule->timewindow = 60;
$rule = $monitorgenerator->create_rule($rule);
// Create the subscription.
$sub = new \stdClass();
$sub->courseid = $course->id;
$sub->userid = $user->id;
$sub->ruleid = $rule->id;
$monitorgenerator->create_subscription($sub);
// Now create the \mod_book\event\chapter_viewed event we are listening for.
$context = \context_module::instance($book->cmid);
$event = \mod_book\event\chapter_viewed::create_from_chapter($book, $context, $chapter);
// Trigger and capture the event.
$sink = $this->redirectEvents();
\tool_monitor\eventobservers::process_event($event);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Confirm that the event contains the expected values.
$this->assertInstanceOf('\tool_monitor\event\subscription_criteria_met', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEventContextNotUsed($event);
}
}
@@ -0,0 +1,642 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/blog/locallib.php');
require_once($CFG->dirroot . '/blog/lib.php');
/**
* Unit tests for event observers.
*
* @package tool_monitor
* @category test
* @copyright 2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class eventobservers_test extends \advanced_testcase {
/**
* Set up method.
*/
public function setUp(): void {
// Enable monitor.
set_config('enablemonitor', 1, 'tool_monitor');
}
/**
* Test observer for course delete event.
*/
public function test_course_deleted(): void {
global $DB;
$this->setAdminUser();
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = $course1->id;
$rule->plugin = 'test';
$sub = new \stdClass();
$sub->courseid = $course1->id;
$sub->userid = $user->id;
// Add 10 rules for this course with subscriptions.
for ($i = 0; $i < 10; $i++) {
$createdrule = $monitorgenerator->create_rule($rule);
$sub->ruleid = $createdrule->id;
$monitorgenerator->create_subscription($sub);
}
// Add 10 random rules for course 2.
$rule->courseid = $course2->id;
for ($i = 0; $i < 10; $i++) {
$createdrule = $monitorgenerator->create_rule($rule);
$sub->courseid = $rule->courseid;
$sub->ruleid = $createdrule->id;
$monitorgenerator->create_subscription($sub);
}
// Add a site rule.
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = 0;
$rule->plugin = 'core';
$monitorgenerator->create_rule($rule);
// Verify that if we do not specify that we do not want the site rules, they are returned.
$courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id);
$this->assertCount(11, $courserules);
// Verify data before course delete.
$totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
$this->assertCount(20, $totalrules);
$courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
$this->assertCount(10, $courserules);
$this->assertEquals(20, $DB->count_records('tool_monitor_subscriptions'));
$coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
$this->assertCount(10, $coursesubs);
// Let us delete the course now.
delete_course($course1->id, false);
// Confirm the site rule still exists.
$this->assertEquals(1, $DB->count_records('tool_monitor_rules', array('courseid' => 0)));
// Verify data after course delete.
$totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
$this->assertCount(10, $totalrules);
$courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
$this->assertCount(0, $courserules); // Making sure all rules are deleted.
$this->assertEquals(10, $DB->count_records('tool_monitor_subscriptions'));
$coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
$this->assertCount(0, $coursesubs); // Making sure all subscriptions are deleted.
}
/**
* This tests if writing of the events to the table tool_monitor_events is working fine.
*/
public function test_flush(): void {
global $DB;
$this->resetAfterTest();
// Create the necessary items for testing.
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Fire a bunch of events.
// Trigger a bunch of other events.
$eventparams = array(
'context' => \context_course::instance($course->id)
);
for ($i = 0; $i < 5; $i++) {
\core\event\course_viewed::create($eventparams)->trigger();
\mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
\mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
}
// Confirm that nothing was stored in the tool_monitor_events table
// as we do not have any subscriptions associated for the above events.
$this->assertEquals(0, $DB->count_records('tool_monitor_events'));
// Now, let's create a rule so an event can be stored.
$rule = new \stdClass();
$rule->courseid = $course->id;
$rule->plugin = 'mod_book';
$rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
$rule = $monitorgenerator->create_rule($rule);
// Let's subscribe to this rule.
$sub = new \stdClass;
$sub->courseid = $course->id;
$sub->ruleid = $rule->id;
$sub->userid = $user->id;
$monitorgenerator->create_subscription($sub);
// Again, let's just fire more events to make sure they still aren't stored.
for ($i = 0; $i < 5; $i++) {
\core\event\course_viewed::create($eventparams)->trigger();
\mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
\mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
}
// Fire the event we want to capture.
$event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
$event->trigger();
// Check that the event data is valid.
$events = $DB->get_records('tool_monitor_events');
$this->assertEquals(1, count($events));
$monitorevent = array_pop($events);
$this->assertEquals($event->eventname, $monitorevent->eventname);
$this->assertEquals($event->contextid, $monitorevent->contextid);
$this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
$this->assertEquals($event->get_url()->out(), $monitorevent->link);
$this->assertEquals($event->courseid, $monitorevent->courseid);
$this->assertEquals($event->timecreated, $monitorevent->timecreated);
// Remove the stored events.
$DB->delete_records('tool_monitor_events');
// Now, let's create a site wide rule.
$rule = new \stdClass();
$rule->courseid = 0;
$rule->plugin = 'mod_book';
$rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
$rule = $monitorgenerator->create_rule($rule);
// Let's subscribe to this rule.
$sub = new \stdClass;
$sub->courseid = 0;
$sub->ruleid = $rule->id;
$sub->userid = $user->id;
$monitorgenerator->create_subscription($sub);
// Fire the event we want to capture - but in a different course.
$event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course2);
$event->trigger();
// Check that the event data is valid.
$events = $DB->get_records('tool_monitor_events');
$this->assertEquals(1, count($events));
$monitorevent = array_pop($events);
$this->assertEquals($event->eventname, $monitorevent->eventname);
$this->assertEquals($event->contextid, $monitorevent->contextid);
$this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
$this->assertEquals($event->get_url()->out(), $monitorevent->link);
$this->assertEquals($event->courseid, $monitorevent->courseid);
$this->assertEquals($event->timecreated, $monitorevent->timecreated);
}
/**
* Test the notification sending features.
*/
public function test_process_event(): void {
global $DB, $USER;
$this->resetAfterTest();
$this->setAdminUser();
$msgsink = $this->redirectMessages();
// Generate data.
$course = $this->getDataGenerator()->create_course();
$toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rulerecord = new \stdClass();
$rulerecord->courseid = $course->id;
$rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
$rulerecord->frequency = 1;
$rule = $toolgenerator->create_rule($rulerecord);
$subrecord = new \stdClass();
$subrecord->courseid = $course->id;
$subrecord->ruleid = $rule->id;
$subrecord->userid = $USER->id;
$toolgenerator->create_subscription($subrecord);
$recordexists = $DB->record_exists('task_adhoc', array('component' => 'tool_monitor'));
$this->assertFalse($recordexists);
// Now let us trigger the event.
$event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
$event->trigger();
$this->verify_processed_data($msgsink);
// Clean up.
\tool_monitor\rule_manager::delete_rule($rule->id);
$DB->delete_records('tool_monitor_events');
// Let us create a rule with more than 1 frequency.
$rulerecord->frequency = 5;
$rule = $toolgenerator->create_rule($rulerecord);
$subrecord->ruleid = $rule->id;
$toolgenerator->create_subscription($subrecord);
// Let us trigger events.
for ($i = 0; $i < 5; $i++) {
$event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
$event->trigger();
if ($i != 4) {
$this->verify_message_not_sent_yet($msgsink);
}
}
$this->verify_processed_data($msgsink);
// Clean up.
\tool_monitor\rule_manager::delete_rule($rule->id);
$DB->delete_records('tool_monitor_events');
// Now let us create a rule specific to a module instance.
$cm = new \stdClass();
$cm->course = $course->id;
$book = $this->getDataGenerator()->create_module('book', $cm);
$rulerecord->eventname = '\mod_book\event\course_module_viewed';
$rulerecord->cmid = $book->cmid;
$rule = $toolgenerator->create_rule($rulerecord);
$subrecord->ruleid = $rule->id;
$toolgenerator->create_subscription($subrecord);
// Let us trigger events.
$params = array(
'context' => \context_module::instance($book->cmid),
'objectid' => $book->id
);
for ($i = 0; $i < 5; $i++) {
$event = \mod_book\event\course_module_viewed::create($params);
$event->trigger();
if ($i != 4) {
$this->verify_message_not_sent_yet($msgsink);
}
}
$this->verify_processed_data($msgsink);
// Clean up.
\tool_monitor\rule_manager::delete_rule($rule->id);
$DB->delete_records('tool_monitor_events');
// Now let us create a rule for event that happens in category context events.
$rulerecord->eventname = '\core\event\course_category_created';
$rulerecord->courseid = 0;
$rule = $toolgenerator->create_rule($rulerecord);
$subrecord->courseid = 0;
$subrecord->ruleid = $rule->id;
$toolgenerator->create_subscription($subrecord);
// Let us trigger events.
for ($i = 0; $i < 5; $i++) {
$this->getDataGenerator()->create_category();
if ($i != 4) {
$this->verify_message_not_sent_yet($msgsink);
}
}
$this->verify_processed_data($msgsink);
// Clean up.
\tool_monitor\rule_manager::delete_rule($rule->id);
$DB->delete_records('tool_monitor_events');
// Now let us create a rule at site level.
$rulerecord->eventname = '\core\event\blog_entry_created';
$rulerecord->courseid = 0;
$rule = $toolgenerator->create_rule($rulerecord);
$subrecord->courseid = 0;
$subrecord->ruleid = $rule->id;
$toolgenerator->create_subscription($subrecord);
// Let us trigger events.
$blog = new \blog_entry();
$blog->subject = "Subject of blog";
$blog->userid = $USER->id;
$states = \blog_entry::get_applicable_publish_states();
$blog->publishstate = reset($states);
for ($i = 0; $i < 5; $i++) {
$newblog = fullclone($blog);
$newblog->add();
if ($i != 4) {
$this->verify_message_not_sent_yet($msgsink);
}
}
$this->verify_processed_data($msgsink);
}
/**
* Test that same events are not used twice to calculate conditions for a single subscription.
*/
public function test_multiple_notification_not_sent(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$messagesink = $this->redirectMessages();
// Generate data.
$course = $this->getDataGenerator()->create_course();
$toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rulerecord = new \stdClass();
$rulerecord->courseid = $course->id;
$rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
$rulerecord->frequency = 5;
$rule = $toolgenerator->create_rule($rulerecord);
$subrecord = new \stdClass();
$subrecord->courseid = $course->id;
$subrecord->ruleid = $rule->id;
$subrecord->userid = $USER->id;
$toolgenerator->create_subscription($subrecord);
for ($i = 0; $i < 7; $i++) {
// Now let us trigger 7 instances of the event.
$event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
$event->trigger();
$this->waitForSecond(); // Add a second delay, to prevent time collisions.
}
$this->run_adhock_tasks();
$messages = $messagesink->get_messages();
$this->assertCount(1, $messages); // There should be only one message not 3.
for ($i = 0; $i < 3; $i++) {
// Now let us trigger 5 more instances of the event.
$event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
$event->trigger();
}
$this->run_adhock_tasks();
$messages = $messagesink->get_messages();
$this->assertCount(2, $messages); // There should be two messages now.
}
/**
* Run adhoc tasks.
*/
protected function run_adhock_tasks() {
while ($task = \core\task\manager::get_next_adhoc_task(time())) {
$task->execute();
\core\task\manager::adhoc_task_complete($task);
}
$this->expectOutputRegex("/^Sending message to the user with id \d+ for the subscription with id \d+\.\.\..Sent./ms");
}
/**
* Verify that task was scheduled and a message was sent as expected.
*
* @param phpunit_message_sink $msgsink Message sink
*/
protected function verify_processed_data(\phpunit_message_sink $msgsink) {
global $DB, $USER;
$recordexists = $DB->count_records('task_adhoc', array('component' => 'tool_monitor'));
$this->assertEquals(1, $recordexists); // We should have an adhock task now to send notifications.
$this->run_adhock_tasks();
$this->assertEquals(1, $msgsink->count());
$msgs = $msgsink->get_messages();
$msg = array_pop($msgs);
$this->assertEquals($USER->id, $msg->useridto);
$this->assertEquals(1, $msg->notification);
$msgsink->clear();
}
/**
* Verify that a message was not sent.
*
* @param phpunit_message_sink $msgsink Message sink
*/
protected function verify_message_not_sent_yet(\phpunit_message_sink $msgsink) {
$msgs = $msgsink->get_messages();
$this->assertCount(0, $msgs);
$msgsink->clear();
}
/**
* Tests for replace_placeholders method.
*/
public function test_replace_placeholders(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$msgsink = $this->redirectMessages();
// Generate data.
$course = $this->getDataGenerator()->create_course(['fullname' => 'Observed course', 'shortname' => 'obscourse']);
$toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$context = \context_user::instance($USER->id, IGNORE_MISSING);
// Creating book.
$cm = new \stdClass();
$cm->course = $course->id;
$cm->name = 'Observed book';
$book = $this->getDataGenerator()->create_module('book', $cm);
// Creating rule.
$rulerecord = new \stdClass();
$rulerecord->courseid = $course->id;
$rulerecord->eventname = '\mod_book\event\course_module_viewed';
$rulerecord->cmid = $book->cmid;
$rulerecord->frequency = 1;
$rulerecord->template = '## {link} ##
* {modulelink}
* __{rulename}__
* {description}
* {eventname}
* {modulename}
* {coursefullname}
* {courseshortname}';
$rulerecord->templateformat = FORMAT_MARKDOWN;
$rule = $toolgenerator->create_rule($rulerecord);
// Creating subscription.
$subrecord = new \stdClass();
$subrecord->courseid = $course->id;
$subrecord->ruleid = $rule->id;
$subrecord->userid = $USER->id;
$toolgenerator->create_subscription($subrecord);
// Now let us trigger the event.
$params = array(
'context' => \context_module::instance($book->cmid),
'objectid' => $book->id
);
$event = \mod_book\event\course_module_viewed::create($params);
$event->trigger();
$this->run_adhock_tasks();
$msgs = $msgsink->get_messages();
$msg = array_pop($msgs);
$modurl = new \moodle_url('/mod/book/view.php', array('id' => $book->cmid));
$this->assertMatchesRegularExpression('~<h2>.*' . preg_quote($event->get_url()->out(), '~') . '.*</h2>~',
$msg->fullmessagehtml);
$this->assertMatchesRegularExpression('~<li>.*' . preg_quote($modurl->out(), '~') . '.*</li>~', $msg->fullmessagehtml);
$this->assertStringContainsString('<li><strong>'.$rule->get_name($context).'</strong></li>', $msg->fullmessagehtml);
$this->assertStringContainsString('<li>'.$rule->get_description($context).'</li>', $msg->fullmessagehtml);
$this->assertStringContainsString('<li>'.$rule->get_event_name().'</li>', $msg->fullmessagehtml);
$this->assertStringContainsString('<li>' . $cm->name . '</li>', $msg->fullmessagehtml);
$this->assertStringContainsString('<li>' . $course->fullname . '</li>', $msg->fullmessagehtml);
$this->assertStringContainsString('<li>' . $course->shortname . '</li>', $msg->fullmessagehtml);
$this->assertEquals(FORMAT_PLAIN, $msg->fullmessageformat);
$this->assertStringNotContainsString('<h2>', $msg->fullmessage);
$this->assertStringNotContainsString('##', $msg->fullmessage);
$this->assertStringContainsString(strtoupper($event->get_url()->out()), $msg->fullmessage);
$this->assertStringContainsString('* '.$modurl->out(), $msg->fullmessage);
$this->assertStringContainsString('* '.strtoupper($rule->get_name($context)), $msg->fullmessage);
$this->assertStringContainsString('* '.$rule->get_description($context), $msg->fullmessage);
$this->assertStringContainsString('* '.$rule->get_event_name(), $msg->fullmessage);
$this->assertStringContainsString('* ' . $cm->name, $msg->fullmessage);
$this->assertStringContainsString('* ' . $course->fullname, $msg->fullmessage);
$this->assertStringContainsString('* ' . $course->shortname, $msg->fullmessage);
}
/**
* Test observer for user delete event.
*/
public function test_user_deleted(): void {
global $DB;
$this->setAdminUser();
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = $course1->id;
$rule->plugin = 'test';
$sub = new \stdClass();
$sub->courseid = $course1->id;
$sub->userid = $user->id;
// Add 10 rules for this course with subscriptions.
for ($i = 0; $i < 10; $i++) {
$createdrule = $monitorgenerator->create_rule($rule);
$sub->ruleid = $createdrule->id;
$monitorgenerator->create_subscription($sub);
}
// Add 10 random rules for course 2.
$rule->courseid = $course2->id;
for ($i = 0; $i < 10; $i++) {
$createdrule = $monitorgenerator->create_rule($rule);
$sub->courseid = $rule->courseid;
$sub->ruleid = $createdrule->id;
$monitorgenerator->create_subscription($sub);
}
// Verify data before user delete.
$totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
$this->assertCount(20, $totalrules);
$totalsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertCount(20, $totalsubs);
// Let us delete the user now.
delete_user($user);
// Verify data after course delete.
$totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
$this->assertCount(20, $totalrules);
$totalsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertCount(0, $totalsubs); // Make sure all subscriptions are deleted.
}
/**
* Test observer for course module delete event.
*/
public function test_course_module_deleted(): void {
global $DB;
$this->setAdminUser();
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Now let us create a rule specific to a module instance.
$cm = new \stdClass();
$cm->course = $course1->id;
$book = $this->getDataGenerator()->create_module('book', $cm);
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = $course1->id;
$rule->plugin = 'test';
$sub = new \stdClass();
$sub->courseid = $course1->id;
$sub->userid = $user->id;
$sub->cmid = $book->cmid;
// Add 10 rules for this course with subscriptions for this module.
for ($i = 0; $i < 10; $i++) {
$createdrule = $monitorgenerator->create_rule($rule);
$sub->ruleid = $createdrule->id;
$monitorgenerator->create_subscription($sub);
}
// Add 10 random rules for course 2.
$rule->courseid = $course2->id;
for ($i = 0; $i < 10; $i++) {
$createdrule = $monitorgenerator->create_rule($rule);
$sub->courseid = $rule->courseid;
$sub->ruleid = $createdrule->id;
$sub->cmid = 0;
$monitorgenerator->create_subscription($sub);
}
// Verify data before module delete.
$totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
$this->assertCount(20, $totalrules);
$totalsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertCount(20, $totalsubs);
// Let us delete the user now.
course_delete_module($book->cmid);
// Verify data after course delete.
$totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
$this->assertCount(20, $totalrules);
$totalsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertCount(10, $totalsubs); // Make sure only relevant subscriptions are deleted.
}
}
+200
View File
@@ -0,0 +1,200 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Event monitor data generator
*
* @package tool_monitor
* @category test
* @copyright 2014 onwards Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Event monitor data generator class
*
* @since Moodle 2.8
* @package tool_monitor
* @category test
* @copyright 2014 onwards Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_monitor_generator extends testing_module_generator {
/**
* @var int keep track of how many rules have been created.
*/
protected $rulecount;
/**
* Function to generate rule data.
*
* @param \stdClass|array $record data to insert as rule entry.
*
* @return \tool_monitor\rule An instance of rule class.
*/
public function create_rule($record = null) {
global $USER;
$this->rulecount++;
$i = $this->rulecount;
$now = time();
$record = (object)(array)$record;
if (!isset($record->userid)) {
$record->userid = $USER->id;
}
if (!isset($record->courseid)) {
$record->courseid = 0;
}
if (!isset($record->name)) {
$record->name = 'Test rule ' . $i;
}
if (!isset($record->description)) {
$record->description = 'Rule description ' . $i;
}
if (!isset($record->descriptionformat)) {
$record->descriptionformat = FORMAT_HTML;
}
if (!isset($record->frequency)) {
$record->frequency = 5;
}
if (!isset($record->minutes)) {
$record->minutes = 5;
}
if (!isset($record->template)) {
$record->template = 'Rule message template ' . $i;
}
if (!isset($record->templateformat)) {
$record->templateformat = FORMAT_HTML;
}
if (!isset($record->timewindow)) {
$record->timewindow = $record->minutes * 60;
}
if (!isset($record->timecreated)) {
$record->timecreated = $now;
}
if (!isset($record->timemodified)) {
$record->timemodified = $now;
}
if (!isset($record->plugin)) {
$record->plugin = 'core';
}
if (!isset($record->eventname)) {
$record->eventname = '\core\event\blog_entry_created';
}
unset($record->minutes); // Remove the minutes shortcut to the timewindow.
return \tool_monitor\rule_manager::add_rule($record);
}
/**
* Function to generate subscription data.
*
* @throws coding_exception if $record->ruleid or $record->userid not present.
* @param \stdClass|array $record data to insert as subscription entry.
*
* @return \tool_monitor\subscription An instance of the subscription class.
*/
public function create_subscription($record = null) {
if (!isset($record->timecreated)) {
$record->timecreated = time();
}
if (!isset($record->courseid)) {
$record->courseid = 0;
}
if (!isset($record->ruleid)) {
throw new coding_exception('$record->ruleid must be present in tool_monitor_generator::create_subscription()');
}
if (!isset($record->cmid)) {
$record->cmid = 0;
}
if (!isset($record->userid)) {
throw new coding_exception('$record->userid must be present in tool_monitor_generator::create_subscription()');
}
$sid = \tool_monitor\subscription_manager::create_subscription($record->ruleid, $record->courseid,
$record->cmid, $record->userid);
return \tool_monitor\subscription_manager::get_subscription($sid);
}
/**
* Function to generate event entries.
*
* @param \stdClass|array $record data to insert as event entry.
*
* @return \stdClass $record An object representing the newly created event entry.
*/
public function create_event_entries($record = null) {
global $DB, $CFG;
$record = (object)(array)$record;
$context = \context_system::instance();
if (!isset($record->eventname)) {
$record->eventname = '\core\event\user_loggedin';
}
if (!isset($record->contextid)) {
$record->contextid = $context->id;
}
if (!isset($record->contextlevel)) {
$record->contextlevel = $context->contextlevel;
}
if (!isset($record->contextinstanceid)) {
$record->contextinstanceid = $context->instanceid;
}
if (!isset($record->link)) {
$record->link = $CFG->wwwroot . '/user/profile.php';
}
if (!isset($record->courseid)) {
$record->courseid = 0;
}
if (!isset($record->timecreated)) {
$record->timecreated = time();
}
$record->id = $DB->insert_record('tool_monitor_events', $record, true);
return $record;
}
/**
* Function to generate history data.
*
* @throws coding_exception if $record->sid or $record->userid not present.
* @param \stdClass|array $record data to insert as history entry.
*
* @return \stdClass $record An object representing the newly created history entry.
*/
public function create_history($record = null) {
global $DB;
$record = (object)(array)$record;
if (!isset($record->sid)) {
throw new coding_exception('subscription ID must be present in tool_monitor_generator::create_history() $record');
}
if (!isset($record->userid)) {
throw new coding_exception('user ID must be present in tool_monitor_generator::create_history() $record');
}
if (!isset($record->timesent)) {
$record->timesent = time();
}
$record->id = $DB->insert_record('tool_monitor_history', $record, true);
return $record;
}
}
+132
View File
@@ -0,0 +1,132 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
/**
* PHPUnit data generator test case.
*
* @since Moodle 2.8
* @package tool_monitor
* @category test
* @copyright 2014 onwards Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class generator_test extends \advanced_testcase {
/**
* Set up method.
*/
public function setUp(): void {
// Enable monitor.
set_config('enablemonitor', 1, 'tool_monitor');
}
/**
* Test create_rule data generator.
*/
public function test_create_rule(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
$rulegenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$record = new \stdClass();
$record->courseid = $course->id;
$record->userid = $user->id;
$rule = $rulegenerator->create_rule($record);
$this->assertInstanceOf('tool_monitor\rule', $rule);
$this->assertEquals($rule->userid, $record->userid);
$this->assertEquals($rule->courseid, $record->courseid);
}
/**
* Test create_subscription data generator.
*/
public function test_create_subscription(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = $monitorgenerator->create_rule();
$record = new \stdClass();
$record->courseid = $course->id;
$record->userid = $user->id;
$record->ruleid = $rule->id;
$subscription = $monitorgenerator->create_subscription($record);
$this->assertEquals($record->courseid, $subscription->courseid);
$this->assertEquals($record->ruleid, $subscription->ruleid);
$this->assertEquals($record->userid, $subscription->userid);
$this->assertEquals(0, $subscription->cmid);
// Make sure rule id is always required.
$this->expectException('coding_exception');
unset($record->ruleid);
$monitorgenerator->create_subscription($record);
}
/**
* Test create_event data generator.
*/
public function test_create_event_entries(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$context = \context_system::instance();
// Default data generator values.
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// First create and assertdata using default values.
$eventdata = $monitorgenerator->create_event_entries();
$this->assertEquals('\core\event\user_loggedin', $eventdata->eventname);
$this->assertEquals($context->id, $eventdata->contextid);
$this->assertEquals($context->contextlevel, $eventdata->contextlevel);
}
/**
* Test create_history data generator.
*/
public function test_create_history(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = $monitorgenerator->create_rule();
$record = new \stdClass();
$record->userid = $user->id;
$record->ruleid = $rule->id;
$sid = $monitorgenerator->create_subscription($record)->id;
$record->sid = $sid;
$historydata = $monitorgenerator->create_history($record);
$this->assertEquals($record->userid, $historydata->userid);
$this->assertEquals($record->sid, $historydata->sid);
// Test using default values.
$record->userid = 1;
$record->sid = 1;
$historydata = $monitorgenerator->create_history($record);
$this->assertEquals(1, $historydata->userid);
$this->assertEquals(1, $historydata->sid);
}
}
@@ -0,0 +1,417 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy test for the event monitor
*
* @package tool_monitor
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_monitor\privacy;
defined('MOODLE_INTERNAL') || die();
use tool_monitor\privacy\provider;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\tests\provider_testcase;
/**
* Privacy test for the event monitor
*
* @package tool_monitor
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
/**
* Set up method.
*/
public function setUp(): void {
$this->resetAfterTest();
// Enable monitor.
set_config('enablemonitor', 1, 'tool_monitor');
}
/**
* Assign a capability to $USER
* The function creates a student $USER if $USER->id is empty
*
* @param string $capability capability name
* @param int $contextid
* @param int $roleid
* @return int the role id - mainly returned for creation, so calling function can reuse it
*/
public static function assign_user_capability($capability, $contextid, $roleid = null) {
global $USER;
// Create a new student $USER if $USER doesn't exist.
if (empty($USER->id)) {
$user = self::getDataGenerator()->create_user();
self::setUser($user);
}
if (empty($roleid)) {
$roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
}
assign_capability($capability, CAP_ALLOW, $roleid, $contextid);
role_assign($roleid, $USER->id, $contextid);
accesslib_clear_all_caches_for_unit_testing();
return $roleid;
}
/**
* Test that a collection with data is returned when calling this function.
*/
public function test_get_metadata(): void {
$collection = new \core_privacy\local\metadata\collection('tool_monitor');
$collection = provider::get_metadata($collection);
$this->assertNotEmpty($collection);
}
/**
* Check that a user context is returned if there is any user data for this user.
*/
public function test_get_contexts_for_userid(): void {
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$this->assertEmpty(provider::get_contexts_for_userid($user->id));
$this->assertEmpty(provider::get_contexts_for_userid($user2->id));
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule with this user.
$this->setUser($user);
$rule = $monitorgenerator->create_rule();
$contextlist = provider::get_contexts_for_userid($user->id);
// Check that we only get back one context.
$this->assertCount(1, $contextlist);
// Check that a context is returned for just creating a rule.
$this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]);
$this->setUser($user2);
$record = new \stdClass();
$record->courseid = 0;
$record->userid = $user2->id;
$record->ruleid = $rule->id;
$subscription = $monitorgenerator->create_subscription($record);
$contextlist = provider::get_contexts_for_userid($user2->id);
// Check that we only get back one context.
$this->assertCount(1, $contextlist);
// Check that a context is returned for just subscribing to a rule.
$this->assertEquals($usercontext2->id, $contextlist->get_contextids()[0]);
}
/**
* Check that the correct userlist is returned if there is any user data for this context.
*/
public function test_get_users_in_context(): void {
$component = 'tool_monitor';
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
$userlist = new \core_privacy\local\request\userlist($usercontext2, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule with user.
$this->setUser($user);
$rule = $monitorgenerator->create_rule();
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
// Check that we only get back user.
$userids = $userlist->get_userids();
$this->assertCount(1, $userlist);
$this->assertEquals($user->id, $userids[0]);
// Create a subscription with user2.
$this->setUser($user2);
$record = new \stdClass();
$record->courseid = 0;
$record->userid = $user2->id;
$record->ruleid = $rule->id;
$subscription = $monitorgenerator->create_subscription($record);
$userlist = new \core_privacy\local\request\userlist($usercontext2, $component);
provider::get_users_in_context($userlist);
// Check that user2 is returned for just subscribing to a rule.
$userids = $userlist->get_userids();
$this->assertCount(1, $userlist);
$this->assertEquals($user2->id, $userids[0]);
}
/**
* Test that user data is exported correctly.
*/
public function test_export_user_data(): void {
$user = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
$writer = \core_privacy\local\request\writer::with_context($usercontext);
$this->assertFalse($writer->has_any_data());
$approvedlist = new approved_contextlist($user, 'tool_monitor', [$usercontext->id]);
provider::export_user_data($approvedlist);
// Check that the rules created by this user are exported.
$this->assertEquals($rulerecord->name, $writer->get_data([get_string('privacy:createdrules', 'tool_monitor'),
$rulerecord->name . '_' . $rule->id])->name);
$this->assertEquals($secondrulerecord->name, $writer->get_data([get_string('privacy:createdrules', 'tool_monitor'),
$secondrulerecord->name . '_' . $rule2->id])->name);
// Check that the subscriptions for this user are also exported.
$this->assertEquals($rulerecord->name, $writer->get_data([get_string('privacy:subscriptions', 'tool_monitor'),
$rulerecord->name . '_' . $subscription->id, 'Site' , 'All events'])->name);
}
/**
* Test deleting all user data for a specific context.
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
// Need to give user one the ability to manage rules.
$this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
// Have user 2 subscribe to the second rule created by user 1.
$subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
$subscription2 = $monitorgenerator->create_subscription($subscription2);
$this->setUser($user2);
$thirdrulerecord = (object)['name' => 'privacy rule for second user'];
$rule3 = $monitorgenerator->create_rule($thirdrulerecord);
$subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
$subscription3 = $monitorgenerator->create_subscription($subscription3);
// Try a different context first.
provider::delete_data_for_all_users_in_context(\context_system::instance());
// Get all of the monitor rules.
$dbrules = $DB->get_records('tool_monitor_rules');
// All of the rules should still be present.
$this->assertCount(3, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule->id]->userid);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// Delete everything for the first user context.
provider::delete_data_for_all_users_in_context($usercontext);
// Get all of the monitor rules.
$dbrules = $DB->get_records('tool_monitor_rules');
// Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
$this->assertCount(2, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// Get all of the monitor subscriptions.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
// There should be two subscriptions left, both for user 2.
$this->assertCount(2, $dbsubs);
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
}
/**
* This should work identical to the above test.
*/
public function test_delete_data_for_user(): void {
global $DB;
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
// Need to give user one the ability to manage rules.
$this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
// Have user 2 subscribe to the second rule created by user 1.
$subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
$subscription2 = $monitorgenerator->create_subscription($subscription2);
$this->setUser($user2);
$thirdrulerecord = (object)['name' => 'privacy rule for second user'];
$rule3 = $monitorgenerator->create_rule($thirdrulerecord);
$subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
$subscription3 = $monitorgenerator->create_subscription($subscription3);
$approvedlist = new approved_contextlist($user, 'tool_monitor', [$usercontext->id]);
// Delete everything for the first user.
provider::delete_data_for_user($approvedlist);
// Get all of the monitor rules.
$dbrules = $DB->get_records('tool_monitor_rules');
// Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
$this->assertCount(2, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// Get all of the monitor subscriptions.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
// There should be two subscriptions left, both for user 2.
$this->assertCount(2, $dbsubs);
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
}
/**
* Test deleting user data for an approved userlist in a context.
*/
public function test_delete_data_for_users(): void {
global $DB;
$component = 'tool_monitor';
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
// Need to give user one the ability to manage rules.
$this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
// Have user 2 subscribe to the second rule created by user 1.
$subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
$subscription2 = $monitorgenerator->create_subscription($subscription2);
$this->setUser($user2);
$thirdrulerecord = (object)['name' => 'privacy rule for second user'];
$rule3 = $monitorgenerator->create_rule($thirdrulerecord);
$subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
$subscription3 = $monitorgenerator->create_subscription($subscription3);
// Get all of the monitor rules, ensure all exist.
$dbrules = $DB->get_records('tool_monitor_rules');
$this->assertCount(3, $dbrules);
// Delete for user2 in first user's context, should have no effect.
$approveduserids = [$user2->id];
$approvedlist = new approved_userlist($usercontext, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
$dbrules = $DB->get_records('tool_monitor_rules');
$this->assertCount(3, $dbrules);
// Delete for user in usercontext.
$approveduserids = [$user->id];
$approvedlist = new approved_userlist($usercontext, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
// Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
$dbrules = $DB->get_records('tool_monitor_rules');
$this->assertCount(2, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// There should be two subscriptions left, both for user 2.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertCount(2, $dbsubs);
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
// Delete for user2 in context 2.
$approveduserids = [$user2->id];
$approvedlist = new approved_userlist($usercontext2, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
// There should be no subscriptions left.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertEmpty($dbsubs);
}
}
@@ -0,0 +1,187 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
/**
* Unit tests for rule manager api.
*
* @package tool_monitor
* @category test
* @copyright 2014 onwards Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class rule_manager_test extends \advanced_testcase {
/**
* Set up method.
*/
public function setUp(): void {
// Enable monitor.
set_config('enablemonitor', 1, 'tool_monitor');
}
/**
* Test add_rule method.
*/
public function test_add_rule(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$now = time();
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = $course->id;
$rule->name = 'test rule 1';
$rule->plugin = 'core';
$rule->eventname = '\core\event\course_updated';
$rule->description = 'test description 1';
$rule->descriptionformat = FORMAT_HTML;
$rule->frequency = 15;
$rule->template = 'test template message';
$rule->templateformat = FORMAT_HTML;
$rule->timewindow = 300;
$rule->timecreated = $now;
$rule->timemodified = $now;
$ruledata = \tool_monitor\rule_manager::add_rule($rule);
foreach ($rule as $prop => $value) {
$this->assertEquals($ruledata->$prop, $value);
}
}
/**
* Test get_rule method.
*/
public function test_get_rule(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = $monitorgenerator->create_rule();
$rules1 = \tool_monitor\rule_manager::get_rule($rule->id);
$this->assertInstanceOf('tool_monitor\rule', $rules1);
$this->assertEquals($rules1, $rule);
}
/**
* Test update_rule method.
*/
public function test_update_rule(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = $monitorgenerator->create_rule();
$ruledata = new \stdClass;
$ruledata->id = $rule->id;
$ruledata->frequency = 25;
\tool_monitor\rule_manager::update_rule($ruledata);
$this->assertEquals(25, $ruledata->frequency);
}
/**
* Test get_rules_by_courseid method.
*/
public function test_get_rules_by_courseid(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$record = new \stdClass();
$record->courseid = $course1->id;
$record2 = new \stdClass();
$record2->courseid = $course2->id;
$ruleids = array();
for ($i = 0; $i < 10; $i++) {
$rule = $monitorgenerator->create_rule($record);
$ruleids[] = $rule->id;
$rule = $monitorgenerator->create_rule(); // Create some site level rules.
$ruleids[] = $rule->id;
$rule = $monitorgenerator->create_rule($record2); // Create rules in a different course.
}
$ruledata = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id);
$this->assertEmpty(array_merge(array_diff(array_keys($ruledata), $ruleids), array_diff($ruleids, array_keys($ruledata))));
$this->assertCount(20, $ruledata);
}
/**
* Test get_rules_by_plugin method.
*/
public function test_get_rules_by_plugin(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$record = new \stdClass();
$record->plugin = 'core';
$record2 = new \stdClass();
$record2->plugin = 'mod_assign';
$ruleids = array();
for ($i = 0; $i < 10; $i++) {
$rule = $monitorgenerator->create_rule($record);
$ruleids[] = $rule->id;
$rule = $monitorgenerator->create_rule($record2); // Create rules in a different plugin.
}
$ruledata = \tool_monitor\rule_manager::get_rules_by_plugin('core');
$this->assertEmpty(array_merge(array_diff(array_keys($ruledata), $ruleids), array_diff($ruleids, array_keys($ruledata))));
$this->assertCount(10, $ruledata);
}
/**
* Test get_rules_by_event method.
*/
public function test_get_rules_by_event(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule = $monitorgenerator->create_rule();
$record = new \stdClass();
$record->eventname = '\core\event\calendar_event_created';
$record2 = new \stdClass();
$record2->eventname = '\core\event\calendar_event_updated';
$ruleids = array();
for ($i = 0; $i < 10; $i++) {
$rule = $monitorgenerator->create_rule($record);
$ruleids[] = $rule->id;
$rule = $monitorgenerator->create_rule($record2); // Create rules in a different plugin.
}
$ruledata = \tool_monitor\rule_manager::get_rules_by_event('\core\event\calendar_event_created');
$this->assertEmpty(array_diff(array_keys($ruledata), $ruleids));
$this->assertCount(10, $ruledata);
}
}
@@ -0,0 +1,70 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
/**
* Unit tests for subscription manager api.
*
* @package tool_monitor
* @category test
* @copyright 2014 onwards Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class subscription_manager_test extends \advanced_testcase {
/**
* Test count_rule_subscriptions method.
*/
public function test_count_rule_subscriptions(): void {
$this->setAdminUser();
$this->resetAfterTest(true);
// Create users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Create few rules.
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$rule1 = $monitorgenerator->create_rule();
$rule2 = $monitorgenerator->create_rule();
$subs = \tool_monitor\subscription_manager::count_rule_subscriptions($rule1->id);
// No subscriptions at this point.
$this->assertEquals(0, $subs);
// Subscribe user 1 to rule 1.
$record = new \stdClass;
$record->ruleid = $rule1->id;
$record->userid = $user1->id;
$monitorgenerator->create_subscription($record);
// Subscribe user 2 to rule 1.
$record->userid = $user2->id;
$monitorgenerator->create_subscription($record);
// Subscribe user 2 to rule 2.
$record->ruleid = $rule2->id;
$monitorgenerator->create_subscription($record);
// Should have 2 subscriptions for rule 1 and 1 subscription for rule 2
$subs1 = \tool_monitor\subscription_manager::count_rule_subscriptions($rule1->id);
$subs2 = \tool_monitor\subscription_manager::count_rule_subscriptions($rule2->id);
$this->assertEquals(2, $subs1);
$this->assertEquals(1, $subs2);
}
}
@@ -0,0 +1,69 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
/**
* Unit tests for the subscription class.
* @since 3.2.0
*
* @package tool_monitor
* @category test
* @copyright 2016 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class subscription_test extends \advanced_testcase {
/**
* @var \tool_monitor\subscription $subscription object.
*/
private $subscription;
/**
* Test set up.
*/
public function setUp(): void {
$this->resetAfterTest(true);
// Create the mock subscription.
$sub = new \stdClass();
$sub->id = 100;
$sub->name = 'My test rule';
$sub->courseid = 20;
$mockbuilder = $this->getMockBuilder('\tool_monitor\subscription');
$mockbuilder->onlyMethods([]);
$mockbuilder->setConstructorArgs(array($sub));
$this->subscription = $mockbuilder->getMock();
}
/**
* Test for the magic __isset method.
*/
public function test_magic_isset(): void {
$this->assertEquals(true, isset($this->subscription->name));
$this->assertEquals(true, isset($this->subscription->courseid));
$this->assertEquals(false, isset($this->subscription->ruleid));
}
/**
* Test for the magic __get method.
*/
public function test_magic_get(): void {
$this->assertEquals(20, $this->subscription->courseid);
$this->expectException(\coding_exception::class);
$this->subscription->ruleid;
}
}
@@ -0,0 +1,365 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
/**
* Unit tests for the tool_monitor clean events task.
* @since 3.2.0
*
* @package tool_monitor
* @category test
* @copyright 2016 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_check_subscriptions_test extends \advanced_testcase {
private $course;
private $user;
private $rule;
private $subscription;
private $teacherrole;
private $studentrole;
/**
* Test set up.
*/
public function setUp(): void {
global $DB;
set_config('enablemonitor', 1, 'tool_monitor');
$this->resetAfterTest(true);
// All tests defined herein need a user, course, rule and subscription, so set these up.
$this->user = $this->getDataGenerator()->create_user();
$this->course = $this->getDataGenerator()->create_course();
$rule = new \stdClass();
$rule->userid = 2; // Rule created by admin.
$rule->courseid = $this->course->id;
$rule->plugin = 'mod_book';
$rule->eventname = '\mod_book\event\course_module_viewed';
$rule->timewindow = 500;
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->rule = $monitorgenerator->create_rule($rule);
$sub = new \stdClass();
$sub->courseid = $this->course->id;
$sub->userid = $this->user->id;
$sub->ruleid = $this->rule->id;
$this->subscription = $monitorgenerator->create_subscription($sub);
// Also set up a student and a teacher role for use in some tests.
$this->teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
$this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
}
/**
* Reloads the subscription object from the DB.
*
* @return void.
*/
private function reload_subscription() {
global $DB;
$sub = $DB->get_record('tool_monitor_subscriptions', array('id' => $this->subscription->id));
$this->subscription = new \tool_monitor\subscription($sub);
}
/**
* Test to confirm the task is named correctly.
*/
public function test_task_name(): void {
$task = new \tool_monitor\task\check_subscriptions();
$this->assertEquals(get_string('taskchecksubscriptions', 'tool_monitor'), $task->get_name());
}
/**
* Test to confirm that site level subscriptions are activated and deactivated according to system capabilities.
*/
public function test_site_level_subscription(): void {
// Create a site level subscription.
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$sub = new \stdClass();
$sub->userid = $this->user->id;
$sub->ruleid = $this->rule->id;
$this->subscription = $monitorgenerator->create_subscription($sub);
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should be inactive as the user doesn't have the capability. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Now, assign the user as a teacher role at system context.
$this->getDataGenerator()->role_assign($this->teacherrole->id, $this->user->id, \context_system::instance());
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should be active now. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that if the module is disabled, no changes are made to active subscriptions.
*/
public function test_module_disabled(): void {
set_config('enablemonitor', 0, 'tool_monitor');
// Subscription should be active to start with.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Run the task. Note, we never enrolled the user.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should still be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm an active, valid subscription stays active once the scheduled task is run.
*/
public function test_active_unaffected(): void {
// Enrol the user as a teacher. This role should have the required capability.
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->teacherrole->id);
// Subscription should be active to start with.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should still be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that a subscription for a user without an enrolment to the course is made inactive.
*/
public function test_course_enrolment(): void {
// Subscription should be active until deactivated by the scheduled task. Remember, by default the test setup
// doesn't enrol the user, so the first run of the task should deactivate it.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should NOT be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Enrol the user.
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->teacherrole->id);
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// Subscription should now be active again.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that subscriptions for enrolled users without the required capability are made inactive.
*/
public function test_enrolled_user_with_no_capability(): void {
// Enrol the user. By default, students won't have the required capability.
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->studentrole->id);
// The subscription should be active to start with. Pass in the id only to refetch the data.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should NOT be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that subscriptions for users who fail can_access_course(), are deactivated.
*/
public function test_can_access_course(): void {
// Enrol the user as a teacher. This role should have the required capability.
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->teacherrole->id);
// Strip the ability to see hidden courses, so we'll fail the check_subscriptions->user_can_access_course call.
$context = \context_course::instance($this->course->id);
assign_capability('moodle/course:viewhiddencourses', CAP_PROHIBIT, $this->teacherrole->id, $context);
// Subscription should be active to start with.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Hide the course.
course_change_visibility($this->course->id, false);
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should be inactive. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that subscriptions for enrolled users who don't have CM access, are deactivated.
*/
public function test_cm_access(): void {
// Enrol the user as a student but grant to ability to subscribe. Students cannot view hidden activities.
$context = \context_course::instance($this->course->id);
assign_capability('tool/monitor:subscribe', CAP_ALLOW, $this->studentrole->id, $context);
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->studentrole->id);
// Generate a course module.
$book = $this->getDataGenerator()->create_module('book', array('course' => $this->course->id));
// And add a subscription to it.
$sub = new \stdClass();
$sub->courseid = $this->course->id;
$sub->userid = $this->user->id;
$sub->ruleid = $this->rule->id;
$sub->cmid = $book->cmid;
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->subscription = $monitorgenerator->create_subscription($sub);
// The subscription should be active to start with. Pass in the id only to refetch the data.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should still be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Make the course module invisible, which should in turn make the subscription inactive.
set_coursemodule_visible($book->cmid, false);
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should NOT be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Make the course module visible again.
set_coursemodule_visible($book->cmid, true);
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should be active. Pass in the id only to refetch the data.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that long term inactive subscriptions are removed entirely.
*/
public function test_stale_subscription_removal(): void {
global $DB;
// Manually set the inactivedate to 1 day older than the limit allowed.
$daysold = 1 + \tool_monitor\subscription_manager::INACTIVE_SUBSCRIPTION_LIFESPAN_IN_DAYS;
$inactivedate = strtotime("-$daysold days", time());
$DB->set_field('tool_monitor_subscriptions', 'inactivedate', $inactivedate, array('id' => $this->subscription->id));
// Subscription should be inactive to start with.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// Subscription should now not exist at all.
$this->assertEquals(false, $DB->record_exists('tool_monitor_subscriptions', array('id' => $this->subscription->id)));
}
/**
* Test to confirm that subscriptions for a partially set up user are deactivated.
*/
public function test_user_not_fully_set_up(): void {
global $DB;
// Enrol the user as a teacher.
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->teacherrole->id);
// The subscription should be active to start.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Unset the user's email address, so we fail the check_subscriptions->is_user_setup() call.
$DB->set_field('user', 'email', '', array('id' => $this->user->id));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should now be inactive.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
/**
* Test to confirm that a suspended user's subscriptions are deactivated properly.
*/
public function test_suspended_user(): void {
global $DB;
// Enrol the user as a teacher. This role should have the required capability.
$this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, $this->teacherrole->id);
// Subscription should be active to start with.
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Suspend the user.
$DB->set_field('user', 'suspended', '1', array('id' => $this->user->id));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should now be inactive.
$this->reload_subscription();
$this->assertEquals(false, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
// Unsuspend the user.
$DB->set_field('user', 'suspended', '0', array('id' => $this->user->id));
// Run the task.
$task = new \tool_monitor\task\check_subscriptions();
$task->execute();
// The subscription should now be active again.
$this->reload_subscription();
$this->assertEquals(true, \tool_monitor\subscription_manager::subscription_is_active($this->subscription));
}
}
@@ -0,0 +1,239 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_monitor;
/**
* Unit tests for the tool_monitor clean events task.
*
* @package tool_monitor
* @category test
* @copyright 2014 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_clean_events_test extends \advanced_testcase {
/**
* Test set up.
*/
public function setUp(): void {
set_config('enablemonitor', 1, 'tool_monitor');
$this->resetAfterTest(true);
}
/**
* Tests the cleaning up of events.
*/
public function test_clean_events(): void {
global $DB;
// Create the necessary items for testing.
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$bookgenerator = $this->getDataGenerator()->get_plugin_generator('mod_book');
$book = $this->getDataGenerator()->create_module('book', array('course' => $course->id));
$bookcontext = \context_module::instance($book->cmid);
$bookchapter = $bookgenerator->create_chapter(array('bookid' => $book->id));
$course2 = $this->getDataGenerator()->create_course();
$book2 = $this->getDataGenerator()->create_module('book', array('course' => $course2->id));
$book2context = \context_module::instance($book2->cmid);
$book2chapter = $bookgenerator->create_chapter(array('bookid' => $book2->id));
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Let's set some data for the rules we need before we can generate them.
$rule = new \stdClass();
$rule->userid = $user->id;
$rule->courseid = $course->id;
$rule->plugin = 'mod_book';
$rule->eventname = '\mod_book\event\course_module_viewed';
$rule->timewindow = 500;
// Let's add a few rules we want to monitor.
$rule1 = $monitorgenerator->create_rule($rule);
$rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
$rule2 = $monitorgenerator->create_rule($rule);
// Add the same rules for the same course, but this time with a lower timewindow (used to test that we do not
// remove an event for a course if there is still a rule where the maximum timewindow has not been reached).
$rule->eventname = '\mod_book\event\course_module_viewed';
$rule->timewindow = 200;
$rule3 = $monitorgenerator->create_rule($rule);
$rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
$rule4 = $monitorgenerator->create_rule($rule);
// Add another rule in a different course.
$rule->courseid = $course2->id;
$rule->eventname = '\mod_book\event\chapter_viewed';
$rule->timewindow = 200;
$rule5 = $monitorgenerator->create_rule($rule);
// Add a site wide rule.
$rule->courseid = 0;
$rule->eventname = '\mod_book\event\chapter_viewed';
$rule->timewindow = 500;
$rule6 = $monitorgenerator->create_rule($rule);
// Let's subscribe to these rules.
$sub = new \stdClass;
$sub->courseid = $course->id;
$sub->ruleid = $rule1->id;
$sub->userid = $user->id;
$monitorgenerator->create_subscription($sub);
$sub->ruleid = $rule2->id;
$monitorgenerator->create_subscription($sub);
$sub->ruleid = $rule3->id;
$monitorgenerator->create_subscription($sub);
$sub->ruleid = $rule4->id;
$monitorgenerator->create_subscription($sub);
$sub->ruleid = $rule5->id;
$sub->courseid = $course2->id;
$monitorgenerator->create_subscription($sub);
$sub->ruleid = $rule6->id;
$sub->courseid = 0;
$monitorgenerator->create_subscription($sub);
// Now let's populate the tool_monitor table with the events associated with those rules.
\mod_book\event\course_module_viewed::create_from_book($book, $bookcontext)->trigger();
\mod_book\event\course_module_instance_list_viewed::create_from_course($course)->trigger();
\mod_book\event\chapter_viewed::create_from_chapter($book, $bookcontext, $bookchapter)->trigger();
// Let's trigger the viewed events again, but in another course. The rules created for these events are
// associated with another course, so these events should get deleted when we trigger the cleanup task.
\mod_book\event\course_module_viewed::create_from_book($book2, $book2context)->trigger();
\mod_book\event\course_module_instance_list_viewed::create_from_course($course2)->trigger();
// Trigger a chapter_viewed event in this course - this should not get deleted as the rule is site wide.
\mod_book\event\chapter_viewed::create_from_chapter($book2, $book2context, $book2chapter)->trigger();
// Trigger a bunch of other events.
$eventparams = array(
'context' => \context_course::instance($course->id)
);
for ($i = 0; $i < 5; $i++) {
\mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
\mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
}
// We do not store events that have no subscriptions - so there will be only 4 events.
$this->assertEquals(4, $DB->count_records('tool_monitor_events'));
// Run the task and check that all the quiz, scorm and rule events are removed as well as the course_module_*
// viewed events in the second course.
$task = new \tool_monitor\task\clean_events();
$task->execute();
$events = $DB->get_records('tool_monitor_events', array(), 'id');
$this->assertEquals(4, count($events));
$event1 = array_shift($events);
$event2 = array_shift($events);
$event3 = array_shift($events);
$event4 = array_shift($events);
$this->assertEquals('\mod_book\event\course_module_viewed', $event1->eventname);
$this->assertEquals($course->id, $event1->courseid);
$this->assertEquals('\mod_book\event\course_module_instance_list_viewed', $event2->eventname);
$this->assertEquals($course->id, $event2->courseid);
$this->assertEquals('\mod_book\event\chapter_viewed', $event3->eventname);
$this->assertEquals($course->id, $event3->courseid);
$this->assertEquals('\mod_book\event\chapter_viewed', $event4->eventname);
$this->assertEquals($course2->id, $event4->courseid);
// Update the timewindow for two of the rules.
$updaterule = new \stdClass();
$updaterule->id = $rule1->id;
$updaterule->timewindow = 0;
\tool_monitor\rule_manager::update_rule($updaterule);
$updaterule->id = $rule2->id;
\tool_monitor\rule_manager::update_rule($updaterule);
// Run the task and check that the events remain as we still have not reached the maximum timewindow.
$task = new \tool_monitor\task\clean_events();
$task->execute();
$this->assertEquals(4, $DB->count_records('tool_monitor_events'));
// Now, remove the rules associated with course_module_* events so they get deleted.
\tool_monitor\rule_manager::delete_rule($rule1->id);
\tool_monitor\rule_manager::delete_rule($rule2->id);
\tool_monitor\rule_manager::delete_rule($rule3->id);
\tool_monitor\rule_manager::delete_rule($rule4->id);
// Run the task and check all the course_module_* events are gone.
$task = new \tool_monitor\task\clean_events();
$task->execute();
// We now should only have the chapter_viewed events.
$events = $DB->get_records('tool_monitor_events', array(), 'id');
$this->assertEquals(2, count($events));
$event1 = array_shift($events);
$event2 = array_shift($events);
$this->assertEquals('\mod_book\event\chapter_viewed', $event1->eventname);
$this->assertEquals($course->id, $event1->courseid);
$this->assertEquals('\mod_book\event\chapter_viewed', $event2->eventname);
$this->assertEquals($course2->id, $event2->courseid);
// Set the timewindow of the rule for the event chapter_viewed in the second course to 0.
$updaterule->id = $rule5->id;
\tool_monitor\rule_manager::update_rule($updaterule);
// Run the task.
$task = new \tool_monitor\task\clean_events();
$task->execute();
// Check that nothing was deleted as we still have a site wide rule for the chapter_viewed event.
$this->assertEquals(2, $DB->count_records('tool_monitor_events'));
// Set the timewindow back to 500.
$updaterule->id = $rule5->id;
$updaterule->timewindow = 500;
\tool_monitor\rule_manager::update_rule($updaterule);
// Set the site rule timewindow to 0.
$updaterule->id = $rule6->id;
$updaterule->timewindow = 0;
\tool_monitor\rule_manager::update_rule($updaterule);
// Run the task.
$task = new \tool_monitor\task\clean_events();
$task->execute();
// We now should only have one chapter_viewed event for the second course.
$events = $DB->get_records('tool_monitor_events');
$this->assertEquals(1, count($events));
$event1 = array_shift($events);
$this->assertEquals('\mod_book\event\chapter_viewed', $event1->eventname);
$this->assertEquals($course2->id, $event1->courseid);
// Remove the site rule.
\tool_monitor\rule_manager::delete_rule($rule6->id);
// Remove the last remaining rule.
\tool_monitor\rule_manager::delete_rule($rule5->id);
// Run the task.
$task = new \tool_monitor\task\clean_events();
$task->execute();
// There should be no events left.
$this->assertEquals(0, $DB->count_records('tool_monitor_events'));
}
}