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
declare(strict_types=1);
18
 
19
namespace core_badges\reportbuilder\local\entities;
20
 
21
use context_course;
22
use context_helper;
23
use context_system;
24
use html_writer;
25
use lang_string;
26
use moodle_url;
27
use stdClass;
28
use core_reportbuilder\local\entities\base;
29
use core_reportbuilder\local\filters\{date, select, text};
30
use core_reportbuilder\local\helpers\database;
31
use core_reportbuilder\local\report\{column, filter};
32
 
33
defined('MOODLE_INTERNAL') or die;
34
 
35
global $CFG;
36
require_once("{$CFG->libdir}/badgeslib.php");
37
 
38
/**
39
 * Badge entity
40
 *
41
 * @package     core_badges
42
 * @copyright   2022 Paul Holden <paulh@moodle.com>
43
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44
 */
45
class badge extends base {
46
 
47
    /**
48
     * Database tables that this entity uses
49
     *
50
     * @return string[]
51
     */
52
    protected function get_default_tables(): array {
53
        return [
54
            'badge',
55
            'context',
56
            'tag_instance',
57
            'tag',
58
        ];
59
    }
60
 
61
    /**
62
     * The default title for this entity
63
     *
64
     * @return lang_string
65
     */
66
    protected function get_default_entity_title(): lang_string {
67
        return new lang_string('badgedetails', 'core_badges');
68
    }
69
 
70
    /**
71
     * Initialise the entity
72
     *
73
     * @return base
74
     */
75
    public function initialise(): base {
76
        $columns = $this->get_all_columns();
77
        foreach ($columns as $column) {
78
            $this->add_column($column);
79
        }
80
 
81
        // All the filters defined by the entity can also be used as conditions.
82
        $filters = $this->get_all_filters();
83
        foreach ($filters as $filter) {
84
            $this
85
                ->add_filter($filter)
86
                ->add_condition($filter);
87
        }
88
 
89
        return $this;
90
    }
91
 
92
    /**
93
     * Returns list of all available columns
94
     *
95
     * @return column[]
96
     */
97
    protected function get_all_columns(): array {
98
        $badgealias = $this->get_table_alias('badge');
99
        $contextalias = $this->get_table_alias('context');
100
 
101
        // Name.
102
        $columns[] = (new column(
103
            'name',
104
            new lang_string('name'),
105
            $this->get_entity_name()
106
        ))
107
            ->add_joins($this->get_joins())
108
            ->set_type(column::TYPE_TEXT)
109
            ->add_field("{$badgealias}.name")
110
            ->set_is_sortable(true);
111
 
112
        // Name with link.
113
        $columns[] = (new column(
114
            'namewithlink',
115
            new lang_string('namewithlink', 'core_badges'),
116
            $this->get_entity_name()
117
        ))
118
            ->add_joins($this->get_joins())
119
            ->set_type(column::TYPE_TEXT)
120
            ->add_fields("{$badgealias}.name, {$badgealias}.id")
121
            ->set_is_sortable(true)
122
            ->add_callback(static function(?string $value, stdClass $row): string {
123
                if (!$row->id) {
124
                    return '';
125
                }
126
 
127
                $url = new moodle_url('/badges/overview.php', ['id' => $row->id]);
128
                return html_writer::link($url, $row->name);
129
            });
130
 
1441 ariadna 131
        // Name with image and link.
132
        $columns[] = (new column(
133
            'namewithimagelink',
134
            new lang_string('namewithimagelink', 'core_badges'),
135
            $this->get_entity_name()
136
        ))
137
            ->add_joins($this->get_joins())
138
            ->add_join("LEFT JOIN {context} {$contextalias}
139
                    ON {$contextalias}.contextlevel = " . CONTEXT_COURSE . "
140
                   AND {$contextalias}.instanceid = {$badgealias}.courseid")
141
            ->add_fields(
142
                "{$badgealias}.name, {$badgealias}.id, {$badgealias}.type, {$badgealias}.courseid, {$badgealias}.imagecaption"
143
            )
144
            ->add_fields(context_helper::get_preload_record_columns_sql($contextalias))
145
            ->set_is_sortable(true)
146
            ->add_callback(static function ($value, stdClass $badge): string {
147
                if ($badge->id === null) {
148
                    return '';
149
                }
150
                if ($badge->type == BADGE_TYPE_SITE) {
151
                    $context = context_system::instance();
152
                } else {
153
                    context_helper::preload_from_record($badge);
154
                    $context = context_course::instance($badge->courseid);
155
                }
156
 
157
                $badgeimage = moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', 'f2');
158
                $url = new moodle_url('/badges/overview.php', ['id' => $badge->id]);
159
                return html_writer::img($badgeimage, $badge->imagecaption) . ' ' . html_writer::link($url, $badge->name);
160
            });
161
 
1 efrain 162
        // Description (note, this column contains plaintext so requires no post-processing).
163
        $columns[] = (new column(
164
            'description',
165
            new lang_string('description', 'core_badges'),
166
            $this->get_entity_name()
167
        ))
168
            ->add_joins($this->get_joins())
169
            ->set_type(column::TYPE_LONGTEXT)
1441 ariadna 170
            ->add_field("{$badgealias}.description")
171
            ->set_is_sortable(true);
1 efrain 172
 
173
        // Criteria.
174
        $columns[] = (new column(
175
            'criteria',
176
            new lang_string('bcriteria', 'core_badges'),
177
            $this->get_entity_name()
178
        ))
179
            ->add_joins($this->get_joins())
180
            ->set_type(column::TYPE_TEXT)
181
            ->add_field("{$badgealias}.id")
182
            ->set_disabled_aggregation_all()
183
            ->add_callback(static function($badgeid): string {
184
                global $PAGE;
185
                if (!$badgeid) {
186
                    return '';
187
                }
188
                $badge = new \core_badges\badge($badgeid);
1441 ariadna 189
                if (empty($badge->criteria)) {
190
                    return '<span class="no-criteria-set d-none"></span>';
191
                }
1 efrain 192
                $renderer = $PAGE->get_renderer('core_badges');
193
                return $renderer->print_badge_criteria($badge, 'short');
194
            });
195
 
196
        // Image.
197
        $columns[] = (new column(
198
            'image',
199
            new lang_string('badgeimage', 'core_badges'),
200
            $this->get_entity_name()
201
        ))
202
            ->add_joins($this->get_joins())
203
            ->add_join("LEFT JOIN {context} {$contextalias}
204
                    ON {$contextalias}.contextlevel = " . CONTEXT_COURSE . "
205
                   AND {$contextalias}.instanceid = {$badgealias}.courseid")
1441 ariadna 206
            ->add_fields("{$badgealias}.id, {$badgealias}.type, {$badgealias}.courseid, {$badgealias}.imagecaption")
1 efrain 207
            ->add_fields(context_helper::get_preload_record_columns_sql($contextalias))
1441 ariadna 208
            ->add_callback(static function($value, stdClass $badge): string {
209
                if ($badge->id === null) {
1 efrain 210
                    return '';
211
                }
212
                if ($badge->type == BADGE_TYPE_SITE) {
213
                    $context = context_system::instance();
214
                } else {
215
                    context_helper::preload_from_record($badge);
216
                    $context = context_course::instance($badge->courseid);
217
                }
218
 
1441 ariadna 219
                $badgeimage = moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', 'f2');
1 efrain 220
                return html_writer::img($badgeimage, $badge->imagecaption);
221
            });
222
 
223
        // Language.
224
        $columns[] = (new column(
225
            'language',
226
            new lang_string('language'),
227
            $this->get_entity_name()
228
        ))
229
            ->add_joins($this->get_joins())
230
            ->set_type(column::TYPE_TEXT)
231
            ->add_field("{$badgealias}.language")
232
            ->set_is_sortable(true)
233
            ->add_callback(static function($language): string {
234
                $languages = get_string_manager()->get_list_of_languages();
1441 ariadna 235
                return (string) ($languages[$language] ?? $language);
1 efrain 236
            });
237
 
238
        // Version.
239
        $columns[] = (new column(
240
            'version',
241
            new lang_string('version', 'core_badges'),
242
            $this->get_entity_name()
243
        ))
244
            ->add_joins($this->get_joins())
245
            ->set_type(column::TYPE_TEXT)
246
            ->add_field("{$badgealias}.version")
247
            ->set_is_sortable(true);
248
 
249
        // Status.
250
        $columns[] = (new column(
251
            'status',
252
            new lang_string('status', 'core_badges'),
253
            $this->get_entity_name()
254
        ))
255
            ->add_joins($this->get_joins())
256
            ->set_type(column::TYPE_TEXT)
257
            ->add_field("{$badgealias}.status")
258
            ->set_is_sortable(true)
259
            ->add_callback(static function($status): string {
260
                if ($status === null) {
261
                    return '';
262
                }
263
 
264
                return get_string("badgestatus_{$status}", 'core_badges');
265
            });
266
 
267
        // Expiry date/period.
268
        $columns[] = (new column(
269
            'expiry',
270
            new lang_string('expirydate', 'core_badges'),
271
            $this->get_entity_name()
272
        ))
273
            ->add_joins($this->get_joins())
274
            ->set_type(column::TYPE_TIMESTAMP)
275
            ->add_fields("{$badgealias}.expiredate, {$badgealias}.expireperiod, {$badgealias}.id")
276
            ->set_is_sortable(true, ["{$badgealias}.expiredate", "{$badgealias}.expireperiod"])
277
            ->set_disabled_aggregation_all()
278
            ->add_callback(static function(?int $expiredate, stdClass $badge): string {
279
                if (!$badge->id) {
280
                    return '';
281
                } else if ($expiredate) {
282
                    return userdate($expiredate);
283
                } else if ($badge->expireperiod) {
284
                    return format_time($badge->expireperiod);
285
                } else {
286
                    return get_string('never', 'core_badges');
287
                }
288
            });
289
 
290
        return $columns;
291
    }
292
 
293
    /**
294
     * Return list of all available filters
295
     *
296
     * @return filter[]
297
     */
298
    protected function get_all_filters(): array {
299
        $badgealias = $this->get_table_alias('badge');
300
 
301
        // Name.
302
        $filters[] = (new filter(
303
            text::class,
304
            'name',
305
            new lang_string('name'),
306
            $this->get_entity_name(),
307
            "{$badgealias}.name"
308
        ))
309
            ->add_joins($this->get_joins());
310
 
311
        // Version.
312
        $filters[] = (new filter(
313
            text::class,
314
            'version',
315
            new lang_string('version', 'core_badges'),
316
            $this->get_entity_name(),
317
            "{$badgealias}.version"
318
        ))
319
            ->add_joins($this->get_joins());
320
 
321
        // Status.
322
        $filters[] = (new filter(
323
            select::class,
324
            'status',
325
            new lang_string('status', 'core_badges'),
326
            $this->get_entity_name(),
327
            "{$badgealias}.status"
328
        ))
329
            ->add_joins($this->get_joins())
330
            ->set_options([
331
                BADGE_STATUS_INACTIVE => new lang_string('badgestatus_0', 'core_badges'),
332
                BADGE_STATUS_ACTIVE => new lang_string('badgestatus_1', 'core_badges'),
333
                BADGE_STATUS_INACTIVE_LOCKED => new lang_string('badgestatus_2', 'core_badges'),
334
                BADGE_STATUS_ACTIVE_LOCKED => new lang_string('badgestatus_3', 'core_badges'),
335
                BADGE_STATUS_ARCHIVED => new lang_string('badgestatus_4', 'core_badges'),
336
            ]);
337
 
338
        // Expiry date/period.
1441 ariadna 339
        $paramtime = database::generate_param_name();
1 efrain 340
        $filters[] = (new filter(
341
            date::class,
342
            'expiry',
343
            new lang_string('expirydate', 'core_badges'),
344
            $this->get_entity_name(),
345
            "CASE WHEN {$badgealias}.expiredate IS NULL AND {$badgealias}.expireperiod IS NULL
1441 ariadna 346
                  THEN " . SQL_INT_MAX . "
1 efrain 347
                  ELSE COALESCE({$badgealias}.expiredate, {$badgealias}.expireperiod + :{$paramtime})
348
             END",
1441 ariadna 349
            [$paramtime => time()]
1 efrain 350
        ))
351
            ->add_joins($this->get_joins())
352
            ->set_limited_operators([
353
                date::DATE_ANY,
354
                date::DATE_RANGE,
355
                date::DATE_LAST,
356
                date::DATE_CURRENT,
357
                date::DATE_NEXT,
358
                date::DATE_PAST,
359
                date::DATE_FUTURE,
360
            ]);
361
 
362
        // Type.
363
        $filters[] = (new filter(
364
            select::class,
365
            'type',
366
            new lang_string('type', 'core_badges'),
367
            $this->get_entity_name(),
368
            "{$badgealias}.type"
369
        ))
370
            ->add_joins($this->get_joins())
371
            ->set_options([
372
                BADGE_TYPE_SITE => new lang_string('site'),
373
                BADGE_TYPE_COURSE => new lang_string('course'),
374
            ]);
375
 
376
        return $filters;
377
    }
378
 
379
    /**
380
     * Return joins necessary for retrieving tags
381
     *
382
     * @return string[]
383
     */
384
    public function get_tag_joins(): array {
385
        return $this->get_tag_joins_for_entity('core_badges', 'badge', $this->get_table_alias('badge') . '.id');
386
    }
387
}