Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 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\helpers; 20 21 use stdClass; 22 use invalid_parameter_exception; 23 use core\persistent; 24 use core_reportbuilder\datasource; 25 use core_reportbuilder\manager; 26 use core_reportbuilder\local\models\column; 27 use core_reportbuilder\local\models\filter; 28 use core_reportbuilder\local\models\report as report_model; 29 30 /** 31 * Helper class for manipulating custom reports and their elements (columns, filters, conditions, etc) 32 * 33 * @package core_reportbuilder 34 * @copyright 2021 Paul Holden <paulh@moodle.com> 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class report { 38 39 /** 40 * Create custom report 41 * 42 * @param stdClass $data 43 * @param bool $default If $default is set to true it will populate report with default layout as defined by the selected 44 * source. These include pre-defined columns, filters and conditions. 45 * @return report_model 46 */ 47 public static function create_report(stdClass $data, bool $default = true): report_model { 48 $data->name = trim($data->name); 49 $data->type = datasource::TYPE_CUSTOM_REPORT; 50 51 $reportpersistent = manager::create_report_persistent($data); 52 53 // Add datasource default columns, filters and conditions to the report. 54 if ($default) { 55 $source = $reportpersistent->get('source'); 56 /** @var datasource $datasource */ 57 $datasource = new $source($reportpersistent, []); 58 $datasource->add_default_columns(); 59 $datasource->add_default_filters(); 60 $datasource->add_default_conditions(); 61 } 62 63 return $reportpersistent; 64 } 65 66 /** 67 * Update custom report 68 * 69 * @param stdClass $data 70 * @return report_model 71 */ 72 public static function update_report(stdClass $data): report_model { 73 $report = report_model::get_record(['id' => $data->id, 'type' => datasource::TYPE_CUSTOM_REPORT]); 74 if ($report === false) { 75 throw new invalid_parameter_exception('Invalid report'); 76 } 77 78 $report->set_many([ 79 'name' => trim($data->name), 80 'uniquerows' => $data->uniquerows, 81 ])->update(); 82 83 return $report; 84 } 85 86 /** 87 * Delete custom report 88 * 89 * @param int $reportid 90 * @return bool 91 * @throws invalid_parameter_exception 92 */ 93 public static function delete_report(int $reportid): bool { 94 $report = report_model::get_record(['id' => $reportid, 'type' => datasource::TYPE_CUSTOM_REPORT]); 95 if ($report === false) { 96 throw new invalid_parameter_exception('Invalid report'); 97 } 98 99 return $report->delete(); 100 } 101 102 /** 103 * Add given column to report 104 * 105 * @param int $reportid 106 * @param string $uniqueidentifier 107 * @return column 108 * @throws invalid_parameter_exception 109 */ 110 public static function add_report_column(int $reportid, string $uniqueidentifier): column { 111 $report = manager::get_report_from_id($reportid); 112 113 // Ensure column is available. 114 if (!array_key_exists($uniqueidentifier, $report->get_columns())) { 115 throw new invalid_parameter_exception('Invalid column'); 116 } 117 118 $column = new column(0, (object) [ 119 'reportid' => $reportid, 120 'uniqueidentifier' => $uniqueidentifier, 121 'columnorder' => column::get_max_columnorder($reportid, 'columnorder') + 1, 122 'sortorder' => column::get_max_columnorder($reportid, 'sortorder') + 1, 123 ]); 124 125 return $column->create(); 126 } 127 128 /** 129 * Delete given column from report 130 * 131 * @param int $reportid 132 * @param int $columnid 133 * @return bool 134 * @throws invalid_parameter_exception 135 */ 136 public static function delete_report_column(int $reportid, int $columnid): bool { 137 global $DB; 138 139 $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]); 140 if ($column === false) { 141 throw new invalid_parameter_exception('Invalid column'); 142 } 143 144 // After deletion, re-index remaining report columns. 145 if ($result = $column->delete()) { 146 $sqlupdateorder = ' 147 UPDATE {' . column::TABLE . '} 148 SET columnorder = columnorder - 1 149 WHERE reportid = :reportid 150 AND columnorder > :columnorder'; 151 152 $DB->execute($sqlupdateorder, ['reportid' => $reportid, 'columnorder' => $column->get('columnorder')]); 153 } 154 155 return $result; 156 } 157 158 /** 159 * Re-order given column within a report 160 * 161 * @param int $reportid 162 * @param int $columnid 163 * @param int $position 164 * @return bool 165 * @throws invalid_parameter_exception 166 */ 167 public static function reorder_report_column(int $reportid, int $columnid, int $position): bool { 168 $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]); 169 if ($column === false) { 170 throw new invalid_parameter_exception('Invalid column'); 171 } 172 173 // Get the rest of the report columns, excluding the one we are moving. 174 $columns = column::get_records_select('reportid = :reportid AND id <> :id', [ 175 'reportid' => $reportid, 176 'id' => $columnid, 177 ], 'columnorder'); 178 179 return static::reorder_persistents_by_field($column, $columns, $position, 'columnorder'); 180 } 181 182 /** 183 * Re-order given column sorting within a report 184 * 185 * @param int $reportid 186 * @param int $columnid 187 * @param int $position 188 * @return bool 189 * @throws invalid_parameter_exception 190 */ 191 public static function reorder_report_column_sorting(int $reportid, int $columnid, int $position): bool { 192 $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]); 193 if ($column === false) { 194 throw new invalid_parameter_exception('Invalid column'); 195 } 196 197 // Get the rest of the report columns, excluding the one we are moving. 198 $columns = column::get_records_select('reportid = :reportid AND id <> :id', [ 199 'reportid' => $reportid, 200 'id' => $columnid, 201 ], 'sortorder'); 202 203 return static::reorder_persistents_by_field($column, $columns, $position, 'sortorder'); 204 } 205 206 /** 207 * Toggle sorting options for given column within a report 208 * 209 * @param int $reportid 210 * @param int $columnid 211 * @param bool $enabled 212 * @param int $direction 213 * @return bool 214 * @throws invalid_parameter_exception 215 */ 216 public static function toggle_report_column_sorting(int $reportid, int $columnid, bool $enabled, 217 int $direction = SORT_ASC): bool { 218 219 $column = column::get_record(['id' => $columnid, 'reportid' => $reportid]); 220 if ($column === false) { 221 throw new invalid_parameter_exception('Invalid column'); 222 } 223 224 return $column->set_many([ 225 'sortenabled' => $enabled, 226 'sortdirection' => $direction, 227 ])->update(); 228 } 229 230 /** 231 * Add given condition to report 232 * 233 * @param int $reportid 234 * @param string $uniqueidentifier 235 * @return filter 236 * @throws invalid_parameter_exception 237 */ 238 public static function add_report_condition(int $reportid, string $uniqueidentifier): filter { 239 $report = manager::get_report_from_id($reportid); 240 241 // Ensure condition is available. 242 if (!array_key_exists($uniqueidentifier, $report->get_conditions())) { 243 throw new invalid_parameter_exception('Invalid condition'); 244 } 245 246 // Ensure condition wasn't already added. 247 if (array_key_exists($uniqueidentifier, $report->get_active_conditions())) { 248 throw new invalid_parameter_exception('Duplicate condition'); 249 } 250 251 $condition = new filter(0, (object) [ 252 'reportid' => $reportid, 253 'uniqueidentifier' => $uniqueidentifier, 254 'iscondition' => true, 255 'filterorder' => filter::get_max_filterorder($reportid, true) + 1, 256 ]); 257 258 return $condition->create(); 259 } 260 261 /** 262 * Delete given condition from report 263 * 264 * @param int $reportid 265 * @param int $conditionid 266 * @return bool 267 * @throws invalid_parameter_exception 268 */ 269 public static function delete_report_condition(int $reportid, int $conditionid): bool { 270 global $DB; 271 272 $condition = filter::get_condition_record($reportid, $conditionid); 273 if ($condition === false) { 274 throw new invalid_parameter_exception('Invalid condition'); 275 } 276 277 // After deletion, re-index remaining report conditions. 278 if ($result = $condition->delete()) { 279 $sqlupdateorder = ' 280 UPDATE {' . filter::TABLE . '} 281 SET filterorder = filterorder - 1 282 WHERE reportid = :reportid 283 AND filterorder > :filterorder 284 AND iscondition = 1'; 285 286 $DB->execute($sqlupdateorder, ['reportid' => $reportid, 'filterorder' => $condition->get('filterorder')]); 287 } 288 289 return $result; 290 } 291 292 /** 293 * Re-order given condition within a report 294 * 295 * @param int $reportid 296 * @param int $conditionid 297 * @param int $position 298 * @return bool 299 * @throws invalid_parameter_exception 300 */ 301 public static function reorder_report_condition(int $reportid, int $conditionid, int $position): bool { 302 $condition = filter::get_condition_record($reportid, $conditionid); 303 if ($condition === false) { 304 throw new invalid_parameter_exception('Invalid condition'); 305 } 306 307 // Get the rest of the report conditions, excluding the one we are moving. 308 $conditions = filter::get_records_select('reportid = :reportid AND iscondition = 1 AND id <> :id', [ 309 'reportid' => $reportid, 310 'id' => $conditionid, 311 ], 'filterorder'); 312 313 return static::reorder_persistents_by_field($condition, $conditions, $position, 'filterorder'); 314 } 315 316 /** 317 * Add given filter to report 318 * 319 * @param int $reportid 320 * @param string $uniqueidentifier 321 * @return filter 322 * @throws invalid_parameter_exception 323 */ 324 public static function add_report_filter(int $reportid, string $uniqueidentifier): filter { 325 $report = manager::get_report_from_id($reportid); 326 327 // Ensure filter is available. 328 if (!array_key_exists($uniqueidentifier, $report->get_filters())) { 329 throw new invalid_parameter_exception('Invalid filter'); 330 } 331 332 // Ensure filter wasn't already added. 333 if (array_key_exists($uniqueidentifier, $report->get_active_filters())) { 334 throw new invalid_parameter_exception('Duplicate filter'); 335 } 336 337 $filter = new filter(0, (object) [ 338 'reportid' => $reportid, 339 'uniqueidentifier' => $uniqueidentifier, 340 'filterorder' => filter::get_max_filterorder($reportid) + 1, 341 ]); 342 343 return $filter->create(); 344 } 345 346 /** 347 * Delete given filter from report 348 * 349 * @param int $reportid 350 * @param int $filterid 351 * @return bool 352 * @throws invalid_parameter_exception 353 */ 354 public static function delete_report_filter(int $reportid, int $filterid): bool { 355 global $DB; 356 357 $filter = filter::get_filter_record($reportid, $filterid); 358 if ($filter === false) { 359 throw new invalid_parameter_exception('Invalid filter'); 360 } 361 362 // After deletion, re-index remaining report filters. 363 if ($result = $filter->delete()) { 364 $sqlupdateorder = ' 365 UPDATE {' . filter::TABLE . '} 366 SET filterorder = filterorder - 1 367 WHERE reportid = :reportid 368 AND filterorder > :filterorder 369 AND iscondition = 0'; 370 371 $DB->execute($sqlupdateorder, ['reportid' => $reportid, 'filterorder' => $filter->get('filterorder')]); 372 } 373 374 return $result; 375 } 376 377 /** 378 * Re-order given filter within a report 379 * 380 * @param int $reportid 381 * @param int $filterid 382 * @param int $position 383 * @return bool 384 * @throws invalid_parameter_exception 385 */ 386 public static function reorder_report_filter(int $reportid, int $filterid, int $position): bool { 387 $filter = filter::get_filter_record($reportid, $filterid); 388 if ($filter === false) { 389 throw new invalid_parameter_exception('Invalid filter'); 390 } 391 392 // Get the rest of the report filters, excluding the one we are moving. 393 $filters = filter::get_records_select('reportid = :reportid AND iscondition = 0 AND id <> :id', [ 394 'reportid' => $reportid, 395 'id' => $filterid, 396 ], 'filterorder'); 397 398 return static::reorder_persistents_by_field($filter, $filters, $position, 'filterorder'); 399 } 400 401 /** 402 * Get available columns for a given report 403 * 404 * @param report_model $persistent 405 * @return array 406 * 407 * @deprecated since Moodle 4.1 - please do not use this function any more, {@see custom_report_column_cards_exporter} 408 */ 409 public static function get_available_columns(report_model $persistent) : array { 410 debugging('The function ' . __FUNCTION__ . '() is deprecated, please do not use it any more. ' . 411 'See \'custom_report_column_cards_exporter\' class for replacement', DEBUG_DEVELOPER); 412 413 $available = []; 414 415 $report = manager::get_report_from_persistent($persistent); 416 417 // Get current report columns. 418 foreach ($report->get_columns() as $column) { 419 $entityname = $column->get_entity_name(); 420 $entitytitle = $column->get_title(); 421 if (!array_key_exists($entityname, $available)) { 422 $available[$entityname] = [ 423 'name' => (string) $report->get_entity_title($entityname), 424 'key' => $entityname, 425 'items' => [], 426 ]; 427 } 428 429 $available[$entityname]['items'][] = [ 430 'name' => $entitytitle, 431 'identifier' => $column->get_unique_identifier(), 432 'title' => get_string('addcolumn', 'core_reportbuilder', $entitytitle), 433 'action' => 'report-add-column' 434 ]; 435 } 436 437 return array_values($available); 438 } 439 440 /** 441 * Helper method for re-ordering given persistents (columns, filters, etc) 442 * 443 * @param persistent $persistent The persistent we are moving 444 * @param persistent[] $persistents The rest of the persistents 445 * @param int $position 446 * @param string $field The field we need to update 447 * @return bool 448 */ 449 private static function reorder_persistents_by_field(persistent $persistent, array $persistents, int $position, 450 string $field): bool { 451 452 // Splice into new position. 453 array_splice($persistents, $position - 1, 0, [$persistent]); 454 455 $fieldorder = 1; 456 foreach ($persistents as $persistent) { 457 $persistent->set($field, $fieldorder++) 458 ->update(); 459 } 460 461 return true; 462 } 463 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body