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\audiences;
20
 
21
use core_plugin_manager;
22
use MoodleQuickForm;
23
use stdClass;
24
use core\output\notification;
25
use core_reportbuilder\local\helpers\database;
26
use core_reportbuilder\local\models\audience;
27
use core_reportbuilder\report_access_exception;
28
 
29
/**
30
 * Audience base class
31
 *
32
 * @package     core_reportbuilder
33
 * @copyright   2021 David Matamoros <davidmc@moodle.com>
34
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
abstract class base {
37
 
38
    /** @var int Maximim number of multi-select elements to show in description, before appending "plus X more" */
39
    private const MULTI_SELECT_LIMIT = 5;
40
 
41
    /** @var audience The persistent object associated with this audience */
42
    protected $audience;
43
 
44
    /**
45
     * Protected constructor, please use the static instance method.
46
     */
47
    protected function __construct() {
48
    }
49
 
50
    /**
51
     * Loads an existing instance of audience with persistent
52
     *
53
     * @param int $id
54
     * @param null|stdClass $record
55
     * @return self|null
56
     */
57
    final public static function instance(int $id = 0, ?stdClass $record = null): ?self {
58
        $persistent = new audience($id, $record);
59
        // Needed for get_audience_types() method.
60
        if (!$classname = $persistent->get('classname')) {
61
            // Use the called class name.
62
            $classname = get_called_class();
63
            $persistent->set('classname', $classname);
64
        }
65
 
66
        // Check if audience type class still exists in the system.
67
        if (!class_exists($classname)) {
68
            return null;
69
        }
70
 
71
        $instance = new $classname();
72
        $instance->audience = $persistent;
73
        return $instance;
74
    }
75
 
76
    /**
77
     * Creates a new audience and saves it to database
78
     *
79
     * @param int $reportid
80
     * @param array $configdata
81
     * @return self
82
     */
83
    final public static function create(int $reportid, array $configdata): self {
84
        $record = new stdClass();
85
        $record->reportid = $reportid;
86
        $record->classname = get_called_class();
87
        $record->configdata = json_encode($configdata);
88
        $instance = self::instance(0, $record);
89
        $instance->audience->save();
90
        return $instance;
91
    }
92
 
93
    /**
94
     * Return display name of the component the audience belongs to
95
     *
96
     * @return string
97
     */
98
    final public function get_component_displayname(): string {
99
        [$component] = explode('\\', get_class($this));
100
 
101
        if ($plugininfo = core_plugin_manager::instance()->get_plugin_info($component)) {
102
            return $plugininfo->displayname;
103
        }
104
 
105
        // Return generic site text for those audiences belonging to core subsystems.
106
        return get_string('site');
107
    }
108
 
109
    /**
110
     * Helps to build SQL to retrieve users that matches the current audience
111
     *
112
     * Implementations must use {@see database::generate_alias} and {@see database::generate_param_name} for table/column
113
     * aliases and parameter names
114
     *
115
     * @param string $usertablealias
116
     * @return array array of three elements [$join, $where, $params]
117
     */
118
    abstract public function get_sql(string $usertablealias): array;
119
 
120
    /**
121
     * Returns string for audience category.
122
     *
123
     * @return string
124
     *
125
     * @deprecated since Moodle 4.2 - please do not use this function any more, {@see get_component_displayname}
126
     */
127
    final public function get_category(): string {
128
        debugging('The function ' . __FUNCTION__ . '() is deprecated, please do not use it any more. ' .
129
            'See class \'get_component_displayname\' method for replacement', DEBUG_DEVELOPER);
130
 
131
        return $this->get_component_displayname();
132
    }
133
 
134
    /**
135
     * If the current user is able to add this audience type
136
     *
137
     * @return bool
138
     */
139
    abstract public function user_can_add(): bool;
140
 
141
    /**
142
     * If the current user is able to edit this audience type
143
     *
144
     * @return bool
145
     */
146
    abstract public function user_can_edit(): bool;
147
 
148
    /**
149
     * If the current user is able to use this audience type
150
     *
151
     * This method needs to return true if audience type is available to user for
152
     * reasons other than permission check, which is done in {@see user_can_add}.
153
     * (e.g. user can add cohort audience type only if there is at least one cohort
154
     * they can access).
155
     *
156
     * @return bool
157
     */
