diff --git a/admin/tool/monitor/classes/eventobservers.php b/admin/tool/monitor/classes/eventobservers.php index 2ffc4fd5631..3918a7dd32f 100644 --- a/admin/tool/monitor/classes/eventobservers.php +++ b/admin/tool/monitor/classes/eventobservers.php @@ -129,6 +129,7 @@ class eventobservers { $select = "SELECT COUNT(id) FROM {tool_monitor_events} "; $now = time(); $messagestosend = array(); + $allsubids = array(); // Let us now process the events and check for subscriptions. foreach ($events as $eventobj) { @@ -136,6 +137,7 @@ class eventobservers { $idstosend = array(); foreach ($subscriptions as $subscription) { $starttime = $now - $subscription->timewindow; + $starttime = ($starttime > $subscription->lastnotificationsent) ? $starttime : $subscription->lastnotificationsent; if ($subscription->courseid == 0) { // Site level subscription. Count all events. $where = "eventname = :eventname AND timecreated > :starttime"; @@ -188,9 +190,18 @@ class eventobservers { } if (!empty($idstosend)) { $messagestosend[] = array('subscriptionids' => $idstosend, 'event' => $eventobj); + $allsubids = array_merge($allsubids, $idstosend); } } + if (!empty($allsubids)) { + // Update the last trigger flag. + list($sql, $params) = $DB->get_in_or_equal($allsubids, SQL_PARAMS_NAMED); + $params['now'] = $now; + $sql = "UPDATE {tool_monitor_subscriptions} SET lastnotificationsent = :now WHERE id $sql"; + $DB->execute($sql, $params); + } + // Schedule a task to send notification. if (!empty($messagestosend)) { $adhocktask = new notification_task(); diff --git a/admin/tool/monitor/db/install.xml b/admin/tool/monitor/db/install.xml index 39d2bb94ef7..7729199f1b8 100644 --- a/admin/tool/monitor/db/install.xml +++ b/admin/tool/monitor/db/install.xml @@ -1,5 +1,5 @@ - @@ -37,6 +37,7 @@ + diff --git a/admin/tool/monitor/db/upgrade.php b/admin/tool/monitor/db/upgrade.php new file mode 100644 index 00000000000..59f0e869fca --- /dev/null +++ b/admin/tool/monitor/db/upgrade.php @@ -0,0 +1,54 @@ +. + +/** + * Upgrade scirpt for tool_monitor. + * + * @package tool_monitor + * @copyright 2014 onwards Ankit Agarwal + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Upgrade the plugin. + * + * @param int $oldversion + * @return bool always true + */ +function xmldb_tool_monitor_upgrade($oldversion) { + global $DB; + + $dbman = $DB->get_manager(); + + if ($oldversion < 2014102000) { + + // Define field lastnotificationsent to be added to tool_monitor_subscriptions. + $table = new xmldb_table('tool_monitor_subscriptions'); + $field = new xmldb_field('lastnotificationsent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timecreated'); + + // Conditionally launch add field lastnotificationsent. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Monitor savepoint reached. + upgrade_plugin_savepoint(true, 2014102000, 'tool', 'monitor'); + } + + return true; +} diff --git a/admin/tool/monitor/tests/eventobservers_test.php b/admin/tool/monitor/tests/eventobservers_test.php index 4e601835ec5..f9d0ed0282f 100644 --- a/admin/tool/monitor/tests/eventobservers_test.php +++ b/admin/tool/monitor/tests/eventobservers_test.php @@ -266,6 +266,53 @@ class tool_monitor_eventobservers_testcase extends advanced_testcase { $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() { + 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(); + sleep(1); // 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. */ diff --git a/admin/tool/monitor/version.php b/admin/tool/monitor/version.php index b8150b03136..9231910cfdc 100644 --- a/admin/tool/monitor/version.php +++ b/admin/tool/monitor/version.php @@ -26,6 +26,6 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2014061901; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2014102000; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2014061900; // Requires this Moodle version. $plugin->component = 'tool_monitor'; // Full name of the plugin (used for diagnostics).