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_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          // Course count column.
 203          $columns[] = (new column(
 204              'coursecount',
 205              new lang_string('coursecount', 'core_course'),
 206              $this->get_entity_name()
 207          ))
 208              ->add_joins($this->get_joins())
 209              ->set_type(column::TYPE_INTEGER)
 210              ->add_fields("{$tablealias}.coursecount")
 211              ->set_is_sortable(true);
 212  
 213          return $columns;
 214      }
 215  
 216      /**
 217       * Return list of all available filters
 218       *
 219       * @return filter[]
 220       */
 221      protected function get_all_filters(): array {
 222          $tablealias = $this->get_table_alias('course_categories');
 223  
 224          // Select category filter.
 225          $filters[] = (new filter(
 226              category::class,
 227              'name',
 228              new lang_string('categoryselect', 'core_reportbuilder'),
 229              $this->get_entity_name(),
 230              "{$tablealias}.id"
 231          ))
 232              ->add_joins($this->get_joins())
 233              ->set_options([
 234                  'requiredcapabilities' => 'moodle/category:viewcourselist',
 235              ]);
 236  
 237          // Name filter.
 238          $filters[] = (new filter(
 239              text::class,
 240              'text',
 241              new lang_string('categoryname'),
 242              $this->get_entity_name(),
 243              "{$tablealias}.name"
 244          ))
 245              ->add_joins($this->get_joins());
 246  
 247          // ID number filter.
 248          $filters[] = (new filter(
 249              text::class,
 250              'idnumber',
 251              new lang_string('idnumbercoursecategory'),
 252              $this->get_entity_name(),
 253              "{$tablealias}.idnumber"
 254          ))
 255              ->add_joins($this->get_joins());
 256  
 257          return $filters;
 258      }
 259  
 260      /**
 261       * Return context join used by columns
 262       *
 263       * @return string
 264       */
 265      public function get_context_join(): string {
 266          $coursecategories = $this->get_table_alias('course_categories');
 267          $context = $this->get_table_alias('context');
 268          return "LEFT JOIN {context} {$context} ON {$context}.instanceid = {$coursecategories}.id
 269              AND {$context}.contextlevel = " . CONTEXT_COURSECAT;
 270      }
 271  }