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
declare(strict_types=1);
18
 
19
namespace core_reportbuilder\local\helpers;
20
 
21
use stdClass;
22
use invalid_parameter_exception;
23
use core\persistent;
24
use core_reportbuilder\datasource;
25
use core_reportbuilder\manager;
26
use core_reportbuilder\local\models\column;
27
use core_reportbuilder\local\models\filter;
28
use core_reportbuilder\local\models\report as report_model;
29
use core_tag_tag;
30
 
31
/**
32
 * Helper class for manipulating custom reports and their elements (columns, filters, conditions, etc)
33
 *
34
 * @package     core_reportbuilder
35
 * @copyright   2021 Paul Holden <paulh@moodle.com>
36
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
38
class report {
39
 
40
    /**
41
     * Create custom report
42
     *
43
     * @param stdClass $data
44
     * @param bool $default If $default is set to true it will populate report with default layout as defined by the selected
45
     *                      source. These include pre-defined columns, filters and conditions.
46
     * @return report_model
47
     */
48
    public static function create_report(stdClass $data, bool $default = true): report_model {
49
        $data->name = trim($data->name);
50
        $data->type = datasource::TYPE_CUSTOM_REPORT;
51
 
52
        // Create report persistent.
53
        $report = manager::create_report_persistent($data);
54
 
55
        // Add datasource default columns, filters and conditions to the report.
56
        if ($default) {
57
            $source = $report->get('source');
58
            /** @var datasource $datasource */
59
            $datasource = new $source($report);
60
            $datasource->add_default_columns();
61
            $datasource->add_default_filters();
62
            $datasource->add_default_conditions();
63
        }
64
 
65
        // Report tags.
66
        if (property_exists($data, "tags")) {
67
            core_tag_tag::set_item_tags('core_reportbuilder', 'reportbuilder_report', $report->get('id'),
68
                $report->get_context(), $data->tags);
69
        }
70
 
71
        return $report;
72
    }
73
 
74
    /**
75
     * Update custom report
76
     *
77
     * @param stdClass $data
78
     * @return report_model
79
     */
80
    public static function update_report(stdClass $data): report_model {
81
        $report = report_model::get_record(['id' => $data->id, 'type' => datasource::TYPE_CUSTOM_REPORT]);
82
        if ($report === false) {
83
            throw new invalid_parameter_exception('Invalid report');
84
        }
85
 
86
        $report->set_many([
87
            'name' => trim($data->name),
88
            'uniquerows' => $data->uniquerows,
89
        ])->update();
90
 
91
        // Report tags.
92
        if (property_exists($data, "tags")) {
93
            core_tag_tag::set_item_tags('core_reportbuilder', 'reportbuilder_report', $report->get('id'),
94
                $report->get_context(), $data->tags);
95
        }
96
 
97
        return $report;
98
    }
99
 
100
    /**
101
     * Delete custom report
102
     *
103
     * @param int $reportid
104
     * @return bool
105
     * @throws invalid_parameter_exception
106
     */
107
    public static function delete_report(int $reportid): bool {
108
        $report = report_model::get_record(['id' => $reportid, 'type' => datasource::TYPE_CUSTOM_REPORT]);
109
        if ($report === false) {
110
            throw new invalid_parameter_exception('Invalid report');
111
        }
112
 
113
        // Report tags.
114
        core_tag_tag::remove_all_item_tags('core_reportbuilder', 'reportbuilder_report', $report->get('id'));
115
 
116
        return $report->delete();
117
    }
118
 
119
    /**
120
     * Add given column to report
121
     *
122
     * @param int $reportid
123
     * @param string $uniqueidentifier
124
     * @return column
125
     * @throws invalid_parameter_exception
126
     */
