Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
namespace core_admin\reportbuilder\local\entities;
18
 
19
use core_reportbuilder\local\filters\date;
20
use core_reportbuilder\local\filters\duration;
21
use core_reportbuilder\local\filters\number;
22
use core_reportbuilder\local\filters\select;
23
use core_reportbuilder\local\filters\text;
24
use core_reportbuilder\local\filters\autocomplete;
25
use core_reportbuilder\local\helpers\format;
26
use lang_string;
27
use core_reportbuilder\local\entities\base;
28
use core_reportbuilder\local\report\column;
29
use core_reportbuilder\local\report\filter;
30
use stdClass;
31
use core_collator;
32
 
33
/**
34
 * Task log entity class implementation
35
 *
36
 * @package    core_admin
37
 * @copyright  2021 David Matamoros <davidmc@moodle.com>
38
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39
 */
40
class task_log extends base {
41
 
42
    /** @var int Result success */
43
    protected const SUCCESS = 0;
44
 
45
    /** @var int Result failed */
46
    protected const FAILED = 1;
47
 
48
    /**
49
     * Database tables that this entity uses
50
     *
51
     * @return string[]
52
     */
53
    protected function get_default_tables(): array {
54
        return [
55
            'task_log',
56
        ];
57
    }
58
 
59
    /**
60
     * The default title for this entity in the list of columns/conditions/filters in the report builder
61
     *
62
     * @return lang_string
63
     */
64
    protected function get_default_entity_title(): lang_string {
65
        return new lang_string('entitytasklog', 'admin');
66
    }
67
 
68
    /**
69
     * Initialise the entity
70
     *
71
     * @return base
72
     */
73
    public function initialise(): base {
74
        $columns = $this->get_all_columns();
75
        foreach ($columns as $column) {
76
            $this->add_column($column);
77
        }
78
 
79
        // All the filters defined by the entity can also be used as conditions.
80
        $filters = $this->get_all_filters();
81
        foreach ($filters as $filter) {
82
            $this
83
                ->add_filter($filter)
84
                ->add_condition($filter);
85
        }
86
 
87
        return $this;
88
    }
89
 
90
    /**
91
     * Returns list of all available columns
92
     *
93
     * @return column[]
94
     */
95
    protected function get_all_columns(): array {
96
        global $DB;
97
 
98
        $tablealias = $this->get_table_alias('task_log');
99
 
100
        // Name column.
101
        $columns[] = (new column(
102
            'name',
103
            new lang_string('name'),
104
            $this->get_entity_name()
105
        ))
106
            ->add_joins($this->get_joins())
107
            ->set_type(column::TYPE_TEXT)
1441 ariadna 108
            ->add_field("{$tablealias}.classname")
1 efrain 109
            ->set_is_sortable(true)
110
            ->add_callback(static function(string $classname): string {
111
                $output = '';
112
                if (class_exists($classname)) {
113
                    $task = new $classname;
114
                    if ($task instanceof \core\task\task_base) {
115
                        $output = $task->get_name();
116
                    }
117
                }
118
                $output .= \html_writer::tag('div', "\\{$classname}", [
119
                    'class' => 'small text-muted',
120
                ]);
121
                return $output;
122
            });
123
 
124
        // Component column.
125
        $columns[] = (new column(
126
            'component',
127
            new lang_string('plugin'),
128
            $this->get_entity_name()
129
        ))
130
            ->add_joins($this->get_joins())
131
            ->set_type(column::TYPE_TEXT)
132
            ->add_field("{$tablealias}.component")
133
            ->set_is_sortable(true);
134
 
135
        // Type column.
136
        $columns[] = (new column(
137
            'type',
138
            new lang_string('tasktype', 'admin'),
139
            $this->get_entity_name()
140
        ))
141
            ->add_joins($this->get_joins())
142
            ->set_type(column::TYPE_TEXT)
143
            ->add_field("{$tablealias}.type")
144
            ->set_is_sortable(true)
145
            ->add_callback(static function($value): string {
146
                if (\core\task\database_logger::TYPE_SCHEDULED === (int) $value) {
147
                    return get_string('task_type:scheduled', 'admin');
148
                }
149
                return get_string('task_type:adhoc', 'admin');
150
            });
151
 
152
        // Start time column.
153
        $columns[] = (new column(
154
            'starttime',
155
            new lang_string('task_starttime', 'admin'),
156
            $this->get_entity_name()
157
        ))
158
            ->add_joins($this->get_joins())
159
            ->set_type(column::TYPE_TIMESTAMP)
160
            ->add_field("{$tablealias}.timestart")
161
            ->set_is_sortable(true)
162
            ->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
163
 
164
        // End time column.
165
        $columns[] = (new column(
166
            'endtime',
167
            new lang_string('task_endtime', 'admin'),
168
            $this->get_entity_name()
169
        ))
170
            ->add_joins($this->get_joins())
171
            ->set_type(column::TYPE_TIMESTAMP)
172
            ->add_field("{$tablealias}.timeend")
173
            ->set_is_sortable(true)
174
            ->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
175
 
176
        // Duration column.
177
        $columns[] = (new column(
178
            'duration',
179
            new lang_string('task_duration', 'admin'),
180
            $this->get_entity_name()
181
        ))
182
            ->add_joins($this->get_joins())
183
            ->set_type(column::TYPE_FLOAT)
184
            ->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
185
            ->set_is_sortable(true)
1441 ariadna 186
            ->add_callback([format::class, 'format_time'], 2);
1 efrain 187
 
188
        // Hostname column.
189
        $columns[] = (new column(
190
            'hostname',
191
            new lang_string('hostname', 'admin'),
192
            $this->get_entity_name()
193
        ))
194
            ->add_joins($this->get_joins())
195
            ->set_type(column::TYPE_TEXT)
196
            ->add_field("$tablealias.hostname")
197
            ->set_is_sortable(true);
198
 
199
        // PID column.
200
        $columns[] = (new column(
201
            'pid',
202
            new lang_string('pid', 'admin'),
203
            $this->get_entity_name()
204
        ))
205
            ->add_joins($this->get_joins())
206
            ->add_field("{$tablealias}.pid")
1441 ariadna 207
            ->set_is_sortable(true);
1 efrain 208
 
209
        // Database column.
210
        $columns[] = (new column(
211
            'database',
212
            new lang_string('task_dbstats', 'admin'),
213
            $this->get_entity_name()
214
        ))
215
            ->add_joins($this->get_joins())
216
            ->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
217
            ->set_is_sortable(true, ["{$tablealias}.dbreads", "{$tablealias}.dbwrites"])
1441 ariadna 218
            ->add_callback(static function($value, stdClass $row): string {
1 efrain 219
                $output = '';
220
                $output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
221
                $output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
222
                return $output;
1441 ariadna 223
            });
1 efrain 224
 
225
        // Database reads column.
226
        $columns[] = (new column(
227
            'dbreads',
228
            new lang_string('task_dbreads', 'admin'),
229
            $this->get_entity_name()
230
        ))
231
            ->add_joins($this->get_joins())
232
            ->set_type(column::TYPE_INTEGER)
233
            ->add_fields("{$tablealias}.dbreads")
234
            ->set_is_sortable(true);
235
 
236
        // Database writes column.
237
        $columns[] = (new column(
238
            'dbwrites',
239
            new lang_string('task_dbwrites', 'admin'),
240
            $this->get_entity_name()
241
        ))
242
            ->add_joins($this->get_joins())
243
            ->set_type(column::TYPE_INTEGER)
244
            ->add_fields("{$tablealias}.dbwrites")
245
            ->set_is_sortable(true);
246
 
247
        // Result column.
248
        $columns[] = (new column(
249
            'result',
250
            new lang_string('task_result', 'admin'),
251
            $this->get_entity_name()
252
        ))
253
            ->add_joins($this->get_joins())
254
            ->set_type(column::TYPE_BOOLEAN)
255
            // For accurate aggregation, we need to return boolean success = true by xor'ing the field value.
256
            ->add_field($DB->sql_bitxor("{$tablealias}.result", 1), 'success')
257
            ->set_is_sortable(true)
258
            ->add_callback(static function(bool $success): string {
259
                if (!$success) {
260
                    return get_string('task_result:failed', 'admin');
261
                }
262
                return get_string('success');
263
            });
264
 
265
        return $columns;
266
    }
267
 
268
    /**
269
     * Return list of all available filters
270
     *
271
     * @return filter[]
272
     */
273
    protected function get_all_filters(): array {
274
        $tablealias = $this->get_table_alias('task_log');
275
 
276
        // Name filter (Filter by classname).
277
        $filters[] = (new filter(
278
            autocomplete::class,
279
            'name',
280
            new lang_string('classname', 'tool_task'),
281
            $this->get_entity_name(),
282
            "{$tablealias}.classname"
283
        ))
284
            ->add_joins($this->get_joins())
285
            ->set_options_callback(static function(): array {
286
                global $DB;
287
                $classnames = $DB->get_fieldset_sql('SELECT DISTINCT classname FROM {task_log} ORDER BY classname ASC');
288
 
289
                $options = [];
290
                foreach ($classnames as $classname) {
291
                    if (class_exists($classname)) {
292
                        $task = new $classname;
293
                        $options[$classname] = $task->get_name();
294
                    }
295
                }
296
 
297
                core_collator::asort($options);
298
                return $options;
299
            });
300
 
301
        // Component filter.
302
        $filters[] = (new filter(
303
            text::class,
304
            'component',
305
            new lang_string('plugin'),
306
            $this->get_entity_name(),
307
            "{$tablealias}.component"
308
        ))
309
            ->add_joins($this->get_joins());
310
 
311
        // Type filter.
312
        $filters[] = (new filter(
313
            select::class,
314
            'type',
315
            new lang_string('tasktype', 'admin'),
316
            $this->get_entity_name(),
317
            "{$tablealias}.type"
318
        ))
319
            ->add_joins($this->get_joins())
320
            ->set_options([
321
                \core\task\database_logger::TYPE_ADHOC => new lang_string('task_type:adhoc', 'admin'),
322
                \core\task\database_logger::TYPE_SCHEDULED => new lang_string('task_type:scheduled', 'admin'),
323
            ]);
324
 
325
        // Output filter (Filter by task output).
326
        $filters[] = (new filter(
327
            text::class,
328
            'output',
329
            new lang_string('task_logoutput', 'admin'),
330
            $this->get_entity_name(),
1441 ariadna 331
            "{$tablealias}.output"
1 efrain 332
        ))
333
            ->add_joins($this->get_joins());
334
 
335
        // Start time filter.
336
        $filters[] = (new filter(
337
            date::class,
338
            'timestart',
339
            new lang_string('task_starttime', 'admin'),
340
            $this->get_entity_name(),
341
            "{$tablealias}.timestart"
342
        ))
343
            ->add_joins($this->get_joins())
344
            ->set_limited_operators([
345
                date::DATE_ANY,
346
                date::DATE_RANGE,
347
                date::DATE_PREVIOUS,
348
                date::DATE_CURRENT,
349
            ]);
350
 
351
        // End time.
352
        $filters[] = (new filter(
353
            date::class,
354
            'timeend',
355
            new lang_string('task_endtime', 'admin'),
356
            $this->get_entity_name(),
357
            "{$tablealias}.timeend"
358
        ))
359
            ->add_joins($this->get_joins())
360
            ->set_limited_operators([
361
                date::DATE_ANY,
362
                date::DATE_RANGE,
363
                date::DATE_PREVIOUS,
364
                date::DATE_CURRENT,
365
            ]);
366
 
367
        // Duration filter.
368
        $filters[] = (new filter(
369
            duration::class,
370
            'duration',
371
            new lang_string('task_duration', 'admin'),
372
            $this->get_entity_name(),
373
            "{$tablealias}.timeend - {$tablealias}.timestart"
374
        ))
375
            ->add_joins($this->get_joins());
376
 
377
        // Database reads.
378
        $filters[] = (new filter(
379
            number::class,
380
            'dbreads',
381
            new lang_string('task_dbreads', 'admin'),
382
            $this->get_entity_name(),
383
            "{$tablealias}.dbreads"
384
        ))
385
            ->add_joins($this->get_joins());
386
 
387
        // Database writes.
388
        $filters[] = (new filter(
389
            number::class,
390
            'dbwrites',
391
            new lang_string('task_dbwrites', 'admin'),
392
            $this->get_entity_name(),
393
            "{$tablealias}.dbwrites"
394
        ))
395
            ->add_joins($this->get_joins());
396
 
397
        // Result filter.
398
        $filters[] = (new filter(
399
            select::class,
400
            'result',
401
            new lang_string('task_result', 'admin'),
402
            $this->get_entity_name(),
403
            "{$tablealias}.result"
404
        ))
405
            ->add_joins($this->get_joins())
406
            ->set_options([
407
                self::SUCCESS => get_string('success'),
408
                self::FAILED => get_string('task_result:failed', 'admin'),
409
            ]);
410
 
411
        return $filters;
412
    }
413
}