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.
   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  namespace core_cohort\reportbuilder\local\systemreports;
  18  
  19  use context;
  20  use context_coursecat;
  21  use context_system;
  22  use core_cohort\reportbuilder\local\entities\cohort;
  23  use core_reportbuilder\local\helpers\database;
  24  use core_reportbuilder\local\report\action;
  25  use core_reportbuilder\local\report\column;
  26  use html_writer;
  27  use lang_string;
  28  use moodle_url;
  29  use pix_icon;
  30  use core_reportbuilder\system_report;
  31  use stdClass;
  32  
  33  /**
  34   * Cohorts system report class implementation
  35   *
  36   * @package    core_cohort
  37   * @copyright  2021 David Matamoros <davidmc@moodle.com>
  38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class cohorts extends system_report {
  41  
  42      /**
  43       * Initialise report, we need to set the main table, load our entities and set columns/filters
  44       */
  45      protected function initialise(): void {
  46          // Our main entity, it contains all of the column definitions that we need.
  47          $cohortentity = new cohort();
  48          $entitymainalias = $cohortentity->get_table_alias('cohort');
  49  
  50          $this->set_main_table('cohort', $entitymainalias);
  51          $this->add_entity($cohortentity);
  52  
  53          // Any columns required by actions should be defined here to ensure they're always available.
  54          $this->add_base_fields("{$entitymainalias}.id, {$entitymainalias}.contextid, {$entitymainalias}.visible, " .
  55              "{$entitymainalias}.component");
  56  
  57          // Check if report needs to show a specific category.
  58          $contextid = $this->get_parameter('contextid', 0, PARAM_INT);
  59          $showall = $this->get_parameter('showall', true, PARAM_BOOL);
  60          if (!$showall) {
  61              $paramcontextid = database::generate_param_name();
  62              $this->add_base_condition_sql("{$entitymainalias}.contextid = :$paramcontextid", [$paramcontextid => $contextid]);
  63          }
  64  
  65          // Now we can call our helper methods to add the content we want to include in the report.
  66          $this->add_columns($cohortentity);
  67          $this->add_filters();
  68          $this->add_actions();
  69  
  70          // Set if report can be downloaded.
  71          $this->set_downloadable(false);
  72      }
  73  
  74      /**
  75       * Validates access to view this report
  76       *
  77       * @return bool
  78       */
  79      protected function can_view(): bool {
  80          $contextid = $this->get_parameter('contextid', 0, PARAM_INT);
  81          if ($contextid) {
  82              $context = context::instance_by_id($contextid, MUST_EXIST);
  83          } else {
  84              $context = context_system::instance();
  85          }
  86  
  87          return has_any_capability(['moodle/cohort:manage', 'moodle/cohort:view'], $context);
  88      }
  89  
  90      /**
  91       * Adds the columns we want to display in the report
  92       *
  93       * They are provided by the entities we previously added in the {@see initialise} method, referencing each by their
  94       * unique identifier. If custom columns are needed just for this report, they can be defined here.
  95       *
  96       * @param cohort $cohortentity
  97       */
  98      public function add_columns(cohort $cohortentity): void {
  99  
 100          $entitymainalias = $cohortentity->get_table_alias('cohort');
 101          $showall = $this->get_parameter('showall', false, PARAM_BOOL);
 102  
 103          // Category column. An extra callback is appended in order to extend the current column formatting.
 104          if ($showall) {
 105              $this->add_column_from_entity('cohort:context')
 106                  ->add_callback(static function(string $value, stdClass $cohort): string {
 107                      $context = context::instance_by_id($cohort->contextid);
 108                      if ($context instanceof context_coursecat) {
 109                          return html_writer::link(new moodle_url('/cohort/index.php',
 110                              ['contextid' => $cohort->contextid]), $value);
 111                      }
 112  
 113                      return $value;
 114                  });
 115          }
 116  
 117          // Name column using the inplace editable component.
 118          $this->add_column(new column(
 119              'editablename',
 120              new lang_string('name', 'core_cohort'),
 121              $cohortentity->get_entity_name()
 122          ))
 123              ->set_type(column::TYPE_TEXT)
 124              ->set_is_sortable(true)
 125              ->add_fields("{$entitymainalias}.name, {$entitymainalias}.id, {$entitymainalias}.contextid")
 126              ->add_callback(static function(string $name, stdClass $cohort): string {
 127                  global $OUTPUT, $PAGE;
 128                  $renderer = $PAGE->get_renderer('core');
 129  
 130                  $template = new \core_cohort\output\cohortname($cohort);
 131                  return $renderer->render_from_template('core/inplace_editable', $template->export_for_template($OUTPUT));
 132              });
 133  
 134          // ID Number column using the inplace editable component.
 135          $this->add_column(new column(
 136              'editableidnumber',
 137              new lang_string('idnumber', 'core_cohort'),
 138              $cohortentity->get_entity_name()
 139          ))
 140              ->set_type(column::TYPE_TEXT)
 141              ->set_is_sortable(true)
 142              ->add_fields("{$entitymainalias}.idnumber, {$entitymainalias}.id, {$entitymainalias}.contextid")
 143              ->add_callback(static function(?string $idnumber, stdClass $cohort): string {
 144                  global $OUTPUT, $PAGE;
 145                  $renderer = $PAGE->get_renderer('core');
 146  
 147                  $template = new \core_cohort\output\cohortidnumber($cohort);
 148                  return $renderer->render_from_template('core/inplace_editable', $template->export_for_template($OUTPUT));
 149              });
 150  
 151          // Description column.
 152          $this->add_column_from_entity('cohort:description');
 153  
 154          // Cohort size column using a custom SQL query to count cohort members.
 155          $cm = database::generate_param_name();
 156          $sql = "(SELECT count($cm.id) as memberscount
 157                  FROM {cohort_members} $cm
 158                  WHERE $cm.cohortid = {$entitymainalias}.id)";
 159          $this->add_column(new column(
 160              'memberscount',
 161              new lang_string('memberscount', 'cohort'),
 162              $cohortentity->get_entity_name()
 163          ))
 164              ->set_type(column::TYPE_INTEGER)
 165              ->set_is_sortable(true)
 166              ->add_field($sql, 'memberscount');
 167  
 168          // Component column. Override the display name of a column.
 169          $this->add_column_from_entity('cohort:component')
 170              ->set_title(new lang_string('source', 'core_plugin'));
 171  
 172          // It's possible to set a default initial sort direction for one column.
 173          $this->set_initial_sort_column('cohort:editablename', SORT_ASC);
 174      }
 175  
 176      /**
 177       * Adds the filters we want to display in the report
 178       *
 179       * They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
 180       * unique identifier
 181       */
 182      protected function add_filters(): void {
 183          $filters = [
 184              'cohort:name',
 185              'cohort:idnumber',
 186              'cohort:description',
 187          ];
 188          $this->add_filters_from_entities($filters);
 189      }
 190  
 191      /**
 192       * Add the system report actions. An extra column will be appended to each row, containing all actions added here
 193       *
 194       * Note the use of ":id" placeholder which will be substituted according to actual values in the row
 195       */
 196      protected function add_actions(): void {
 197  
 198          $contextid = $this->get_parameter('contextid', 0, PARAM_INT);
 199          $showall = $this->get_parameter('showall', true, PARAM_BOOL);
 200          $returnurl = (new moodle_url('/cohort/index.php',
 201              ['id' => ':id', 'contextid' => $contextid, 'showall' => $showall]))->out(false);
 202  
 203          // Hide action. It will be only shown if the property 'visible' is true and user has 'moodle/cohort:manage' capabillity.
 204          $this->add_action((new action(
 205              new moodle_url('/cohort/edit.php', ['id' => ':id', 'sesskey' => sesskey(), 'hide' => 1, 'returnurl' => $returnurl]),
 206              new pix_icon('t/show', '', 'core'),
 207              [],
 208              false,
 209              new lang_string('hide')
 210          ))->add_callback(function(stdClass $row): bool {
 211              return empty($row->component) && $row->visible
 212                  && has_capability('moodle/cohort:manage', context::instance_by_id($row->contextid));
 213          }));
 214  
 215          // Show action. It will be only shown if the property 'visible' is false and user has 'moodle/cohort:manage' capabillity.
 216          $this->add_action((new action(
 217              new moodle_url('/cohort/edit.php', ['id' => ':id', 'sesskey' => sesskey(), 'show' => 1, 'returnurl' => $returnurl]),
 218              new pix_icon('t/hide', '', 'core'),
 219              [],
 220              false,
 221              new lang_string('show')
 222          ))->add_callback(function(stdClass $row): bool {
 223              return empty($row->component) && !$row->visible
 224                  && has_capability('moodle/cohort:manage', context::instance_by_id($row->contextid));
 225          }));
 226  
 227          // Edit action. It will be only shown if user has 'moodle/cohort:manage' capabillity.
 228          $this->add_action((new action(
 229              new moodle_url('/cohort/edit.php', ['id' => ':id', 'returnurl' => $returnurl]),
 230              new pix_icon('t/edit', '', 'core'),
 231              [],
 232              false,
 233              new lang_string('edit')
 234          ))->add_callback(function(stdClass $row): bool {
 235              return empty($row->component) && has_capability('moodle/cohort:manage', context::instance_by_id($row->contextid));
 236          }));
 237  
 238          // Delete action. It will be only shown if user has 'moodle/cohort:manage' capabillity.
 239          $this->add_action((new action(
 240              new moodle_url('/cohort/edit.php', ['id' => ':id', 'delete' => 1, 'returnurl' => $returnurl]),
 241              new pix_icon('t/delete', '', 'core'),
 242              [],
 243              false,
 244              new lang_string('delete')
 245          ))->add_callback(function(stdClass $row): bool {
 246              return empty($row->component) && has_capability('moodle/cohort:manage', context::instance_by_id($row->contextid));
 247          }));
 248  
 249          // Assign members to cohort action. It will be only shown if user has 'moodle/cohort:assign' capabillity.
 250          $this->add_action((new action(
 251              new moodle_url('/cohort/assign.php', ['id' => ':id', 'returnurl' => $returnurl]),
 252              new pix_icon('i/users', '', 'core'),
 253              [],
 254              false,
 255              new lang_string('assign', 'core_cohort')
 256          ))->add_callback(function(stdClass $row): bool {
 257              return empty($row->component) && has_capability('moodle/cohort:assign', context::instance_by_id($row->contextid));
 258          }));
 259      }
 260  
 261      /**
 262       * CSS class for the row
 263       *
 264       * @param stdClass $row
 265       * @return string
 266       */
 267      public function get_row_class(stdClass $row): string {
 268          return (!$row->visible) ? 'text-muted' : '';
 269      }
 270  }