Search moodle.org's
Developer Documentation

See Release Notes

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

Differences Between: [Versions 401 and 402] [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_course\reportbuilder\local\entities;
  20  
  21  use context_coursecat;
  22  use context_helper;
  23  use html_writer;
  24  use lang_string;
  25  use moodle_url;
  26  use stdClass;
  27  use core_course_category;
  28  use core_reportbuilder\local\entities\base;
  29  use core_reportbuilder\local\filters\{category, text};
  30  use core_reportbuilder\local\report\column;
  31  use core_reportbuilder\local\report\filter;
  32  
  33  /**
  34   * Course category entity
  35   *
  36   * @package     core_course
  37   * @copyright   2021 Paul Holden <paulh@moodle.com>
  38   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class course_category 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              'context' => 'ccctx',
  50              'course_categories' => 'cc',
  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('coursecategory');
  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          global $DB;
  92  
  93          $tablealias = $this->get_table_alias('course_categories');
  94          $tablealiascontext = $this->get_table_alias('context');
  95  
  96          // Name column.
  97          $columns[] = (new column(
  98              'name',
  99              new lang_string('categoryname'),
 100              $this->get_entity_name()
 101          ))
 102              ->add_joins($this->get_joins())
 103              ->add_join($this->get_context_join())
 104              ->set_type(column::TYPE_TEXT)
 105              ->add_fields("{$tablealias}.name, {$tablealias}.id")
 106              ->add_fields(context_helper::get_preload_record_columns_sql($tablealiascontext))
 107              ->add_callback(static function(?string $name, stdClass $category): string {
 108                  if (empty($category->id)) {
 109                      return '';
 110                  }
 111  
 112                  context_helper::preload_from_record($category);
 113                  $context = context_coursecat::instance($category->id);
 114  
 115                  return format_string($category->name, true, ['context' => $context]);
 116              })
 117              ->set_is_sortable(true);
 118  
 119          // Category name with link column.
 120          $columns[] = (new column(
 121              'namewithlink',
 122              new lang_string('namewithlink', 'core_course'),
 123              $this->get_entity_name()
 124          ))
 125              ->add_joins($this->get_joins())
 126              ->add_join($this->get_context_join())
 127              ->set_type(column::TYPE_TEXT)
 128              ->add_fields("{$tablealias}.name, {$tablealias}.id")
 129              ->add_fields(context_helper::get_preload_record_columns_sql($tablealiascontext))
 130              ->add_callback(static function(?string $name, stdClass $category): string {
 131                  if (empty($category->id)) {
 132                      return '';
 133                  }
 134                  context_helper::preload_from_record($category);
 135                  $context = context_coursecat::instance($category->id);
 136                  $url = new moodle_url('/course/management.php', ['categoryid' => $category->id]);
 137                  return html_writer::link($url,
 138                      format_string($category->name, true, ['context' => $context]));
 139              })
 140              ->set_is_sortable(true);
 141  
 142          // Path column.
 143          $columns[] = (new column(
 144              'path',
 145              new lang_string('categorypath'),
 146              $this->get_entity_name()
 147          ))
 148              ->add_joins($this->get_joins())
 149              ->set_type(column::TYPE_TEXT)
 150              ->add_fields("{$tablealias}.name, {$tablealias}.id")
 151              ->add_callback(static function(?string $name, stdClass $category): string {
 152                  return empty($category->id) ? '' :
 153                      core_course_category::get($category->id, MUST_EXIST, true)->get_nested_name(false);
 154              })
 155              ->set_disabled_aggregation(['groupconcat', 'groupconcatdistinct'])
 156              ->set_is_sortable(true);
 157  
 158          // ID number column.
 159          $columns[] = (new column(
 160              'idnumber',
 161              new lang_string('idnumbercoursecategory'),
 162              $this->get_entity_name()
 163          ))
 164              ->add_joins($this->get_joins())
 165              ->set_type(column::TYPE_TEXT)
 166              ->add_fields("{$tablealias}.idnumber")
 167              ->set_is_sortable(true);
 168  
 169          // Description column (note we need to join/select from the context table in order to format the column).
 170          $descriptionfieldsql = "{$tablealias}.description";
 171          if ($DB->get_dbfamily() === 'oracle') {
 172              $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024);
 173          }
 174          $columns[] = (new column(
 175              'description',
 176              new lang_string('description'),
 177              $this->get_entity_name()
 178          ))
 179              ->add_joins($this->get_joins())
 180              ->add_join($this->get_context_join())
 181              ->set_type(column::TYPE_LONGTEXT)
 182              ->add_field($descriptionfieldsql, 'description')
 183              ->add_fields("{$tablealias}.descriptionformat, {$tablealias}.id")
 184              ->add_fields(context_helper::get_preload_record_columns_sql($tablealiascontext))
 185              ->add_callback(static function(?string $description, stdClass $category): string {
 186                  global $CFG;
 187                  require_once("{$CFG->libdir}/filelib.php");
 188  
 189                  if ($description === null) {
 190                      return '';
 191                  }
 192  
 193                  context_helper::preload_from_record($category);
 194                  $context = context_coursecat::instance($category->id);
 195  
 196                  $description = file_rewrite_pluginfile_urls($description, 'pluginfile.php', $context->id, 'coursecat',
 197                      'description', null);
 198  
 199                  return format_text($description, $category->descriptionformat, ['context' => $context->id]);
 200              });
 201  
 202          return $columns;
 203      }
 204  
 205      /**
 206       * Return list of all available filters
 207       *
 208       * @return filter[]
 209       */
 210      protected function get_all_filters(): array {
 211          $tablealias = $this->get_table_alias('course_categories');
 212  
 213          // Select category filter.
 214          $filters[] = (new filter(
 215              category::class,
 216              'name',
 217              new lang_string('categoryselect', 'core_reportbuilder'),
 218              $this->get_entity_name(),
 219              "{$tablealias}.id"
 220          ))
 221              ->add_joins($this->get_joins())
 222              ->set_options([
 223                  'requiredcapabilities' => 'moodle/category:viewcourselist',
 224              ]);
 225  
 226          // Name filter.
 227          $filters[] = (new filter(
 228              text::class,
 229              'text',
 230              new lang_string('categoryname'),
 231              $this->get_entity_name(),
 232              "{$tablealias}.name"
 233          ))
 234              ->add_joins($this->get_joins());
 235  
 236          // ID number filter.
 237          $filters[] = (new filter(
 238              text::class,
 239              'idnumber',
 240              new lang_string('idnumbercoursecategory'),
 241              $this->get_entity_name(),
 242              "{$tablealias}.idnumber"
 243          ))
 244              ->add_joins($this->get_joins());
 245  
 246          return $filters;
 247      }
 248  
 249      /**
 250       * Return context join used by columns
 251       *
 252       * @return string
 253       */
 254      private function get_context_join(): string {
 255          $coursecategories = $this->get_table_alias('course_categories');
 256          $context = $this->get_table_alias('context');
 257          return "LEFT JOIN {context} {$context} ON {$context}.instanceid = {$coursecategories}.id
 258              AND {$context}.contextlevel = " . CONTEXT_COURSECAT;
 259      }
 260  }