127
    public static function add_report_column(int $reportid, string $uniqueidentifier): column {
128
        $report = manager::get_report_from_id($reportid);
129
 
130
        // Ensure column is available.
131
        if (!array_key_exists($uniqueidentifier, $report->get_columns())) {
132
            throw new invalid_parameter_exception('Invalid column');
133
        }
134
 
135
        $column = new column(0, (object) [
136
            'reportid' => $reportid,
137
            'uniqueidentifier' => $uniqueidentifier,
138
            'columnorder' => column::get_max_columnorder($reportid, 'columnorder') + 1,
139
            'sortorder' => column::get_max_columnorder($reportid, 'sortorder') + 1,
140
        ]);
141
 
142
        return $column->create();
143
    }
144
 
145
    /**
146
     * Delete given column from report
147
     *
148
     * @param int $reportid
149
     * @param int $columnid
150
     * @return bool
151
     * @throws invalid_parameter_exception
152
     */
153
    public static function delete_report_column(int $reportid, int $columnid): bool {
154
        global $DB;
155
 
156
        $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]);
157
        if ($column === false) {
158
            throw new invalid_parameter_exception('Invalid column');
159
        }
160
 
161
        // After deletion, re-index remaining report columns.
162
        if ($result = $column->delete()) {
163
            $sqlupdateorder = '
164
                UPDATE {' . column::TABLE . '}
165
                   SET columnorder = columnorder - 1
166
                 WHERE reportid = :reportid
167
                   AND columnorder > :columnorder';
168
 
169
            $DB->execute($sqlupdateorder, ['reportid' => $reportid, 'columnorder' => $column->get('columnorder')]);
170
        }
171
 
172
        return $result;
173
    }
174
 
175
    /**
176
     * Re-order given column within a report
177
     *
178
     * @param int $reportid
179
     * @param int $columnid
180
     * @param int $position
181
     * @return bool
182
     * @throws invalid_parameter_exception
183
     */
184
    public static function reorder_report_column(int $reportid, int $columnid, int $position): bool {
185
        $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]);
186
        if ($column === false) {
187
            throw new invalid_parameter_exception('Invalid column');
188
        }
189
 
190
        // Get the rest of the report columns, excluding the one we are moving.
191
        $columns = column::get_records_select('reportid = :reportid AND id <> :id', [
192
            'reportid' => $reportid,
193
            'id' => $columnid,
194
        ], 'columnorder');
195
 
196
        return static::reorder_persistents_by_field($column, $columns, $position, 'columnorder');
197
    }
198
 
199
    /**
200
     * Re-order given column sorting within a report
201
     *
202
     * @param int $reportid
203
     * @param int $columnid
204
     * @param int $position
205
     * @return bool
206
     * @throws invalid_parameter_exception
207
     */
208
    public static function reorder_report_column_sorting(int $reportid, int $columnid, int $position): bool {
209
        $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]);
210
        if ($column === false) {
211
            throw new invalid_parameter_exception('Invalid column');
212
        }
213
 
214
        // Get the rest of the report columns, excluding the one we are moving.
215
        $columns = column::get_records_select('reportid = :reportid AND id <> :id', [
216
            'reportid' => $reportid,
217
            'id' => $columnid,
218
        ], 'sortorder');
219
 
220
        return static::reorder_persistents_by_field($column, $columns, $position, 'sortorder');
221
    }
222
 
223
    /**
224
     * Toggle sorting options for given column within a report
225
     *
226
     * @param int $reportid
227
     * @param int $columnid
228
     * @param bool $enabled
229
     * @param int $direction
230
     * @return bool
231
     * @throws invalid_parameter_exception
232
     */
233
    public static function toggle_report_column_sorting(int $reportid, int $columnid, bool $enabled,
234
            int $direction = SORT_ASC): bool {
235
 
236
        $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]);
237
        if ($column === false) {
238
            throw new invalid_parameter_exception('Invalid column');
239
        }
240
 
241
        return $column->set_many([
242
            'sortenabled' => $enabled,
243
            'sortdirection' => $direction,
244
        ])->update();
245
    }
246
 
247
    /**
248
     * Add given condition to report
249
     *
250
     * @param int $reportid
251
     * @param string $uniqueidentifier
252
     * @return filter
253
     * @throws invalid_parameter_exception
254
     */
