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_course;
  22  use core_course\reportbuilder\local\formatters\enrolment as enrolment_formatter;
  23  use core_reportbuilder\local\entities\base;
  24  use core_reportbuilder\local\filters\date;
  25  use core_reportbuilder\local\filters\select;
  26  use core_reportbuilder\local\helpers\database;
  27  use core_reportbuilder\local\helpers\format;
  28  use core_reportbuilder\local\report\column;
  29  use core_reportbuilder\local\report\filter;
  30  use core_user\output\status_field;
  31  use enrol_plugin;
  32  use lang_string;
  33  use stdClass;
  34  
  35  /**
  36   * Course enrolment entity implementation
  37   *
  38   * @package     core_course
  39   * @copyright   2022 David Matamoros <davidmc@moodle.com>
  40   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class enrolment extends base {
  43  
  44      /**
  45       * Database tables that this entity uses and their default aliases
  46       *
  47       * @return array
  48       */
  49      protected function get_default_table_aliases(): array {
  50          return ['user_enrolments' => 'ue', 'enrol' => 'e'];
  51      }
  52  
  53      /**
  54       * The default title for this entity in the list of columns/conditions/filters in the report builder
  55       *
  56       * @return lang_string
  57       */
  58      protected function get_default_entity_title(): lang_string {
  59          return new lang_string('enrolment', 'enrol');
  60      }
  61  
  62      /**
  63       * Initialise the entity
  64       *
  65       * @return base
  66       */
  67      public function initialise(): base {
  68          foreach ($this->get_all_columns() as $column) {
  69              $this->add_column($column);
  70          }
  71  
  72          // All the filters defined by the entity can also be used as conditions.
  73          foreach ($this->get_all_filters() as $filter) {
  74              $this
  75                  ->add_filter($filter)
  76                  ->add_condition($filter);
  77          }
  78  
  79          return $this;
  80      }
  81  
  82      /**
  83       * Returns list of all available columns
  84       *
  85       * @return column[]
  86       */
  87      protected function get_all_columns(): array {
  88          $userenrolments = $this->get_table_alias('user_enrolments');
  89          $enrol = $this->get_table_alias('enrol');
  90  
  91          // Enrolment method column (Deprecated since Moodle 4.3, to remove in MDL-78118).
  92          $columns[] = (new column(
  93              'method',
  94              new lang_string('method', 'enrol'),
  95              $this->get_entity_name()
  96          ))
  97              ->add_joins($this->get_joins())
  98              ->set_type(column::TYPE_TEXT)
  99              ->add_fields("{$enrol}.enrol, {$enrol}.id")
 100              ->set_is_sortable(true)
 101              ->set_is_deprecated('See \'enrol:name\' for replacement')
 102              ->add_callback([enrolment_formatter::class, 'enrolment_name']);
 103  
 104          // Enrolment time created.
 105          $columns[] = (new column(
 106              'timecreated',
 107              new lang_string('timecreated', 'moodle'),
 108              $this->get_entity_name()
 109          ))
 110              ->add_joins($this->get_joins())
 111              ->set_type(column::TYPE_TIMESTAMP)
 112              ->add_field("{$userenrolments}.timecreated")
 113              ->set_is_sortable(true)
 114              ->add_callback([format::class, 'userdate']);
 115  
 116          // Enrolment time started.
 117          $columns[] = (new column(
 118              'timestarted',
 119              new lang_string('timestarted', 'enrol'),
 120              $this->get_entity_name()
 121          ))
 122              ->add_joins($this->get_joins())
 123              ->set_type(column::TYPE_TIMESTAMP)
 124              ->add_field("
 125                  CASE WHEN {$userenrolments}.timestart = 0
 126                       THEN {$userenrolments}.timecreated
 127                       ELSE {$userenrolments}.timestart
 128                   END", 'timestarted')
 129              ->set_is_sortable(true)
 130              ->add_callback([format::class, 'userdate']);
 131  
 132          // Enrolment time ended.
 133          $columns[] = (new column(
 134              'timeended',
 135              new lang_string('timeended', 'enrol'),
 136              $this->get_entity_name()
 137          ))
 138              ->add_joins($this->get_joins())
 139              ->set_type(column::TYPE_TIMESTAMP)
 140              ->add_field("{$userenrolments}.timeend")
 141              ->set_is_sortable(true)
 142              ->add_callback([format::class, 'userdate']);
 143  
 144          // Enrolment status.
 145          $columns[] = (new column(
 146              'status',
 147              new lang_string('status', 'moodle'),
 148              $this->get_entity_name()
 149          ))
 150              ->add_joins($this->get_joins())
 151              ->set_type(column::TYPE_TEXT)
 152              ->add_field($this->get_status_field_sql(), 'status')
 153              ->set_is_sortable(true)
 154              ->add_callback([enrolment_formatter::class, 'enrolment_status']);
 155  
 156          // Role column (Deprecated since Moodle 4.3, to remove in MDL-78118).
 157          $ctx = database::generate_alias();
 158          $ra = database::generate_alias();
 159          $r = database::generate_alias();
 160          $columns[] = (new column(
 161              'role',
 162              new lang_string('role', 'moodle'),
 163              $this->get_entity_name()
 164          ))
 165              ->add_joins($this->get_joins())
 166              ->add_join("LEFT JOIN {context} {$ctx}
 167                  ON {$ctx}.instanceid = {$enrol}.courseid AND {$ctx}.contextlevel = " . CONTEXT_COURSE)
 168              ->add_join("LEFT JOIN {role_assignments} {$ra}
 169                  ON {$ra}.contextid = {$ctx}.id AND {$ra}.userid = {$userenrolments}.userid")
 170              ->add_join("LEFT JOIN {role} {$r} ON {$r}.id = {$ra}.roleid")
 171              ->set_type(column::TYPE_TEXT)
 172              ->add_fields("{$r}.id, {$r}.name, {$r}.shortname, {$ctx}.instanceid")
 173              ->set_is_sortable(true, ["{$r}.shortname"])
 174              ->set_is_deprecated('See \'role:name\' for replacement')
 175              ->add_callback(static function(?string $value, stdClass $row): string {
 176                  if (!$row->id) {
 177                      return '';
 178                  }
 179                  $context = context_course::instance($row->instanceid);
 180                  return role_get_name($row, $context, ROLENAME_ALIAS);
 181              });
 182  
 183          return $columns;
 184      }
 185  
 186      /**
 187       * Generate SQL snippet suitable for returning enrolment status field
 188       *
 189       * @return string
 190       */
 191      private function get_status_field_sql(): string {
 192          $time = time();
 193          $userenrolments = $this->get_table_alias('user_enrolments');
 194          $enrol = $this->get_table_alias('enrol');
 195  
 196          return "
 197              CASE WHEN {$userenrolments}.status = " . ENROL_USER_ACTIVE . "
 198                   THEN CASE WHEN ({$userenrolments}.timestart > {$time})
 199                               OR ({$userenrolments}.timeend > 0 AND {$userenrolments}.timeend < {$time})
 200                               OR ({$enrol}.status = " . ENROL_INSTANCE_DISABLED . ")
 201                             THEN " . status_field::STATUS_NOT_CURRENT . "
 202                             ELSE " . status_field::STATUS_ACTIVE . "
 203                        END
 204                   ELSE {$userenrolments}.status
 205              END";
 206      }
 207  
 208      /**
 209       * Return list of all available filters
 210       *
 211       * @return filter[]
 212       */
 213      protected function get_all_filters(): array {
 214          $userenrolments = $this->get_table_alias('user_enrolments');
 215          $enrol = $this->get_table_alias('enrol');
 216  
 217          // Enrolment method (Deprecated since Moodle 4.3, to remove in MDL-78118).
 218          $enrolmentmethods = static function(): array {
 219              return array_map(static function(enrol_plugin $plugin): string {
 220                  return get_string('pluginname', 'enrol_' . $plugin->get_name());
 221              }, enrol_get_plugins(true));
 222          };
 223          $filters[] = (new filter(
 224              select::class,
 225              'method',
 226              new lang_string('method', 'enrol'),
 227              $this->get_entity_name(),
 228              "{$enrol}.enrol"
 229          ))
 230              ->add_joins($this->get_joins())
 231              ->set_is_deprecated('See \'enrol:plugin\' for replacement')
 232              ->set_options_callback($enrolmentmethods);
 233  
 234          // Enrolment time created.
 235          $filters[] = (new filter(
 236              date::class,
 237              'timecreated',
 238              new lang_string('timecreated', 'moodle'),
 239              $this->get_entity_name(),
 240              "{$userenrolments}.timecreated"
 241          ))
 242              ->add_joins($this->get_joins())
 243              ->set_limited_operators([
 244                  date::DATE_ANY,
 245                  date::DATE_NOT_EMPTY,
 246                  date::DATE_EMPTY,
 247                  date::DATE_RANGE,
 248                  date::DATE_LAST,
 249                  date::DATE_CURRENT,
 250              ]);
 251  
 252          // Enrolment time started.
 253          $filters[] = (new filter(
 254              date::class,
 255              'timestarted',
 256              new lang_string('timestarted', 'enrol'),
 257              $this->get_entity_name(),
 258              "CASE WHEN {$userenrolments}.timestart = 0
 259                            THEN {$userenrolments}.timecreated
 260                            ELSE {$userenrolments}.timestart
 261                        END"
 262          ))
 263              ->add_joins($this->get_joins())
 264              ->set_limited_operators([
 265                  date::DATE_ANY,
 266                  date::DATE_NOT_EMPTY,
 267                  date::DATE_EMPTY,
 268                  date::DATE_RANGE,
 269                  date::DATE_LAST,
 270                  date::DATE_CURRENT,
 271              ]);
 272  
 273          // Enrolment time ended.
 274          $filters[] = (new filter(
 275              date::class,
 276              'timeended',
 277              new lang_string('timeended', 'enrol'),
 278              $this->get_entity_name(),
 279              "{$userenrolments}.timeend"
 280          ))
 281              ->add_joins($this->get_joins())
 282              ->set_limited_operators([
 283                  date::DATE_ANY,
 284                  date::DATE_NOT_EMPTY,
 285                  date::DATE_EMPTY,
 286                  date::DATE_RANGE,
 287                  date::DATE_LAST,
 288                  date::DATE_CURRENT,
 289              ]);
 290  
 291          // Enrolment status.
 292          $filters[] = (new filter(
 293              select::class,
 294              'status',
 295              new lang_string('status', 'moodle'),
 296              $this->get_entity_name(),
 297              $this->get_status_field_sql()
 298          ))
 299              ->add_joins($this->get_joins())
 300              ->set_options(enrolment_formatter::enrolment_values());
 301  
 302          return $filters;
 303      }
 304  }