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 |
}
|