255
    public static function add_report_condition(int $reportid, string $uniqueidentifier): filter {
256
        $report = manager::get_report_from_id($reportid);
257
 
258
        // Ensure condition is available.
259
        if (!array_key_exists($uniqueidentifier, $report->get_conditions())) {
260
            throw new invalid_parameter_exception('Invalid condition');
261
        }
262
 
263
        // Ensure condition wasn't already added.
264
        if (array_key_exists($uniqueidentifier, $report->get_active_conditions())) {
265
            throw new invalid_parameter_exception('Duplicate condition');
266
        }
267
 
268
        $condition = new filter(0, (object) [
269
            'reportid' => $reportid,
270
            'uniqueidentifier' => $uniqueidentifier,
271
            'iscondition' => true,
272
            'filterorder' => filter::get_max_filterorder($reportid, true) + 1,
273
        ]);
274
 
275
        return $condition->create();
276
    }
277
 
278
    /**
279
     * Delete given condition from report
280
     *
281
     * @param int $reportid
282
     * @param int $conditionid
283
     * @return bool
284
     * @throws invalid_parameter_exception
285
     */
286
    public static function delete_report_condition(int $reportid, int $conditionid): bool {
287
        global $DB;
288
 
289
        $condition = filter::get_condition_record($reportid, $conditionid);
290
        if ($condition === false) {
291
            throw new invalid_parameter_exception('Invalid condition');
292
        }
293
 
294
        // After deletion, re-index remaining report conditions.
295
        if ($result = $condition->delete()) {
296
            $sqlupdateorder = '
297
                UPDATE {' . filter::TABLE . '}
298
                   SET filterorder = filterorder - 1
299
                 WHERE reportid = :reportid
300
                   AND filterorder > :filterorder
301
                   AND iscondition = 1';
302
 
303
            $DB->execute($sqlupdateorder, ['reportid' => $reportid, 'filterorder' => $condition->get('filterorder')]);
304
        }
305
 
306
        return $result;
307
    }
308
 
309
    /**
310
     * Re-order given condition within a report
311
     *
312
     * @param int $reportid
313
     * @param int $conditionid
314
     * @param int $position
315
     * @return bool
316
     * @throws invalid_parameter_exception
317
     */
318
    public static function reorder_report_condition(int $reportid, int $conditionid, int $position): bool {
319
        $condition = filter::get_condition_record($reportid, $conditionid);
320
        if ($condition === false) {
321
            throw new invalid_parameter_exception('Invalid condition');
322
        }
323
 
324
        // Get the rest of the report conditions, excluding the one we are moving.
325
        $conditions = filter::get_records_select('reportid = :reportid AND iscondition = 1 AND id <> :id', [
326
            'reportid' => $reportid,
327
            'id' => $conditionid,
328
        ], 'filterorder');
329
 
330
        return static::reorder_persistents_by_field($condition, $conditions, $position, 'filterorder');
331
    }
332
 
333
    /**
334
     * Add given filter to report
335
     *
336
     * @param int $reportid
337
     * @param string $uniqueidentifier
338
     * @return filter
339
     * @throws invalid_parameter_exception
340
     */
341
    public static function add_report_filter(int $reportid, string $uniqueidentifier): filter {
342
        $report = manager::get_report_from_id($reportid);
343
 
344
        // Ensure filter is available.
345
        if (!array_key_exists($uniqueidentifier, $report->get_filters())) {
346
            throw new invalid_parameter_exception('Invalid filter');
347
        }
348
 
349
        // Ensure filter wasn't already added.
350
        if (array_key_exists($uniqueidentifier, $report->get_active_filters())) {
351
            throw new invalid_parameter_exception('Duplicate filter');
352
        }
353
 
354
        $filter = new filter(0, (object) [
355
            'reportid' => $reportid,
356
            'uniqueidentifier' => $uniqueidentifier,
357
            'filterorder' => filter::get_max_filterorder($reportid) + 1,
358
        ]);
359
 
360
        return $filter->create();
361
    }
362
 
363
    /**
364
     * Delete given filter from report
365
     *
366
     * @param int $reportid
367
     * @param int $filterid
368
     * @return bool
369
     * @throws invalid_parameter_exception
370
     */
