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 * Event documentation
19 *
20 * @package    tool_monitor
21 * @copyright  2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
22 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace tool_monitor;
26
27defined('MOODLE_INTERNAL') || die();
28
29/**
30 * Class for returning event information.
31 *
32 * @since      Moodle 2.8
33 * @package    tool_monitor
34 * @copyright  2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
35 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 */
37class eventlist {
38    /**
39     * Return all of the core event files.
40     *
41     * @return array Core events.
42     */
43    protected static function get_core_eventlist() {
44        global $CFG;
45
46        // Disable developer debugging as deprecated events will fire warnings.
47        // Setup backup variables to restore the following settings back to what they were when we are finished.
48        $debuglevel          = $CFG->debug;
49        $debugdisplay        = $CFG->debugdisplay;
50        $debugdeveloper      = $CFG->debugdeveloper;
51        $CFG->debug          = 0;
52        $CFG->debugdisplay   = false;
53        $CFG->debugdeveloper = false;
54
55        $eventinformation = array();
56        $directory = $CFG->libdir . '/classes/event';
57        $files = self::get_file_list($directory);
58
59        // Remove exceptional events that will cause problems being displayed.
60        if (isset($files['unknown_logged'])) {
61            unset($files['unknown_logged']);
62        }
63        foreach ($files as $file => $location) {
64            $classname = '\\core\\event\\' . $file;
65            // Check to see if this is actually a valid event.
66            if (method_exists($classname, 'get_static_info')) {
67                $ref = new \ReflectionClass($classname);
68                // Ignore abstracts.
69                if (!$ref->isAbstract() && $file != 'manager') {
70                    $eventinformation[$classname] = $classname::get_name_with_info();
71                }
72            }
73        }
74        // Now enable developer debugging as event information has been retrieved.
75        $CFG->debug          = $debuglevel;
76        $CFG->debugdisplay   = $debugdisplay;
77        $CFG->debugdeveloper = $debugdeveloper;
78        return $eventinformation;
79    }
80
81    /**
82     * This function returns an array of all events for the plugins of the system.
83     *
84     * @param bool $withoutcomponent Return an eventlist without associated components.
85     *
86     * @return array A list of events from all plug-ins.
87     */
88    protected static function get_non_core_eventlist($withoutcomponent = false) {
89        global $CFG;
90        // Disable developer debugging as deprecated events will fire warnings.
91        // Setup backup variables to restore the following settings back to what they were when we are finished.
92        $debuglevel          = $CFG->debug;
93        $debugdisplay        = $CFG->debugdisplay;
94        $debugdeveloper      = $CFG->debugdeveloper;
95        $CFG->debug          = 0;
96        $CFG->debugdisplay   = false;
97        $CFG->debugdeveloper = false;
98
99        $noncorepluginlist = array();
100        $plugintypes = \core_component::get_plugin_types();
101        foreach ($plugintypes as $plugintype => $notused) {
102            $pluginlist = \core_component::get_plugin_list($plugintype);
103            foreach ($pluginlist as $plugin => $directory) {
104                $plugindirectory = $directory . '/classes/event';
105                foreach (self::get_file_list($plugindirectory) as $eventname => $notused) {
106                    $fullpluginname = $plugintype . '_' . $plugin;
107                    $plugineventname = '\\' . $fullpluginname . '\\event\\' . $eventname;
108                    // Check that this is actually an event.
109                    if (method_exists($plugineventname, 'get_static_info')  && $fullpluginname !== 'tool_monitor') { // No selfie here.
110                        $ref = new \ReflectionClass($plugineventname);
111                        if (!$ref->isAbstract() && $fullpluginname !== 'logstore_legacy') {
112                            if ($withoutcomponent) {
113                                $noncorepluginlist[$plugineventname] = $plugineventname::get_name_with_info();
114                            } else {
115                                $noncorepluginlist[$fullpluginname][$plugineventname] = $plugineventname::get_name_with_info();
116                            }
117                        }
118                    }
119                }
120            }
121        }
122
123        // Now enable developer debugging as event information has been retrieved.
124        $CFG->debug          = $debuglevel;
125        $CFG->debugdisplay   = $debugdisplay;
126        $CFG->debugdeveloper = $debugdeveloper;
127
128        return $noncorepluginlist;
129    }
130
131    /**
132     * Returns a list of files with a full directory path in a specified directory.
133     *
134     * @param string $directory location of files.
135     * @return array full location of files from the specified directory.
136     */
137    protected static function get_file_list($directory) {
138        global $CFG;
139        $directoryroot = $CFG->dirroot;
140        $finalfiles = array();
141        if (is_dir($directory)) {
142            if ($handle = opendir($directory)) {
143                $files = scandir($directory);
144                foreach ($files as $file) {
145                    if ($file != '.' && $file != '..') {
146                        // Ignore the file if it is external to the system.
147                        if (strrpos($directory, $directoryroot) !== false) {
148                            $location = substr($directory, strlen($directoryroot));
149                            $name = substr($file, 0, -4);
150                            $finalfiles[$name] = $location  . '/' . $file;
151                        }
152                    }
153                }
154            }
155        }
156        return $finalfiles;
157    }
158
159    /**
160     * Get a list of events present in the system.
161     *
162     * @param bool $withoutcomponent Return an eventlist without associated components.
163     *
164     * @return array list of events present in the system.
165     */
166    public static function get_all_eventlist($withoutcomponent = false) {
167        if ($withoutcomponent) {
168            $return = array_merge(self::get_core_eventlist(), self::get_non_core_eventlist($withoutcomponent));
169            array_multisort($return, SORT_NATURAL);
170        } else {
171            $return = array_merge(array('core' => self::get_core_eventlist()),
172                    self::get_non_core_eventlist($withoutcomponent = false));
173        }
174        return $return;
175    }
176
177    /**
178     * Return list of plugins that have events.
179     *
180     * @param array $eventlist a list of events present in the system {@link eventlist::get_all_eventlist}.
181     *
182     * @return array list of plugins with human readable name.
183     */
184    public static function get_plugin_list($eventlist = array()) {
185        if (empty($eventlist)) {
186            $eventlist = self::get_all_eventlist();
187        }
188        $plugins = array_keys($eventlist);
189        $return = array();
190        foreach ($plugins as $plugin) {
191            if ($plugin === 'core') {
192                $return[$plugin] = get_string('core', 'tool_monitor');
193            } else if (get_string_manager()->string_exists('pluginname', $plugin)) {
194                $return[$plugin] = get_string('pluginname', $plugin);
195            } else {
196                $return[$plugin] = $plugin;
197            }
198        }
199
200        return $return;
201    }
202
203    /**
204     * validate if the given event belongs to the given plugin.
205     *
206     * @param string $plugin Frankenstyle name of the plugin.
207     * @param string $eventname Full qualified event name.
208     * @param array $eventlist List of events generated by {@link eventlist::get_all_eventlist}
209     *
210     * @return bool Returns true if the selected event belongs to the selected plugin, false otherwise.
211     */
212    public static function validate_event_plugin($plugin, $eventname, $eventlist = array()) {
213        if (empty($eventlist)) {
214            $eventlist = self::get_all_eventlist();
215        }
216        if (isset($eventlist[$plugin][$eventname])) {
217            return true;
218        }
219
220        return false;
221    }
222}
223