Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * External database store.
19
 *
20
 * @package    logstore_database
21
 * @copyright  2013 Petr Skoda {@link http://skodak.org}
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace logstore_database\log;
26
defined('MOODLE_INTERNAL') || die();
27
 
28
class store implements \tool_log\log\writer, \core\log\sql_reader {
29
    use \tool_log\helper\store,
30
        \tool_log\helper\reader,
31
        \tool_log\helper\buffered_writer {
32
        dispose as helper_dispose;
33
    }
34
 
35
    /** @var \moodle_database $extdb */
36
    protected $extdb;
37
 
38
    /** @var bool $logguests true if logging guest access */
39
    protected $logguests;
40
 
41
    /** @var array $includelevels An array of education levels to include */
42
    protected $includelevels = array();
43
 
44
    /** @var array $includeactions An array of actions types to include */
45
    protected $includeactions = array();
46
 
47
    /**
48
     * Construct
49
     *
50
     * @param \tool_log\log\manager $manager
51
     */
52
    public function __construct(\tool_log\log\manager $manager) {
53
        $this->helper_setup($manager);
54
        $this->buffersize = $this->get_config('buffersize', 50);
55
        $this->logguests = $this->get_config('logguests', 1);
56
        $actions = $this->get_config('includeactions', '');
57
        $levels = $this->get_config('includelevels', '');
58
        $this->includeactions = $actions === '' ? array() : explode(',', $actions);
59
        $this->includelevels = $levels === '' ? array() : explode(',', $levels);
60
        // JSON writing defaults to false (table format compatibility with older versions).
61
        // Note: This variable is defined in the buffered_writer trait.
62
        $this->jsonformat = (bool)$this->get_config('jsonformat', false);
63
    }
64
 
65
    /**
66
     * Setup the Database.
67
     *
68
     * @return bool
69
     */
70
    protected function init() {
71
        if (isset($this->extdb)) {
72
            return !empty($this->extdb);
73
        }
74
 
75
        $dbdriver = $this->get_config('dbdriver');
76
        if (empty($dbdriver)) {
77
            $this->extdb = false;
78
            return false;
79
        }
80
        list($dblibrary, $dbtype) = explode('/', $dbdriver);
81
 
82
        if (!$db = \moodle_database::get_driver_instance($dbtype, $dblibrary, true)) {
83
            debugging("Unknown driver $dblibrary/$dbtype", DEBUG_DEVELOPER);
84
            $this->extdb = false;
85
            return false;
86
        }
87
 
88
        $dboptions = array();
89
        $dboptions['dbpersist'] = $this->get_config('dbpersist', '0');
90
        $dboptions['dbsocket'] = $this->get_config('dbsocket', '');
91
        $dboptions['dbport'] = $this->get_config('dbport', '');
92
        $dboptions['dbschema'] = $this->get_config('dbschema', '');
93
        $dboptions['dbcollation'] = $this->get_config('dbcollation', '');
94
        $dboptions['dbhandlesoptions'] = $this->get_config('dbhandlesoptions', false);
95
        try {
96
            $db->connect($this->get_config('dbhost'), $this->get_config('dbuser'), $this->get_config('dbpass'),
97
                $this->get_config('dbname'), false, $dboptions);
98
            $tables = $db->get_tables();
99
            if (!in_array($this->get_config('dbtable'), $tables)) {
100
                debugging('Cannot find the specified table', DEBUG_DEVELOPER);
101
                $this->extdb = false;
102
                return false;
103
            }
104
        } catch (\moodle_exception $e) {
105
            debugging('Cannot connect to external database: ' . $e->getMessage(), DEBUG_DEVELOPER);
106
            $this->extdb = false;
107
            return false;
108
        }
109
 
110
        $this->extdb = $db;
111
        return true;
112
    }
113
 
114
    /**
115
     * Should the event be ignored (== not logged)?
116
     * @param \core\event\base $event
117
     * @return bool
118
     */
119
    protected function is_event_ignored(\core\event\base $event) {
120
        if (!in_array($event->crud, $this->includeactions) &&
121
            !in_array($event->edulevel, $this->includelevels)
122
        ) {
123
            // Ignore event if the store settings do not want to store it.
124
            return true;
125
        }
126
        if ((!CLI_SCRIPT or PHPUNIT_TEST) and !$this->logguests) {
127
            // Always log inside CLI scripts because we do not login there.
128
            if (!isloggedin() or isguestuser()) {
129
                return true;
130
            }
131
        }
132
        return false;
133
    }
134
 
135
    /**
136
     * Insert events in bulk to the database.
137
     *
138
     * @param array $evententries raw event data
139
     */
140
    protected function insert_event_entries($evententries) {
141
        if (!$this->init()) {
142
            return;
143
        }
144
        if (!$dbtable = $this->get_config('dbtable')) {
145
            return;
146
        }
147
        try {
148
            $this->extdb->insert_records($dbtable, $evententries);
149
        } catch (\moodle_exception $e) {
150
            debugging('Cannot write to external database: ' . $e->getMessage(), DEBUG_DEVELOPER);
151
        }
152
    }
153
 
154
    /**
155
     * Get an array of events based on the passed on params.
156
     *
157
     * @param string $selectwhere select conditions.
158
     * @param array $params params.
159
     * @param string $sort sortorder.
160
     * @param int $limitfrom limit constraints.
161
     * @param int $limitnum limit constraints.
162
     *
163
     * @return array|\core\event\base[] array of events.
164
     */
165
    public function get_events_select($selectwhere, array $params, $sort, $limitfrom, $limitnum) {
166
        if (!$this->init()) {
167
            return array();
168
        }
169
 
170
        if (!$dbtable = $this->get_config('dbtable')) {
171
            return array();
172
        }
173
 
174
        $sort = self::tweak_sort_by_id($sort);
175
 
176
        $events = array();
177
        $records = $this->extdb->get_records_select($dbtable, $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
178
 
179
        foreach ($records as $data) {
180
            if ($event = $this->get_log_event($data)) {
181
                $events[$data->id] = $event;
182
            }
183
        }
184
 
185
        return $events;
186
    }
187
 
188
    /**
189
     * Fetch records using given criteria returning a Traversable object.
190
     *
191
     * Note that the traversable object contains a moodle_recordset, so
192
     * remember that is important that you call close() once you finish
193
     * using it.
194
     *
195
     * @param string $selectwhere
196
     * @param array $params
197
     * @param string $sort
198
     * @param int $limitfrom
199
     * @param int $limitnum
200
     * @return \core\dml\recordset_walk|\core\event\base[]
201
     */
202
    public function get_events_select_iterator($selectwhere, array $params, $sort, $limitfrom, $limitnum) {
203
        if (!$this->init()) {
204
            return array();
205
        }
206
 
207
        if (!$dbtable = $this->get_config('dbtable')) {
208
            return array();
209
        }
210
 
211
        $sort = self::tweak_sort_by_id($sort);
212
 
213
        $recordset = $this->extdb->get_recordset_select($dbtable, $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
214
 
215
        return new \core\dml\recordset_walk($recordset, array($this, 'get_log_event'));
216
    }
217
 
218
    /**
219
     * Returns an event from the log data.
220
     *
221
     * @param stdClass $data Log data
222
     * @return \core\event\base
223
     */
224
    public function get_log_event($data) {
225
 
226
        $extra = array('origin' => $data->origin, 'ip' => $data->ip, 'realuserid' => $data->realuserid);
227
        $data = (array)$data;
228
        $id = $data['id'];
229
        $data['other'] = self::decode_other($data['other']);
230
        if ($data['other'] === false) {
231
            $data['other'] = array();
232
        }
233
        unset($data['origin']);
234
        unset($data['ip']);
235
        unset($data['realuserid']);
236
        unset($data['id']);
237
 
238
        if (!$event = \core\event\base::restore($data, $extra)) {
239
            return null;
240
        }
241
 
242
        return $event;
243
    }
244
 
245
    /**
246
     * Get number of events present for the given select clause.
247
     *
248
     * @param string $selectwhere select conditions.
249
     * @param array $params params.
250
     *
251
     * @return int Number of events available for the given conditions
252
     */
253
    public function get_events_select_count($selectwhere, array $params) {
254
        if (!$this->init()) {
255
            return 0;
256
        }
257
 
258
        if (!$dbtable = $this->get_config('dbtable')) {
259
            return 0;
260
        }
261
 
262
        return $this->extdb->count_records_select($dbtable, $selectwhere, $params);
263
    }
264
 
265
    /**
266
     * Get whether events are present for the given select clause.
267
     *
268
     * @param string $selectwhere select conditions.
269
     * @param array $params params.
270
     *
271
     * @return bool Whether events available for the given conditions
272
     */
273
    public function get_events_select_exists(string $selectwhere, array $params): bool {
274
        if (!$this->init()) {
275
            return false;
276
        }
277
 
278
        if (!$dbtable = $this->get_config('dbtable')) {
279
            return false;
280
        }
281
 
282
        return $this->extdb->record_exists_select($dbtable, $selectwhere, $params);
283
    }
284
 
285
    /**
286
     * Get a config value for the store.
287
     *
288
     * @param string $name Config name
289
     * @param mixed $default default value
290
     * @return mixed config value if set, else the default value.
291
     */
292
    public function get_config_value($name, $default = null) {
293
        return $this->get_config($name, $default);
294
    }
295
 
296
    /**
297
     * Get the external database object.
298
     *
299
     * @return \moodle_database $extdb
300
     */
301
    public function get_extdb() {
302
        if (!$this->init()) {
303
            return false;
304
        }
305
 
306
        return $this->extdb;
307
    }
308
 
309
    /**
310
     * Are the new events appearing in the reader?
311
     *
312
     * @return bool true means new log events are being added, false means no new data will be added
313
     */
314
    public function is_logging() {
315
        if (!$this->init()) {
316
            return false;
317
        }
318
        return true;
319
    }
320
 
321
    /**
322
     * Dispose off database connection after pushing any buffered events to the database.
323
     */
324
    public function dispose() {
325
        $this->helper_dispose();
326
        if ($this->extdb) {
327
            $this->extdb->dispose();
328
        }
329
        $this->extdb = null;
330
    }
331
}