371
    public static function delete_report_filter(int $reportid, int $filterid): bool {
372
        global $DB;
373
 
374
        $filter = filter::get_filter_record($reportid, $filterid);
375
        if ($filter === false) {
376
            throw new invalid_parameter_exception('Invalid filter');
377
        }
378
 
379
        // After deletion, re-index remaining report filters.
380
        if ($result = $filter->delete()) {
381
            $sqlupdateorder = '
382
                UPDATE {' . filter::TABLE . '}
383
                   SET filterorder = filterorder - 1
384
                 WHERE reportid = :reportid
385
                   AND filterorder > :filterorder
386
                   AND iscondition = 0';
387
 
388
            $DB->execute($sqlupdateorder, ['reportid' => $reportid, 'filterorder' => $filter->get('filterorder')]);
389
        }
390
 
391
        return $result;
392
    }
393
 
394
    /**
395
     * Re-order given filter within a report
396
     *
397
     * @param int $reportid
398
     * @param int $filterid
399
     * @param int $position
400
     * @return bool
401
     * @throws invalid_parameter_exception
402
     */
403
    public static function reorder_report_filter(int $reportid, int $filterid, int $position): bool {
404
        $filter = filter::get_filter_record($reportid, $filterid);
405
        if ($filter === false) {
406
            throw new invalid_parameter_exception('Invalid filter');
407
        }
408
 
409
        // Get the rest of the report filters, excluding the one we are moving.
410
        $filters = filter::get_records_select('reportid = :reportid AND iscondition = 0 AND id <> :id', [
411
            'reportid' => $reportid,
412
            'id' => $filterid,
413
        ], 'filterorder');
414
 
415
        return static::reorder_persistents_by_field($filter, $filters, $position, 'filterorder');
416
    }
417
 
418
    /**
419
     * Get available columns for a given report
420
     *
421
     * @param report_model $persistent
422
     * @return array
423
     *
424
     * @deprecated since Moodle 4.1 - please do not use this function any more, {@see custom_report_column_cards_exporter}
425
     */
426
    public static function get_available_columns(report_model $persistent): array {
427
        debugging('The function ' . __FUNCTION__ . '() is deprecated, please do not use it any more. ' .
428
            'See \'custom_report_column_cards_exporter\' class for replacement', DEBUG_DEVELOPER);
429
 
430
        $available = [];
431
 
432
        $report = manager::get_report_from_persistent($persistent);
433
 
434
        // Get current report columns.
435
        foreach ($report->get_columns() as $column) {
436
            $entityname = $column->get_entity_name();
437
            $entitytitle = $column->get_title();
438
            if (!array_key_exists($entityname, $available)) {
439
                $available[$entityname] = [
440
                    'name' => (string) $report->get_entity_title($entityname),
441
                    'key' => $entityname,
442
                    'items' => [],
443
                ];
444
            }
445
 
446
            $available[$entityname]['items'][] = [
447
                'name' => $entitytitle,
448
                'identifier' => $column->get_unique_identifier(),
449
                'title' => get_string('addcolumn', 'core_reportbuilder', $entitytitle),
450
                'action' => 'report-add-column'
451
            ];
452
        }
453
 
454
        return array_values($available);
455
    }
456
 
457
    /**
458
     * Helper method for re-ordering given persistents (columns, filters, etc)
459
     *
460
     * @param persistent $persistent The persistent we are moving
461
     * @param persistent[] $persistents The rest of the persistents
462
     * @param int $position
463
     * @param string $field The field we need to update
464
     * @return bool
465
     */
466
    private static function reorder_persistents_by_field(persistent $persistent, array $persistents, int $position,
467
            string $field): bool {
468
 
469
        // Splice into new position.
470
        array_splice($persistents, $position - 1, 0, [$persistent]);
471
 
472
        $fieldorder = 1;
473
        foreach ($persistents as $persistent) {
474
            $persistent->set($field, $fieldorder++)
475
                ->update();
476
        }
477
 
478
        return true;
479
    }
480
}