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 402] [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_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              ->set_type(column::TYPE_TEXT)
 104              ->add_fields("{$tablealias}.name, {$tablealias}.id")
 105              ->add_callback(static function(?string $name, stdClass $category): string {
 106                  return empty($category->id) ? '' :
 107                      core_course_category::get($category->id, MUST_EXIST, true)->get_formatted_name();
 108              })
 109              ->set_is_sortable(true);
 110  
 111          // Category name with link column.
 112          $columns[] = (new column(
 113              'namewithlink',
 114              new lang_string('namewithlink', 'core_course'),
 115              $this->get_entity_name()
 116          ))
 117              ->add_joins($this->get_joins())
 118              ->add_join($this->get_context_join())
 119              ->set_type(column::TYPE_TEXT)
 120              ->add_fields("{$tablealias}.name, {$tablealias}.id")
 121              ->add_fields(context_helper::get_preload_record_columns_sql($tablealiascontext))
 122              ->add_callback(static function(?string $name, stdClass $category): string {
 123                  if (empty($category->id)) {
 124                      return '';
 125                  }
 126                  context_helper::preload_from_record($category);
 127                  $context = context_coursecat::instance($category->id);
 128                  $url = new moodle_url('/course/management.php', ['categoryid' => $category->id]);
 129                  return html_writer::link($url,
 130                      format_string($category->name, true, ['context' => $context]));
 131              })
 132              ->set_is_sortable(true);
 133  
 134          // Path column.
 135          $columns[] = (new column(
 136              'path',
 137              new lang_string('categorypath'),
 138              $this->get_entity_name()
 139          ))
 140              ->add_joins($this->get_joins())
 141              ->set_type(column::TYPE_TEXT)
 142              ->add_fields("{$tablealias}.name, {$tablealias}.id")
 143              ->add_callback(static function(?string $name, stdClass $category): string {
 144                  return empty($category->id) ? '' :
 145                      core_course_category::get($category->id, MUST_EXIST, true)->get_nested_name(false);
 146              })
 147              ->set_disabled_aggregation(['groupconcat', 'groupconcatdistinct'])
 148              ->set_is_sortable(true);
 149  
 150          // ID number column.
 151          $columns[] = (new column(
 152              'idnumber',
 153              new lang_string('idnumbercoursecategory'),
 154              $this->get_entity_name()
 155          ))
 156              ->add_joins($this->get_joins())
 157              ->set_type(column::TYPE_TEXT)
 158              ->add_fields("{$tablealias}.idnumber")
 159              ->set_is_sortable(true);
 160  
 161          // Description column (note we need to join/select from the context table in order to format the column).
 162          $descriptionfieldsql = "{$tablealias}.description";
 163          if ($DB->get_dbfamily() === 'oracle') {
 164              $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024);
 165          }
 166          $columns[] = (new column(
 167              'description',
 168              new lang_string('description'),
 169              $this->get_entity_name()
 170          ))
 171              ->add_joins($this->get_joins())
 172              ->add_join($this->get_context_join())
 173              ->set_type(column::TYPE_LONGTEXT)
 174              ->add_field($descriptionfieldsql, 'description')
 175              ->add_fields("{$tablealias}.descriptionformat, {$tablealias}.id")
 176              ->add_fields(context_helper::get_preload_record_columns_sql($tablealiascontext))
 177              ->add_callback(static function(?string $description, stdClass $category): string {
 178                  global $CFG;
 179                  require_once("{$CFG->libdir}/filelib.php");
 180  
 181                  if ($description === null) {
 182                      return '';
 183                  }
 184  
 185                  context_helper::preload_from_record($category);
 186                  $context = context_coursecat::instance($category->id);
 187  
 188                  $description = file_rewrite_pluginfile_urls($description, 'pluginfile.php', $context->id, 'coursecat',
 189                      'description', null);
 190  
 191                  return format_text($description, $category->descriptionformat, ['context' => $context->id]);
 192              });
 193  
 194          return $columns;
 195      }
 196  
 197      /**
 198       * Return list of all available filters
 199       *
 200       * @return filter[]
 201       */
 202      protected function get_all_filters(): array {
 203          $tablealias = $this->get_table_alias('course_categories');
 204  
 205          // Select category filter.
 206          $filters[] = (new filter(
 207              category::class,
 208              'name',
 209              new lang_string('categoryselect', 'core_reportbuilder'),
 210              $this->get_entity_name(),
 211              "{$tablealias}.id"
 212          ))
 213              ->add_joins($this->get_joins())
 214              ->set_options([
 215                  'requiredcapabilities' => 'moodle/category:viewcourselist',
 216              ]);
 217  
 218          // Name filter.
 219          $filters[] = (new filter(
 220              text::class,
 221              'text',
 222              new lang_string('categoryname'),
 223              $this->get_entity_name(),
 224              "{$tablealias}.name"
 225          ))
 226              ->add_joins($this->get_joins());
 227  
 228          // ID number filter.
 229          $filters[] = (new filter(
 230              text::class,
 231              'idnumber',
 232              new lang_string('idnumbercoursecategory'),
 233              $this->get_entity_name(),
 234              "{$tablealias}.idnumber"
 235          ))
 236              ->add_joins($this->get_joins());
 237  
 238          return $filters;
 239      }
 240  
 241      /**
 242       * Return context join used by columns
 243       *
 244       * @return string
 245       */
 246      private function get_context_join(): string {
 247          $coursecategories = $this->get_table_alias('course_categories');
 248          $context = $this->get_table_alias('context');
 249          return "LEFT JOIN {context} {$context} ON {$context}.instanceid = {$coursecategories}.id
 250              AND {$context}.contextlevel = " . CONTEXT_COURSECAT;
 251      }
 252  }