Differences Between: [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_files\reportbuilder\local\entities; 20 21 use context; 22 use context_helper; 23 use lang_string; 24 use license_manager; 25 use html_writer; 26 use stdClass; 27 use core_reportbuilder\local\entities\base; 28 use core_reportbuilder\local\helpers\format; 29 use core_reportbuilder\local\filters\{boolean_select, date, number, select, text}; 30 use core_reportbuilder\local\report\{column, filter}; 31 32 /** 33 * File entity 34 * 35 * @package core_files 36 * @copyright 2022 Paul Holden <paulh@moodle.com> 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class file extends base { 40 41 /** 42 * Database tables that this entity uses and their default aliases 43 * 44 * @return array 45 */ 46 protected function get_default_table_aliases(): array { 47 return [ 48 'files' => 'f', 49 'context' => 'fctx', 50 ]; 51 } 52 53 /** 54 * The default title for this entity 55 * 56 * @return lang_string 57 */ 58 protected function get_default_entity_title(): lang_string { 59 return new lang_string('file'); 60 } 61 62 /** 63 * Initialise the entity 64 * 65 * @return base 66 */ 67 public function initialise(): base { 68 $columns = $this->get_all_columns(); 69 foreach ($columns as $column) { 70 $this->add_column($column); 71 } 72 73 // All the filters defined by the entity can also be used as conditions. 74 $filters = $this->get_all_filters(); 75 foreach ($filters as $filter) { 76 $this 77 ->add_filter($filter) 78 ->add_condition($filter); 79 } 80 81 return $this; 82 } 83 84 /** 85 * Returns list of all available columns 86 * 87 * @return column[] 88 */ 89 protected function get_all_columns(): array { 90 $filesalias = $this->get_table_alias('files'); 91 $contextalias = $this->get_table_alias('context'); 92 93 // Name. 94 $columns[] = (new column( 95 'name', 96 new lang_string('filename', 'core_repository'), 97 $this->get_entity_name() 98 )) 99 ->add_joins($this->get_joins()) 100 ->set_type(column::TYPE_TEXT) 101 ->add_field("{$filesalias}.filename") 102 ->set_is_sortable(true); 103 104 // Size. 105 $columns[] = (new column( 106 'size', 107 new lang_string('size'), 108 $this->get_entity_name() 109 )) 110 ->add_joins($this->get_joins()) 111 ->set_type(column::TYPE_INTEGER) 112 ->add_field("{$filesalias}.filesize") 113 ->add_field("CASE WHEN {$filesalias}.filename = '.' THEN 1 ELSE 0 END", 'directory') 114 ->set_is_sortable(true) 115 ->add_callback(static function($filesize, stdClass $fileinfo): string { 116 // Absent file size and/or directory should not return output. 117 if ($fileinfo->filesize === null || $fileinfo->directory) { 118 return ''; 119 } 120 return display_size($fileinfo->filesize); 121 }); 122 123 // Path. 124 $columns[] = (new column( 125 'path', 126 new lang_string('path'), 127 $this->get_entity_name() 128 )) 129 ->add_joins($this->get_joins()) 130 ->set_type(column::TYPE_TEXT) 131 ->add_field("{$filesalias}.filepath") 132 ->set_is_sortable(true); 133 134 // Type. 135 $columns[] = (new column( 136 'type', 137 new lang_string('type', 'core_repository'), 138 $this->get_entity_name() 139 )) 140 ->add_joins($this->get_joins()) 141 ->set_type(column::TYPE_TEXT) 142 ->add_field("{$filesalias}.mimetype") 143 ->add_field("CASE WHEN {$filesalias}.filename = '.' THEN 1 ELSE 0 END", 'directory') 144 ->set_is_sortable(true) 145 ->add_callback(static function($mimetype, stdClass $fileinfo): string { 146 global $CFG; 147 require_once("{$CFG->libdir}/filelib.php"); 148 149 // Absent mime type and/or directory has pre-determined output. 150 if ($fileinfo->mimetype === null && !$fileinfo->directory) { 151 return ''; 152 } else if ($fileinfo->directory) { 153 return get_string('directory'); 154 } 155 156 return get_mimetype_description($fileinfo->mimetype); 157 }); 158 159 // Author. 160 $columns[] = (new column( 161 'author', 162 new lang_string('author', 'core_repository'), 163 $this->get_entity_name() 164 )) 165 ->add_joins($this->get_joins()) 166 ->set_type(column::TYPE_TEXT) 167 ->add_field("{$filesalias}.author") 168 ->set_is_sortable(true); 169 170 // License. 171 $columns[] = (new column( 172 'license', 173 new lang_string('license', 'core_repository'), 174 $this->get_entity_name() 175 )) 176 ->add_joins($this->get_joins()) 177 ->set_type(column::TYPE_TEXT) 178 ->add_field("{$filesalias}.license") 179 ->set_is_sortable(true) 180 ->add_callback(static function(?string $license): string { 181 global $CFG; 182 require_once("{$CFG->libdir}/licenselib.php"); 183 184 $licenses = license_manager::get_licenses(); 185 if ($license === null || !array_key_exists($license, $licenses)) { 186 return ''; 187 } 188 return $licenses[$license]->fullname; 189 }); 190 191 // Context. 192 $columns[] = (new column( 193 'context', 194 new lang_string('context'), 195 $this->get_entity_name() 196 )) 197 ->add_joins($this->get_joins()) 198 ->set_type(column::TYPE_TEXT) 199 ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$filesalias}.contextid") 200 ->add_fields("{$filesalias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias)) 201 // Sorting may not order alphabetically, but will at least group contexts together. 202 ->set_is_sortable(true) 203 ->set_is_deprecated('See \'context:name\' for replacement') 204 ->add_callback(static function($contextid, stdClass $context): string { 205 if ($contextid === null) { 206 return ''; 207 } 208 209 context_helper::preload_from_record($context); 210 return context::instance_by_id($contextid)->get_context_name(); 211 }); 212 213 // Context link. 214 $columns[] = (new column( 215 'contexturl', 216 new lang_string('contexturl'), 217 $this->get_entity_name() 218 )) 219 ->add_joins($this->get_joins()) 220 ->set_type(column::TYPE_TEXT) 221 ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$filesalias}.contextid") 222 ->add_fields("{$filesalias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias)) 223 // Sorting may not order alphabetically, but will at least group contexts together. 224 ->set_is_sortable(true) 225 ->set_is_deprecated('See \'context:link\' for replacement') 226 ->add_callback(static function($contextid, stdClass $context): string { 227 if ($contextid === null) { 228 return ''; 229 } 230 231 context_helper::preload_from_record($context); 232 $context = context::instance_by_id($contextid); 233 234 return html_writer::link($context->get_url(), $context->get_context_name()); 235 }); 236 237 // Content hash. 238 $columns[] = (new column( 239 'contenthash', 240 new lang_string('contenthash', 'core_files'), 241 $this->get_entity_name() 242 )) 243 ->add_joins($this->get_joins()) 244 ->set_type(column::TYPE_TEXT) 245 ->add_field("{$filesalias}.contenthash") 246 ->set_is_sortable(true); 247 248 // Component. 249 $columns[] = (new column( 250 'component', 251 new lang_string('plugin'), 252 $this->get_entity_name() 253 )) 254 ->add_joins($this->get_joins()) 255 ->set_type(column::TYPE_TEXT) 256 ->add_fields("{$filesalias}.component") 257 ->set_is_sortable(true); 258 259 // Area. 260 $columns[] = (new column( 261 'area', 262 new lang_string('pluginarea'), 263 $this->get_entity_name() 264 )) 265 ->add_joins($this->get_joins()) 266 ->set_type(column::TYPE_TEXT) 267 ->add_fields("{$filesalias}.filearea") 268 ->set_is_sortable(true); 269 270 // Item ID. 271 $columns[] = (new column( 272 'itemid', 273 new lang_string('pluginitemid'), 274 $this->get_entity_name() 275 )) 276 ->add_joins($this->get_joins()) 277 ->set_type(column::TYPE_INTEGER) 278 ->add_fields("{$filesalias}.itemid") 279 ->set_is_sortable(true) 280 ->set_disabled_aggregation_all(); 281 282 // Time created. 283 $columns[] = (new column( 284 'timecreated', 285 new lang_string('timecreated', 'core_reportbuilder'), 286 $this->get_entity_name() 287 )) 288 ->add_joins($this->get_joins()) 289 ->set_type(column::TYPE_TIMESTAMP) 290 ->add_field("{$filesalias}.timecreated") 291 ->add_callback([format::class, 'userdate']) 292 ->set_is_sortable(true); 293 294 return $columns; 295 } 296 297 /** 298 * Return list of all available filters 299 * 300 * @return filter[] 301 */ 302 protected function get_all_filters(): array { 303 $filesalias = $this->get_table_alias('files'); 304 305 // Directory. 306 $filters[] = (new filter( 307 boolean_select::class, 308 'directory', 309 new lang_string('directory'), 310 $this->get_entity_name(), 311 "CASE WHEN {$filesalias}.filename = '.' THEN 1 ELSE 0 END" 312 )) 313 ->add_joins($this->get_joins()); 314 315 // Draft. 316 $filters[] = (new filter( 317 boolean_select::class, 318 'draft', 319 new lang_string('areauserdraft', 'core_repository'), 320 $this->get_entity_name(), 321 "CASE WHEN {$filesalias}.component = 'user' AND {$filesalias}.filearea = 'draft' THEN 1 ELSE 0 END" 322 )) 323 ->add_joins($this->get_joins()); 324 325 // Name. 326 $filters[] = (new filter( 327 text::class, 328 'name', 329 new lang_string('filename', 'core_repository'), 330 $this->get_entity_name(), 331 "{$filesalias}.filename" 332 )) 333 ->add_joins($this->get_joins()); 334 335 // Size. 336 $filters[] = (new filter( 337 number::class, 338 'size', 339 new lang_string('size'), 340 $this->get_entity_name(), 341 "{$filesalias}.filesize" 342 )) 343 ->add_joins($this->get_joins()) 344 ->set_limited_operators([ 345 number::ANY_VALUE, 346 number::LESS_THAN, 347 number::GREATER_THAN, 348 number::RANGE, 349 ]); 350 351 // License (consider null = 'unknown/license not specified' for filtering purposes). 352 $filters[] = (new filter( 353 select::class, 354 'license', 355 new lang_string('license', 'core_repository'), 356 $this->get_entity_name(), 357 "COALESCE({$filesalias}.license, 'unknown')" 358 )) 359 ->add_joins($this->get_joins()) 360 ->set_options_callback(static function(): array { 361 global $CFG; 362 require_once("{$CFG->libdir}/licenselib.php"); 363 364 $licenses = license_manager::get_licenses(); 365 366 return array_map(static function(stdClass $license): string { 367 return $license->fullname; 368 }, $licenses); 369 }); 370 371 // Content hash. 372 $filters[] = (new filter( 373 text::class, 374 'contenthash', 375 new lang_string('contenthash', 'core_files'), 376 $this->get_entity_name(), 377 "{$filesalias}.contenthash" 378 )) 379 ->add_joins($this->get_joins()); 380 381 // Time created. 382 $filters[] = (new filter( 383 date::class, 384 'timecreated', 385 new lang_string('timecreated', 'core_reportbuilder'), 386 $this->get_entity_name(), 387 "{$filesalias}.timecreated" 388 )) 389 ->add_joins($this->get_joins()) 390 ->set_limited_operators([ 391 date::DATE_ANY, 392 date::DATE_RANGE, 393 date::DATE_LAST, 394 date::DATE_CURRENT, 395 ]); 396 397 return $filters; 398 } 399 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body