Differences Between: [Versions 400 and 403] [Versions 401 and 403]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body