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