158
    public function is_available(): bool {
159
        return true;
160
    }
161
 
162
    /**
163
     * Return user friendly name of the audience type
164
     *
165
     * @return string
166
     */
167
    abstract public function get_name(): string;
168
 
169
    /**
170
     * Return the description of this audience type
171
     *
172
     * @return string
173
     */
174
    abstract public function get_description(): string;
175
 
176
    /**
177
     * Helper to format descriptions for audience types that may contain many selected elements, limiting number show according
178
     * to {@see MULTI_SELECT_LIMIT} constant value
179
     *
180
     * @param array $elements
181
     * @return string
182
     */
183
    protected function format_description_for_multiselect(array $elements): string {
184
        global $OUTPUT;
185
 
186
        // Warn user if there are no elements (because they may no longer exist).
187
        $elementcount = count($elements);
188
        if ($elementcount === 0) {
189
            $notification = new notification(get_string('nothingtodisplay'), notification::NOTIFY_WARNING);
190
            return $OUTPUT->render($notification);
191
        }
192
 
193
        $listseparator = get_string('listsep', 'langconfig') . ' ';
194
        if ($elementcount > self::MULTI_SELECT_LIMIT) {
195
            $elements = array_slice($elements, 0, self::MULTI_SELECT_LIMIT);
196
 
197
            // Append overflow element.
198
            $elementoverflow = $elementcount - self::MULTI_SELECT_LIMIT;
199
            $params = [
200
                'elements' => implode($listseparator, $elements),
201
                'morecount' => $elementoverflow,
202
            ];
203
            $description = get_string('audiencemultiselectpostfix', 'core_reportbuilder', $params);
204
        } else {
205
            $description = implode($listseparator, $elements);
206
        }
207
 
208
        return $description;
209
    }
210
 
211
    /**
212
     * Adds audience-specific form elements
213
     *
214
     * @param MoodleQuickForm $mform The form to add elements to
215
     */
216
    abstract public function get_config_form(MoodleQuickForm $mform): void;
217
 
218
    /**
219
     * Validates the configform of the condition.
220
     *
221
     * @param array $data Data from the form
222
     * @return array Array with errors for each element
223
     */
224
    public function validate_config_form(array $data): array {
225
        return [];
226
    }
227
 
228
    /**
229
     * Returns configdata as an associative array
230
     *
231
     * @return array decoded configdata
232
     */
233
    final public function get_configdata(): array {
234
        return json_decode($this->audience->get('configdata'), true);
235
    }
236
 
237
    /**
238
     * Update configdata in audience persistent
239
     *
240
     * @param array $configdata
241
     */
242
    final public function update_configdata(array $configdata): void {
243
        $this->audience->set('configdata', json_encode($configdata));
244
        $this->audience->save();
245
    }
246
 
247
    /**
248
     * Returns $configdata from form data suitable for use in DB record.
249
     *
250
     * @param stdClass $data data obtained from $mform->get_data()
251
     * @return array $configdata
252
     */
253
    final public static function retrieve_configdata(stdClass $data): array {
254
        $configdata = (array) $data;
255
        $invalidkeys = array_fill_keys(['id', 'reportid', 'classname'], '');
256
        return array_diff_key($configdata, $invalidkeys);
257
    }
258
 
259
    /**
260
     * Return audience persistent.
261
     *
262
     * @return audience
263
     */
264
    public function get_persistent(): audience {
265
        return $this->audience;
266
    }
267
 
268
    /**
269
     * Require current user is able to add this audience type
270
     *
271
     * @throws report_access_exception
272
     */
273
    final public function require_user_can_add(): void {
274
        if (!$this->user_can_add()) {
275
            throw new report_access_exception('errorreportedit');
276
        }
277
    }
278
 
279
    /**
280
     * Require current user is able to edit this audience type
281
     *
282
     * @throws report_access_exception
283
     */
284
    final public function require_user_can_edit(): void {
285
        if (!$this->user_can_edit()) {
286
            throw new report_access_exception('errorreportedit');
287
        }
288
    }
289
}