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; 20 21 use action_menu_filler; 22 use coding_exception; 23 use html_writer; 24 use stdClass; 25 use core\output\checkbox_toggleall; 26 use core_reportbuilder\local\models\report; 27 use core_reportbuilder\local\report\action; 28 use core_reportbuilder\local\report\base; 29 use core_reportbuilder\local\report\column; 30 31 /** 32 * Base class for system reports 33 * 34 * @package core_reportbuilder 35 * @copyright 2020 Paul Holden <paulh@moodle.com> 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 abstract class system_report extends base { 39 40 /** @var array $parameters */ 41 private $parameters; 42 43 /** @var string[] $basefields List of base fields */ 44 private $basefields = []; 45 46 /** @var callable $checkboxcallback */ 47 private $checkboxcallback = null; 48 49 /** @var bool $filterformdefault Whether to use the default filters form */ 50 private $filterformdefault = true; 51 52 /** @var action|action_menu_filler[] $actions */ 53 private $actions = []; 54 55 /** @var column $initialsortcolumn */ 56 private $initialsortcolumn; 57 58 /** @var int $initialsortdirection */ 59 private $initialsortdirection; 60 61 /** 62 * System report constructor. 63 * 64 * @param report $report 65 * @param array $parameters 66 */ 67 final public function __construct(report $report, array $parameters) { 68 $this->parameters = $parameters; 69 70 parent::__construct($report); 71 } 72 73 /** 74 * Validates access to view this report 75 * 76 * This is necessary to implement independently of the page that would typically embed the report because 77 * subsequent pages are requested via AJAX requests, and access should be validated each time 78 * 79 * @return bool 80 */ 81 abstract protected function can_view(): bool; 82 83 /** 84 * Validate access to the report 85 * 86 * @throws report_access_exception 87 */ 88 final public function require_can_view(): void { 89 if (!$this->can_view()) { 90 throw new report_access_exception(); 91 } 92 } 93 94 /** 95 * Report validation 96 * 97 * @throws report_access_exception If user cannot access the report 98 * @throws coding_exception If no default column are specified 99 */ 100 protected function validate(): void { 101 parent::validate(); 102 103 $this->require_can_view(); 104 105 // Ensure the report has some default columns specified. 106 if (empty($this->get_columns())) { 107 throw new coding_exception('No columns added'); 108 } 109 } 110 111 /** 112 * Add list of fields that have to be always included in SQL query for actions and row classes 113 * 114 * Base fields are only available in system reports because they are not compatible with aggregation 115 * 116 * @param string $sql SQL clause for the list of fields that only uses main table or base joins 117 */ 118 final protected function add_base_fields(string $sql): void { 119 $this->basefields[] = $sql; 120 } 121 122 /** 123 * Return report base fields 124 * 125 * @return array 126 */ 127 final public function get_base_fields(): array { 128 return $this->basefields; 129 } 130 131 /** 132 * Define toggle all checkbox for the report, required row data should be defined by calling {@see add_base_fields} 133 * 134 * @param callable $callback Callback to return value/label for each checkbox, implementing the following signature: 135 * function(stdClass $row): array containing value/label pair 136 */ 137 final protected function set_checkbox_toggleall(callable $callback): void { 138 $this->checkboxcallback = $callback; 139 } 140 141 /** 142 * Return instance of toggle all checkbox, if previously defined by {@see set_checkbox_toggleall} 143 * 144 * @param bool $ismaster 145 * @param stdClass|null $row 146 * @return checkbox_toggleall|null 147 */ 148 final public function get_checkbox_toggleall(bool $ismaster, ?stdClass $row = null): ?checkbox_toggleall { 149 if (!is_callable($this->checkboxcallback)) { 150 return null; 151 } 152 153 // Generic content for the master checkbox, execute callback for those belonging to each row. 154 if ($ismaster) { 155 $value = ''; 156 $label = get_string('selectall'); 157 } else { 158 [$value, $label] = ($this->checkboxcallback)($row); 159 } 160 161 return new checkbox_toggleall('report-select-all', $ismaster, [ 162 'id' => html_writer::random_id(), 163 'name' => 'report-select-row[]', 164 'value' => $value, 165 'label' => $label, 166 'labelclasses' => 'accesshide', 167 ]); 168 } 169 170 /** 171 * Override whether to use the default system report filters form, for instance this can be disabled if the UI requires 172 * it's own custom filter management form for a specific report 173 * 174 * @param bool $filterformdefault 175 */ 176 final public function set_filter_form_default(bool $filterformdefault = true): void { 177 $this->filterformdefault = $filterformdefault; 178 } 179 180 /** 181 * Whether to use the default filters form 182 * 183 * @return bool 184 */ 185 final public function get_filter_form_default(): bool { 186 return $this->filterformdefault; 187 } 188 189 /** 190 * Adds an action to the report 191 * 192 * @param action $action 193 */ 194 final public function add_action(action $action): void { 195 $this->actions[] = $action; 196 } 197 198 /** 199 * Adds action divider to the report 200 * 201 */ 202 final public function add_action_divider(): void { 203 $divider = new action_menu_filler(); 204 // We need to set as not primary action because we just need add an action divider, not a new action item. 205 $divider->primary = false; 206 $this->actions[] = $divider; 207 } 208 209 /** 210 * Whether report has any actions 211 * 212 * @return bool 213 */ 214 final public function has_actions(): bool { 215 return !empty($this->actions); 216 } 217 218 /** 219 * Return report actions 220 * 221 * @return action|action_menu_filler[] 222 */ 223 final public function get_actions(): array { 224 return $this->actions; 225 } 226 227 /** 228 * Set all report parameters 229 * 230 * @param array $parameters 231 */ 232 final public function set_parameters(array $parameters): void { 233 $this->parameters = $parameters; 234 } 235 236 /** 237 * Return all report parameters 238 * 239 * @return array 240 */ 241 final public function get_parameters(): array { 242 return $this->parameters; 243 } 244 245 /** 246 * Return specific report parameter 247 * 248 * @param string $param 249 * @param mixed $default 250 * @param string $type 251 * @return mixed 252 */ 253 final public function get_parameter(string $param, $default, string $type) { 254 if (!array_key_exists($param, $this->parameters)) { 255 return $default; 256 } 257 258 return clean_param($this->parameters[$param], $type); 259 } 260 261 /** 262 * Output the report 263 * 264 * @uses \core_reportbuilder\output\renderer::render_system_report() 265 * 266 * @return string 267 */ 268 final public function output(): string { 269 global $PAGE; 270 271 /** @var \core_reportbuilder\output\renderer $renderer */ 272 $renderer = $PAGE->get_renderer('core_reportbuilder'); 273 $report = new \core_reportbuilder\output\system_report($this->get_report_persistent(), $this, $this->parameters); 274 275 return $renderer->render($report); 276 } 277 278 /** 279 * CSS classes to add to the row. Can be overridden by system reports do define class to be added to output according to 280 * content of each row 281 * 282 * @param stdClass $row 283 * @return string 284 */ 285 public function get_row_class(stdClass $row): string { 286 return ''; 287 } 288 289 /** 290 * Called before rendering each row. Can be overridden to pre-fetch/create objects and store them in the class, which can 291 * later be used in column and action callbacks 292 * 293 * @param stdClass $row 294 */ 295 public function row_callback(stdClass $row): void { 296 return; 297 } 298 299 /** 300 * Validates access to download this report. 301 * 302 * @return bool 303 */ 304 final public function can_be_downloaded(): bool { 305 return $this->can_view() && $this->is_downloadable(); 306 } 307 308 /** 309 * Return list of column names that will be excluded when table is downloaded. Extending classes should override this method 310 * as appropriate 311 * 312 * @return string[] Array of column unique identifiers 313 */ 314 public function get_exclude_columns_for_download(): array { 315 return []; 316 } 317 318 /** 319 * Set initial sort column and sort direction for the report 320 * 321 * @param string $uniqueidentifier 322 * @param int $sortdirection One of SORT_ASC or SORT_DESC 323 * @throws coding_exception 324 */ 325 public function set_initial_sort_column(string $uniqueidentifier, int $sortdirection): void { 326 if (!$sortcolumn = $this->get_column($uniqueidentifier)) { 327 throw new coding_exception('Unknown column identifier', $uniqueidentifier); 328 } 329 330 $this->initialsortcolumn = $sortcolumn; 331 $this->initialsortdirection = $sortdirection; 332 } 333 334 /** 335 * Get initial sort column 336 * 337 * @return column|null 338 */ 339 public function get_initial_sort_column(): ?column { 340 return $this->initialsortcolumn; 341 } 342 343 /** 344 * Get initial sort column direction 345 * 346 * @return int 347 */ 348 public function get_initial_sort_direction(): int { 349 return $this->initialsortdirection; 350 } 351 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body