1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Clean the tool_monitor_events table.
19 *
20 * @package    tool_monitor
21 * @copyright  2014 Mark Nelson <markn@moodle.com>
22 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace tool_monitor\task;
26
27/**
28 * Simple task to clean the tool_monitor_events table.
29 */
30class clean_events extends \core\task\scheduled_task {
31
32    /**
33     * Get a descriptive name for this task.
34     *
35     * @return string
36     */
37    public function get_name() {
38        return get_string('taskcleanevents', 'tool_monitor');
39    }
40
41    /**
42     * Performs the cleaning of events.
43     */
44    public function execute() {
45        global $DB;
46
47        if (!get_config('tool_monitor', 'enablemonitor')) {
48            return; // The tool is disabled. Nothing to do.
49        }
50
51        // Array to store which events have been triggered in which course.
52        $courses = array();
53
54        // Firstly, let's go through the site wide rules. There may be multiple rules for the site that rely on
55        // the same event being triggered, so we only remove the events when they reach the max timewindow.
56        if ($siterules = $DB->get_recordset('tool_monitor_rules', array('courseid' => 0), 'timewindow DESC')) {
57            // Go through each rule and check if there are any events we can remove.
58            foreach ($siterules as $rule) {
59                // Check if we have already processed this event.
60                if (isset($courses[$rule->courseid][$rule->eventname])) {
61                    continue;
62                }
63                // Store the timewindow for this event.
64                $courses[$rule->courseid][$rule->eventname] = $rule->timewindow;
65                // Delete any events that may exist that have exceeded the timewindow.
66                $DB->delete_records_select('tool_monitor_events', 'eventname = :eventname AND
67                    courseid = :courseid AND timecreated <= :timewindow',
68                    array('eventname' => $rule->eventname, 'courseid' => $rule->courseid,
69                        'timewindow' => time() - $rule->timewindow));
70            }
71            // Free resources.
72            $siterules->close();
73        }
74
75        // Now, get the course rules. The same applies here - there may be multiple rules for the course that rely on
76        // the same event being triggered, so we only remove the events when they reach the max timewindow.
77        if ($rules = $DB->get_recordset_select('tool_monitor_rules', 'courseid != 0', array(), 'timewindow DESC')) {
78            // Go through each rule and check if there are any events we can remove.
79            foreach ($rules as $rule) {
80                // Check if we have already processed this event for this particular course.
81                if (isset($courses[$rule->courseid][$rule->eventname])) {
82                    continue;
83                }
84                // Add the course and event to the list.
85                $courses[$rule->courseid][$rule->eventname] = $rule->timewindow;
86                // If there is a site wide rule listening for this event do not remove it unless the maximum
87                // timewindow between the two has exceeded.
88                $timewindow = $rule->timewindow;
89                if (isset($courses[0][$rule->eventname]) && ($courses[0][$rule->eventname] > $timewindow)) {
90                    $timewindow = $courses[0][$rule->eventname];
91                }
92                // Delete any events that may exist that have exceeded the timewindow.
93                $DB->delete_records_select('tool_monitor_events', 'eventname = :eventname AND
94                    courseid = :courseid AND timecreated <= :timewindow',
95                        array('eventname' => $rule->eventname, 'courseid' => $rule->courseid,
96                            'timewindow' => time() - $timewindow));
97            }
98            // Free resources.
99            $rules->close();
100        }
101
102        if ($siterules || $rules) { // Check that there are rules present.
103            // Get a list of all the events we have been through.
104            $allevents = array();
105            foreach ($courses as $key => $value) {
106                foreach ($courses[$key] as $event => $notused) {
107                    $allevents[] = $event;
108                }
109            }
110            // Remove all the events in the table that are not applicable to any rule. There may be a rule in one course
111            // listening for a certain event, but not in another course, so we can delete the event from the course
112            // where there is no rule. We also have to consider site wide rules. We may have an event that is triggered
113            // in a course we can't remove because there is a site wide rule for this event.
114            if ($events = $DB->get_recordset('tool_monitor_events')) {
115                // Array to store which events we need to remove.
116                $eventstodelete = array();
117                // Store the current time.
118                $now = time();
119                foreach ($events as $event) {
120                    // If the event is not required for a course rule and there is no site wide rule for it, or
121                    // it has extended past or equal to the timewindow for the site rule - it can be deleted.
122                    if (!isset($courses[$event->courseid][$event->eventname]) && (!isset($courses[0][$event->eventname])
123                        || $courses[0][$event->eventname] <= ($now - $event->timecreated))) {
124                        $eventstodelete[] = $event->id;
125                    }
126                }
127                // Free resources.
128                $events->close();
129
130                // Remove the events.
131                if (!empty($eventstodelete)) {
132                    list($eventidsql, $params) = $DB->get_in_or_equal($eventstodelete);
133                    $DB->delete_records_select('tool_monitor_events', "id $eventidsql", $params);
134                }
135            }
136
137            // Remove all the events in the table that are not used by any rule.
138            if (!empty($allevents)) {
139                list($eventnamesql, $params) = $DB->get_in_or_equal($allevents, SQL_PARAMS_QM, 'param', false);
140                $DB->delete_records_select('tool_monitor_events', "eventname $eventnamesql", $params);
141            }
142        } else { // No rules, just remove everything.
143            $DB->delete_records('tool_monitor_events');
144        }
145    }
146}
147