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_cohort\reportbuilder\local\entities;
  20  
  21  use context;
  22  use context_helper;
  23  use lang_string;
  24  use stdClass;
  25  use core_reportbuilder\local\entities\base;
  26  use core_reportbuilder\local\filters\date;
  27  use core_reportbuilder\local\filters\select;
  28  use core_reportbuilder\local\filters\text;
  29  use core_reportbuilder\local\helpers\custom_fields;
  30  use core_reportbuilder\local\helpers\format;
  31  use core_reportbuilder\local\report\column;
  32  use core_reportbuilder\local\report\filter;
  33  
  34  /**
  35   * Cohort entity
  36   *
  37   * @package     core_cohort
  38   * @copyright   2021 Paul Holden <paulh@moodle.com>
  39   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  class cohort extends base {
  42  
  43      /**
  44       * Database tables that this entity uses and their default aliases
  45       *
  46       * @return array
  47       */
  48      protected function get_default_table_aliases(): array {
  49          return [
  50              'cohort' => 'c',
  51              'context' => 'chctx',
  52          ];
  53      }
  54  
  55      /**
  56       * The default title for this entity
  57       *
  58       * @return lang_string
  59       */
  60      protected function get_default_entity_title(): lang_string {
  61          return new lang_string('cohort', 'core_cohort');
  62      }
  63  
  64      /**
  65       * Initialise the entity
  66       *
  67       * @return base
  68       */
  69      public function initialise(): base {
  70          $tablealias = $this->get_table_alias('cohort');
  71  
  72          $customfields = (new custom_fields(
  73              "{$tablealias}.id",
  74              $this->get_entity_name(),
  75              'core_cohort',
  76              'cohort',
  77          ))
  78              ->add_joins($this->get_joins());
  79  
  80          $columns = array_merge($this->get_all_columns(), $customfields->get_columns());
  81          foreach ($columns as $column) {
  82              $this->add_column($column);
  83          }
  84  
  85          // All the filters defined by the entity can also be used as conditions.
  86          $filters = array_merge($this->get_all_filters(), $customfields->get_filters());
  87          foreach ($filters as $filter) {
  88              $this
  89                  ->add_filter($filter)
  90                  ->add_condition($filter);
  91          }
  92  
  93          return $this;
  94      }
  95  
  96      /**
  97       * Returns list of all available columns
  98       *
  99       * @return column[]
 100       */
 101      protected function get_all_columns(): array {
 102          global $DB;
 103  
 104          $tablealias = $this->get_table_alias('cohort');
 105          $contextalias = $this->get_table_alias('context');
 106  
 107          // Category/context column.
 108          $columns[] = (new column(
 109              'context',
 110              new lang_string('category'),
 111              $this->get_entity_name()
 112          ))
 113              ->add_joins($this->get_joins())
 114              ->add_join($this->get_context_join())
 115              ->set_type(column::TYPE_TEXT)
 116              ->add_fields("{$tablealias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias))
 117              ->set_is_sortable(true)
 118              ->add_callback(static function($contextid, stdClass $cohort): string {
 119                  if ($contextid === null) {
 120                      return '';
 121                  }
 122  
 123                  context_helper::preload_from_record($cohort);
 124                  return context::instance_by_id($cohort->contextid)->get_context_name(false);
 125              });
 126  
 127          // Name column.
 128          $columns[] = (new column(
 129              'name',
 130              new lang_string('name', 'core_cohort'),
 131              $this->get_entity_name()
 132          ))
 133              ->add_joins($this->get_joins())
 134              ->set_type(column::TYPE_TEXT)
 135              ->add_fields("{$tablealias}.name")
 136              ->set_is_sortable(true);
 137  
 138          // ID number column.
 139          $columns[] = (new column(
 140              'idnumber',
 141              new lang_string('idnumber', 'core_cohort'),
 142              $this->get_entity_name()
 143          ))
 144              ->add_joins($this->get_joins())
 145              ->set_type(column::TYPE_TEXT)
 146              ->add_fields("{$tablealias}.idnumber")
 147              ->set_is_sortable(true);
 148  
 149          // Description column.
 150          $descriptionfieldsql = "{$tablealias}.description";
 151          if ($DB->get_dbfamily() === 'oracle') {
 152              $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024);
 153          }
 154          $columns[] = (new column(
 155              'description',
 156              new lang_string('description'),
 157              $this->get_entity_name()
 158          ))
 159              ->add_joins($this->get_joins())
 160              ->add_join($this->get_context_join())
 161              ->set_type(column::TYPE_LONGTEXT)
 162              ->add_field($descriptionfieldsql, 'description')
 163              ->add_fields("{$tablealias}.descriptionformat, {$tablealias}.id, {$tablealias}.contextid")
 164              ->add_fields(context_helper::get_preload_record_columns_sql($contextalias))
 165              ->add_callback(static function(?string $description, stdClass $cohort): string {
 166                  global $CFG;
 167                  require_once("{$CFG->libdir}/filelib.php");
 168  
 169                  if ($description === null) {
 170                      return '';
 171                  }
 172  
 173                  context_helper::preload_from_record($cohort);
 174                  $context = context::instance_by_id($cohort->contextid);
 175  
 176                  $description = file_rewrite_pluginfile_urls($description, 'pluginfile.php', $context->id, 'cohort',
 177                      'description', $cohort->id);
 178  
 179                  return format_text($description, $cohort->descriptionformat, ['context' => $context->id]);
 180              });
 181  
 182          // Visible column.
 183          $columns[] = (new column(
 184              'visible',
 185              new lang_string('visible', 'core_cohort'),
 186              $this->get_entity_name()
 187          ))
 188              ->add_joins($this->get_joins())
 189              ->set_type(column::TYPE_BOOLEAN)
 190              ->add_fields("{$tablealias}.visible")
 191              ->set_is_sortable(true)
 192              ->set_callback([format::class, 'boolean_as_text']);
 193  
 194          // Time created column.
 195          $columns[] = (new column(
 196              'timecreated',
 197              new lang_string('timecreated', 'core_reportbuilder'),
 198              $this->get_entity_name()
 199          ))
 200              ->add_joins($this->get_joins())
 201              ->set_type(column::TYPE_TIMESTAMP)
 202              ->add_fields("{$tablealias}.timecreated")
 203              ->set_is_sortable(true)
 204              ->set_callback([format::class, 'userdate']);
 205  
 206          // Time modified column.
 207          $columns[] = (new column(
 208              'timemodified',
 209              new lang_string('timemodified', 'core_reportbuilder'),
 210              $this->get_entity_name()
 211          ))
 212              ->add_joins($this->get_joins())
 213              ->set_type(column::TYPE_TIMESTAMP)
 214              ->add_fields("{$tablealias}.timemodified")
 215              ->set_is_sortable(true)
 216              ->set_callback([format::class, 'userdate']);
 217  
 218          // Component column.
 219          $columns[] = (new column(
 220              'component',
 221              new lang_string('component', 'core_cohort'),
 222              $this->get_entity_name()
 223          ))
 224              ->add_joins($this->get_joins())
 225              ->set_type(column::TYPE_TEXT)
 226              ->add_fields("{$tablealias}.component")
 227              ->set_is_sortable(true)
 228              ->add_callback(static function(?string $component): string {
 229                  if ($component === null) {
 230                      return '';
 231                  }
 232  
 233                  return $component === ''
 234                      ? get_string('nocomponent', 'cohort')
 235                      : get_string('pluginname', $component);
 236              });
 237  
 238          // Theme column.
 239          $columns[] = (new column(
 240              'theme',
 241              new lang_string('theme'),
 242              $this->get_entity_name()
 243          ))
 244              ->add_joins($this->get_joins())
 245              ->set_type(column::TYPE_TEXT)
 246              ->add_fields("{$tablealias}.theme")
 247              ->set_is_sortable(true);
 248  
 249          return $columns;
 250      }
 251  
 252      /**
 253       * Return list of all available filters
 254       *
 255       * @return filter[]
 256       */
 257      protected function get_all_filters(): array {
 258          global $DB;
 259  
 260          $tablealias = $this->get_table_alias('cohort');
 261  
 262          // Context filter.
 263          $filters[] = (new filter(
 264              select::class,
 265              'context',
 266              new lang_string('category'),
 267              $this->get_entity_name(),
 268              "{$tablealias}.contextid"
 269          ))
 270              ->add_joins($this->get_joins())
 271              ->set_options_callback(static function(): array {
 272                  global $DB;
 273  
 274                  // Load all contexts in which there are cohorts.
 275                  $ctxfields = context_helper::get_preload_record_columns_sql('ctx');
 276                  $contexts = $DB->get_records_sql("
 277                      SELECT DISTINCT {$ctxfields}, c.contextid
 278                        FROM {context} ctx
 279                        JOIN {cohort} c ON c.contextid = ctx.id");
 280  
 281                  // Transform context record into it's name (used as the filter options).
 282                  return array_map(static function(stdClass $contextrecord): string {
 283                      context_helper::preload_from_record($contextrecord);
 284  
 285                      return context::instance_by_id($contextrecord->contextid)
 286                          ->get_context_name(false);
 287                  }, $contexts);
 288              });
 289  
 290          // Name filter.
 291          $filters[] = (new filter(
 292              text::class,
 293              'name',
 294              new lang_string('name', 'core_cohort'),
 295              $this->get_entity_name(),
 296              "{$tablealias}.name"
 297          ))
 298              ->add_joins($this->get_joins());
 299  
 300          // ID number filter.
 301          $filters[] = (new filter(
 302              text::class,
 303              'idnumber',
 304              new lang_string('idnumber', 'core_cohort'),
 305              $this->get_entity_name(),
 306              "{$tablealias}.idnumber"
 307          ))
 308              ->add_joins($this->get_joins());
 309  
 310          // Time created filter.
 311          $filters[] = (new filter(
 312              date::class,
 313              'timecreated',
 314              new lang_string('timecreated', 'core_reportbuilder'),
 315              $this->get_entity_name(),
 316              "{$tablealias}.timecreated"
 317          ))
 318              ->add_joins($this->get_joins());
 319  
 320          // Description filter.
 321          $filters[] = (new filter(
 322              text::class,
 323              'description',
 324              new lang_string('description'),
 325              $this->get_entity_name(),
 326              $DB->sql_cast_to_char("{$tablealias}.description")
 327          ))
 328              ->add_joins($this->get_joins());
 329  
 330          return $filters;
 331      }
 332  
 333      /**
 334       * Return context join used by columns
 335       *
 336       * @return string
 337       */
 338      private function get_context_join(): string {
 339  
 340          // If the context table is already joined, we don't need to do that again.
 341          if ($this->has_table_join_alias('context')) {
 342              return '';
 343          }
 344  
 345          $tablealias = $this->get_table_alias('cohort');
 346          $contextalias = $this->get_table_alias('context');
 347  
 348          return "LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$tablealias}.contextid";
 349      }
 350  }