See Release Notes
Long Term Support Release
Differences Between: [Versions 400 and 401]
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\systemreports; 20 21 use html_writer; 22 use lang_string; 23 use moodle_url; 24 use pix_icon; 25 use stdClass; 26 use core_reportbuilder\datasource; 27 use core_reportbuilder\manager; 28 use core_reportbuilder\system_report; 29 use core_reportbuilder\local\entities\user; 30 use core_reportbuilder\local\filters\date; 31 use core_reportbuilder\local\filters\text; 32 use core_reportbuilder\local\filters\select; 33 use core_reportbuilder\local\helpers\audience; 34 use core_reportbuilder\local\helpers\format; 35 use core_reportbuilder\local\report\action; 36 use core_reportbuilder\local\report\column; 37 use core_reportbuilder\local\report\filter; 38 use core_reportbuilder\output\report_name_editable; 39 use core_reportbuilder\local\models\report; 40 use core_reportbuilder\permission; 41 42 /** 43 * Reports list 44 * 45 * @package core_reportbuilder 46 * @copyright 2021 David Matamoros <davidmc@moodle.com> 47 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 48 */ 49 class reports_list extends system_report { 50 51 /** 52 * The name of our internal report entity 53 * 54 * @return string 55 */ 56 private function get_report_entity_name(): string { 57 return 'report'; 58 } 59 60 /** 61 * Initialise the report 62 */ 63 protected function initialise(): void { 64 $this->set_main_table('reportbuilder_report', 'rb'); 65 $this->add_base_condition_simple('rb.type', self::TYPE_CUSTOM_REPORT); 66 67 // Select fields required for actions, permission checks, and row class callbacks. 68 $this->add_base_fields('rb.id, rb.name, rb.source, rb.type, rb.usercreated, rb.contextid'); 69 70 // Limit the returned list to those reports the current user can access. 71 [$where, $params] = audience::user_reports_list_access_sql('rb'); 72 $this->add_base_condition_sql($where, $params); 73 74 // Join user entity for "User modified" column. 75 $entityuser = new user(); 76 $entityuseralias = $entityuser->get_table_alias('user'); 77 78 $this->add_entity($entityuser 79 ->add_join("JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = rb.usermodified") 80 ); 81 82 // Define our internal entity for report elements. 83 $this->annotate_entity($this->get_report_entity_name(), 84 new lang_string('customreports', 'core_reportbuilder')); 85 86 $this->add_columns(); 87 $this->add_filters(); 88 $this->add_actions(); 89 90 $this->set_downloadable(false); 91 } 92 93 /** 94 * Ensure we can view the report 95 * 96 * @return bool 97 */ 98 protected function can_view(): bool { 99 return permission::can_view_reports_list(); 100 } 101 102 /** 103 * Dim the table row for invalid datasource 104 * 105 * @param stdClass $row 106 * @return string 107 */ 108 public function get_row_class(stdClass $row): string { 109 return $this->report_source_valid($row->source) ? '' : 'text-muted'; 110 } 111 112 /** 113 * Add columns to report 114 */ 115 protected function add_columns(): void { 116 $tablealias = $this->get_main_table_alias(); 117 118 // Report name column. 119 $this->add_column((new column( 120 'name', 121 new lang_string('name'), 122 $this->get_report_entity_name() 123 )) 124 ->set_type(column::TYPE_TEXT) 125 // We need enough fields to re-create the persistent and pass to the editable component. 126 ->add_fields(implode(', ', [ 127 "{$tablealias}.id", 128 "{$tablealias}.name", 129 "{$tablealias}.contextid", 130 "{$tablealias}.type", 131 "{$tablealias}.usercreated", 132 ])) 133 ->set_is_sortable(true, ["{$tablealias}.name"]) 134 ->add_callback(static function(string $value, stdClass $report): string { 135 global $PAGE; 136 137 $editable = new report_name_editable(0, new report(0, $report)); 138 return $editable->render($PAGE->get_renderer('core')); 139 }) 140 ); 141 142 // Report source column. 143 $this->add_column((new column( 144 'source', 145 new lang_string('reportsource', 'core_reportbuilder'), 146 $this->get_report_entity_name() 147 )) 148 ->set_type(column::TYPE_TEXT) 149 ->add_fields("{$tablealias}.source") 150 ->set_is_sortable(true) 151 ->add_callback(function(string $value, stdClass $row) { 152 if (!$this->report_source_valid($value)) { 153 // Add danger badge if report source is not valid (either it's missing, or has errors). 154 return html_writer::span(get_string('errorsourceinvalid', 'core_reportbuilder'), 'badge badge-danger'); 155 } 156 157 return call_user_func([$value, 'get_name']); 158 }) 159 ); 160 161 // Time created column. 162 $this->add_column((new column( 163 'timecreated', 164 new lang_string('timecreated', 'core_reportbuilder'), 165 $this->get_report_entity_name() 166 )) 167 ->set_type(column::TYPE_TIMESTAMP) 168 ->add_fields("{$tablealias}.timecreated") 169 ->set_is_sortable(true) 170 ->add_callback([format::class, 'userdate']) 171 ); 172 173 // Time modified column. 174 $this->add_column((new column( 175 'timemodified', 176 new lang_string('timemodified', 'core_reportbuilder'), 177 $this->get_report_entity_name() 178 )) 179 ->set_type(column::TYPE_TIMESTAMP) 180 ->add_fields("{$tablealias}.timemodified") 181 ->set_is_sortable(true) 182 ->add_callback([format::class, 'userdate']) 183 ); 184 185 // The user who modified the report. 186 $this->add_column_from_entity('user:fullname') 187 ->set_title(new lang_string('usermodified', 'reportbuilder')); 188 189 // Initial sorting. 190 $this->set_initial_sort_column('report:timecreated', SORT_DESC); 191 } 192 193 /** 194 * Add filters to report 195 */ 196 protected function add_filters(): void { 197 $tablealias = $this->get_main_table_alias(); 198 199 // Name filter. 200 $this->add_filter((new filter( 201 text::class, 202 'name', 203 new lang_string('name'), 204 $this->get_report_entity_name(), 205 "{$tablealias}.name" 206 ))); 207 208 // Source filter. 209 $this->add_filter((new filter( 210 select::class, 211 'source', 212 new lang_string('reportsource', 'core_reportbuilder'), 213 $this->get_report_entity_name(), 214 "{$tablealias}.source" 215 )) 216 ->set_options_callback(static function(): array { 217 return manager::get_report_datasources(); 218 }) 219 ); 220 221 // Time created filter. 222 $this->add_filter((new filter( 223 date::class, 224 'timecreated', 225 new lang_string('timecreated', 'core_reportbuilder'), 226 $this->get_report_entity_name(), 227 "{$tablealias}.timecreated" 228 )) 229 ->set_limited_operators([ 230 date::DATE_ANY, 231 date::DATE_RANGE, 232 ]) 233 ); 234 } 235 236 /** 237 * Add actions to report 238 */ 239 protected function add_actions(): void { 240 // Edit content action. 241 $this->add_action((new action( 242 new moodle_url('/reportbuilder/edit.php', ['id' => ':id']), 243 new pix_icon('t/right', ''), 244 [], 245 false, 246 new lang_string('editreportcontent', 'core_reportbuilder') 247 )) 248 ->add_callback(function(stdClass $row): bool { 249 return $this->report_source_valid($row->source) && permission::can_edit_report(new report(0, $row)); 250 }) 251 ); 252 253 // Edit details action. 254 $this->add_action((new action( 255 new moodle_url('#'), 256 new pix_icon('t/edit', ''), 257 ['data-action' => 'report-edit', 'data-report-id' => ':id'], 258 false, 259 new lang_string('editreportdetails', 'core_reportbuilder') 260 )) 261 ->add_callback(function(stdClass $row): bool { 262 return $this->report_source_valid($row->source) && permission::can_edit_report(new report(0, $row)); 263 }) 264 ); 265 266 // Preview action. 267 $this->add_action((new action( 268 new moodle_url('/reportbuilder/view.php', ['id' => ':id']), 269 new pix_icon('i/search', ''), 270 [], 271 false, 272 new lang_string('viewreport', 'core_reportbuilder') 273 )) 274 ->add_callback(function(stdClass $row): bool { 275 // We check this only to give the action to editors, because normal users can just click on the report name. 276 return $this->report_source_valid($row->source) && permission::can_edit_report(new report(0, $row)); 277 }) 278 ); 279 280 // Delete action. 281 $this->add_action((new action( 282 new moodle_url('#'), 283 new pix_icon('t/delete', ''), 284 ['data-action' => 'report-delete', 'data-report-id' => ':id', 'data-report-name' => ':name'], 285 false, 286 new lang_string('deletereport', 'core_reportbuilder') 287 )) 288 ->add_callback(function(stdClass $row): bool { 289 290 // Ensure data name attribute is properly formatted. 291 $report = new report(0, $row); 292 $row->name = $report->get_formatted_name(); 293 294 // We don't check whether report is valid to ensure editor can always delete them. 295 return permission::can_edit_report($report); 296 }) 297 ); 298 } 299 300 /** 301 * Helper to determine whether given report source is valid (it both exists, and is available) 302 * 303 * @param string $source 304 * @return bool 305 */ 306 private function report_source_valid(string $source): bool { 307 return manager::report_source_exists($source, datasource::class) && manager::report_source_available($source); 308 } 309 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body