Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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_tag\reportbuilder\local\entities;
  20  
  21  use context;
  22  use context_helper;
  23  use core_collator;
  24  use core_tag_area;
  25  use html_writer;
  26  use lang_string;
  27  use stdClass;
  28  use core_reportbuilder\local\entities\base;
  29  use core_reportbuilder\local\filters\{date, select};
  30  use core_reportbuilder\local\helpers\format;
  31  use core_reportbuilder\local\report\{column, filter};
  32  
  33  /**
  34   * Tag instance entity
  35   *
  36   * @package     core_tag
  37   * @copyright   2022 Paul Holden <paulh@moodle.com>
  38   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class instance extends base {
  41  
  42      /**
  43       * Database tables that this entity uses and their default aliases
  44       *
  45       * @return array
  46       */
  47      protected function get_default_table_aliases(): array {
  48          return [
  49              'tag_instance' => 'ti',
  50              'context' => 'tictx',
  51          ];
  52      }
  53  
  54      /**
  55       * The default title for this entity
  56       *
  57       * @return lang_string
  58       */
  59      protected function get_default_entity_title(): lang_string {
  60          return new lang_string('taginstance', 'core_tag');
  61      }
  62  
  63      /**
  64       * Initialise the entity
  65       *
  66       * @return base
  67       */
  68      public function initialise(): base {
  69          $columns = $this->get_all_columns();
  70          foreach ($columns as $column) {
  71              $this->add_column($column);
  72          }
  73  
  74          // All the filters defined by the entity can also be used as conditions.
  75          $filters = $this->get_all_filters();
  76          foreach ($filters as $filter) {
  77              $this
  78                  ->add_filter($filter)
  79                  ->add_condition($filter);
  80          }
  81  
  82          return $this;
  83      }
  84  
  85      /**
  86       * Returns list of all available columns
  87       *
  88       * @return column[]
  89       */
  90      protected function get_all_columns(): array {
  91          $instancealias = $this->get_table_alias('tag_instance');
  92          $contextalias = $this->get_table_alias('context');
  93  
  94          // Area.
  95          $columns[] = (new column(
  96              'area',
  97              new lang_string('tagarea', 'core_tag'),
  98              $this->get_entity_name()
  99  
 100          ))
 101              ->add_joins($this->get_joins())
 102              ->set_type(column::TYPE_TEXT)
 103              ->add_fields("{$instancealias}.component, {$instancealias}.itemtype")
 104              ->set_is_sortable(true, ["{$instancealias}.component", "{$instancealias}.itemtype"])
 105              ->add_callback(static function($component, stdClass $area): string {
 106                  if ($component === null) {
 107                      return '';
 108                  }
 109                  return (string) core_tag_area::display_name($area->component, $area->itemtype);
 110              });
 111  
 112          // Context.
 113          $columns[] = (new column(
 114              'context',
 115              new lang_string('context'),
 116              $this->get_entity_name()
 117          ))
 118              ->add_joins($this->get_joins())
 119              ->set_type(column::TYPE_TEXT)
 120              ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$instancealias}.contextid")
 121              ->add_fields("{$instancealias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias))
 122              // Sorting may not order alphabetically, but will at least group contexts together.
 123              ->set_is_sortable(true)
 124              ->set_is_deprecated('See \'context:name\' for replacement')
 125              ->add_callback(static function($contextid, stdClass $context): string {
 126                  if ($contextid === null) {
 127                      return '';
 128                  }
 129  
 130                  context_helper::preload_from_record($context);
 131                  return context::instance_by_id($contextid)->get_context_name();
 132              });
 133  
 134          // Context URL.
 135          $columns[] = (new column(
 136              'contexturl',
 137              new lang_string('contexturl'),
 138              $this->get_entity_name()
 139          ))
 140              ->add_joins($this->get_joins())
 141              ->set_type(column::TYPE_TEXT)
 142              ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$instancealias}.contextid")
 143              ->add_fields("{$instancealias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias))
 144              // Sorting may not order alphabetically, but will at least group contexts together.
 145              ->set_is_sortable(true)
 146              ->set_is_deprecated('See \'context:link\' for replacement')
 147              ->add_callback(static function($contextid, stdClass $context): string {
 148                  if ($contextid === null) {
 149                      return '';
 150                  }
 151  
 152                  context_helper::preload_from_record($context);
 153                  $context = context::instance_by_id($contextid);
 154  
 155                  return html_writer::link($context->get_url(), $context->get_context_name());
 156              });
 157  
 158          // Component.
 159          $columns[] = (new column(
 160              'component',
 161              new lang_string('component', 'core_tag'),
 162              $this->get_entity_name()
 163          ))
 164              ->add_joins($this->get_joins())
 165              ->set_type(column::TYPE_TEXT)
 166              ->add_fields("{$instancealias}.component")
 167              ->set_is_sortable(true);
 168  
 169          // Item type.
 170          $columns[] = (new column(
 171              'itemtype',
 172              new lang_string('itemtype', 'core_tag'),
 173              $this->get_entity_name()
 174          ))
 175              ->add_joins($this->get_joins())
 176              ->set_type(column::TYPE_TEXT)
 177              ->add_fields("{$instancealias}.itemtype")
 178              ->set_is_sortable(true);
 179  
 180          // Item ID.
 181          $columns[] = (new column(
 182              'itemid',
 183              new lang_string('itemid', 'core_tag'),
 184              $this->get_entity_name()
 185          ))
 186              ->add_joins($this->get_joins())
 187              ->set_type(column::TYPE_INTEGER)
 188              ->add_fields("{$instancealias}.itemid")
 189              ->set_is_sortable(true)
 190              ->set_disabled_aggregation_all();
 191  
 192          // Time created.
 193          $columns[] = (new column(
 194              'timecreated',
 195              new lang_string('timecreated', 'core_reportbuilder'),
 196              $this->get_entity_name()
 197          ))
 198              ->add_joins($this->get_joins())
 199              ->set_type(column::TYPE_TIMESTAMP)
 200              ->add_fields("{$instancealias}.timecreated")
 201              ->set_is_sortable(true)
 202              ->add_callback([format::class, 'userdate']);
 203  
 204          // Time modified.
 205          $columns[] = (new column(
 206              'timemodified',
 207              new lang_string('timemodified', 'core_reportbuilder'),
 208              $this->get_entity_name()
 209          ))
 210              ->add_joins($this->get_joins())
 211              ->set_type(column::TYPE_TIMESTAMP)
 212              ->add_fields("{$instancealias}.timemodified")
 213              ->set_is_sortable(true)
 214              ->add_callback([format::class, 'userdate']);
 215  
 216          return $columns;
 217      }
 218  
 219      /**
 220       * Return list of all available filters
 221       *
 222       * @return filter[]
 223       */
 224      protected function get_all_filters(): array {
 225          global $DB;
 226  
 227          $instancealias = $this->get_table_alias('tag_instance');
 228  
 229          // Area.
 230          $filters[] = (new filter(
 231              select::class,
 232              'area',
 233              new lang_string('tagarea', 'core_tag'),
 234              $this->get_entity_name(),
 235              $DB->sql_concat("{$instancealias}.component", "'/'", "{$instancealias}.itemtype")
 236          ))
 237              ->add_joins($this->get_joins())
 238              ->set_options_callback(static function(): array {
 239                  $options = [];
 240                  foreach (core_tag_area::get_areas() as $areas) {
 241                      foreach ($areas as $area) {
 242                          $options["{$area->component}/{$area->itemtype}"] = core_tag_area::display_name(
 243                              $area->component, $area->itemtype);
 244                      }
 245                  }
 246  
 247                  core_collator::asort($options);
 248                  return $options;
 249              });
 250  
 251          // Time created.
 252          $filters[] = (new filter(
 253              date::class,
 254              'timecreated',
 255              new lang_string('timecreated', 'core_reportbuilder'),
 256              $this->get_entity_name(),
 257              "{$instancealias}.timecreated"
 258          ))
 259              ->add_joins($this->get_joins())
 260              ->set_limited_operators([
 261                  date::DATE_ANY,
 262                  date::DATE_CURRENT,
 263                  date::DATE_LAST,
 264                  date::DATE_RANGE,
 265              ]);
 266  
 267          // Time modified.
 268          $filters[] = (new filter(
 269              date::class,
 270              'timemodified',
 271              new lang_string('timemodified', 'core_reportbuilder'),
 272              $this->get_entity_name(),
 273              "{$instancealias}.timemodified"
 274          ))
 275              ->add_joins($this->get_joins())
 276              ->set_limited_operators([
 277                  date::DATE_ANY,
 278                  date::DATE_CURRENT,
 279                  date::DATE_LAST,
 280                  date::DATE_RANGE,
 281              ]);
 282  
 283          return $filters;
 284      }
 285  }