Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [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_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              ->add_callback(static function($contextid, stdClass $context): string {
 125                  if ($contextid === null) {
 126                      return '';
 127                  }
 128  
 129                  context_helper::preload_from_record($context);
 130                  return context::instance_by_id($contextid)->get_context_name();
 131              });
 132  
 133          // Context URL.
 134          $columns[] = (new column(
 135              'contexturl',
 136              new lang_string('contexturl'),
 137              $this->get_entity_name()
 138          ))
 139              ->add_joins($this->get_joins())
 140              ->set_type(column::TYPE_TEXT)
 141              ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$instancealias}.contextid")
 142              ->add_fields("{$instancealias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias))
 143              // Sorting may not order alphabetically, but will at least group contexts together.
 144              ->set_is_sortable(true)
 145              ->add_callback(static function($contextid, stdClass $context): string {
 146                  if ($contextid === null) {
 147                      return '';
 148                  }
 149  
 150                  context_helper::preload_from_record($context);
 151                  $context = context::instance_by_id($contextid);
 152  
 153                  return html_writer::link($context->get_url(), $context->get_context_name());
 154              });
 155  
 156          // Component.
 157          $columns[] = (new column(
 158              'component',
 159              new lang_string('component', 'core_tag'),
 160              $this->get_entity_name()
 161          ))
 162              ->add_joins($this->get_joins())
 163              ->set_type(column::TYPE_TEXT)
 164              ->add_fields("{$instancealias}.component")
 165              ->set_is_sortable(true);
 166  
 167          // Item type.
 168          $columns[] = (new column(
 169              'itemtype',
 170              new lang_string('itemtype', 'core_tag'),
 171              $this->get_entity_name()
 172          ))
 173              ->add_joins($this->get_joins())
 174              ->set_type(column::TYPE_TEXT)
 175              ->add_fields("{$instancealias}.itemtype")
 176              ->set_is_sortable(true);
 177  
 178          // Item ID.
 179          $columns[] = (new column(
 180              'itemid',
 181              new lang_string('itemid', 'core_tag'),
 182              $this->get_entity_name()
 183          ))
 184              ->add_joins($this->get_joins())
 185              ->set_type(column::TYPE_INTEGER)
 186              ->add_fields("{$instancealias}.itemid")
 187              ->set_is_sortable(true)
 188              ->set_disabled_aggregation_all();
 189  
 190          // Time created.
 191          $columns[] = (new column(
 192              'timecreated',
 193              new lang_string('timecreated', 'core_reportbuilder'),
 194              $this->get_entity_name()
 195          ))
 196              ->add_joins($this->get_joins())
 197              ->set_type(column::TYPE_TIMESTAMP)
 198              ->add_fields("{$instancealias}.timecreated")
 199              ->set_is_sortable(true)
 200              ->add_callback([format::class, 'userdate']);
 201  
 202          // Time modified.
 203          $columns[] = (new column(
 204              'timemodified',
 205              new lang_string('timemodified', 'core_reportbuilder'),
 206              $this->get_entity_name()
 207          ))
 208              ->add_joins($this->get_joins())
 209              ->set_type(column::TYPE_TIMESTAMP)
 210              ->add_fields("{$instancealias}.timemodified")
 211              ->set_is_sortable(true)
 212              ->add_callback([format::class, 'userdate']);
 213  
 214          return $columns;
 215      }
 216  
 217      /**
 218       * Return list of all available filters
 219       *
 220       * @return filter[]
 221       */
 222      protected function get_all_filters(): array {
 223          global $DB;
 224  
 225          $instancealias = $this->get_table_alias('tag_instance');
 226  
 227          // Area.
 228          $filters[] = (new filter(
 229              select::class,
 230              'area',
 231              new lang_string('tagarea', 'core_tag'),
 232              $this->get_entity_name(),
 233              $DB->sql_concat("{$instancealias}.component", "'/'", "{$instancealias}.itemtype")
 234          ))
 235              ->add_joins($this->get_joins())
 236              ->set_options_callback(static function(): array {
 237                  $options = [];
 238                  foreach (core_tag_area::get_areas() as $areas) {
 239                      foreach ($areas as $area) {
 240                          $options["{$area->component}/{$area->itemtype}"] = core_tag_area::display_name(
 241                              $area->component, $area->itemtype);
 242                      }
 243                  }
 244  
 245                  core_collator::asort($options);
 246                  return $options;
 247              });
 248  
 249          // Time created.
 250          $filters[] = (new filter(
 251              date::class,
 252              'timecreated',
 253              new lang_string('timecreated', 'core_reportbuilder'),
 254              $this->get_entity_name(),
 255              "{$instancealias}.timecreated"
 256          ))
 257              ->add_joins($this->get_joins())
 258              ->set_limited_operators([
 259                  date::DATE_ANY,
 260                  date::DATE_CURRENT,
 261                  date::DATE_LAST,
 262                  date::DATE_RANGE,
 263              ]);
 264  
 265          // Time modified.
 266          $filters[] = (new filter(
 267              date::class,
 268              'timemodified',
 269              new lang_string('timemodified', 'core_reportbuilder'),
 270              $this->get_entity_name(),
 271              "{$instancealias}.timemodified"
 272          ))
 273              ->add_joins($this->get_joins())
 274              ->set_limited_operators([
 275                  date::DATE_ANY,
 276                  date::DATE_CURRENT,
 277                  date::DATE_LAST,
 278                  date::DATE_RANGE,
 279              ]);
 280  
 281          return $filters;
 282      }
 283  }