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 400 and 402]

   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_reportbuilder\local\systemreports;
  20  
  21  use context;
  22  use lang_string;
  23  use moodle_url;
  24  use pix_icon;
  25  use stdClass;
  26  use core_reportbuilder\permission;
  27  use core_reportbuilder\system_report;
  28  use core_reportbuilder\local\entities\user;
  29  use core_reportbuilder\local\filters\date;
  30  use core_reportbuilder\local\filters\text;
  31  use core_reportbuilder\local\helpers\format;
  32  use core_reportbuilder\local\models\report;
  33  use core_reportbuilder\local\models\schedule;
  34  use core_reportbuilder\local\report\action;
  35  use core_reportbuilder\local\report\column;
  36  use core_reportbuilder\local\report\filter;
  37  use core_reportbuilder\output\schedule_name_editable;
  38  
  39  /**
  40   * Report schedules list
  41   *
  42   * @package     core_reportbuilder
  43   * @copyright   2021 Paul Holden <paulh@moodle.com>
  44   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  45   */
  46  class report_schedules extends system_report {
  47  
  48      /**
  49       * The name of our internal report entity
  50       *
  51       * @return string
  52       */
  53      private function get_schedule_entity_name(): string {
  54          return 'schedule';
  55      }
  56  
  57      /**
  58       * Initialise the report
  59       */
  60      protected function initialise(): void {
  61          $this->set_main_table(schedule::TABLE, 'sc');
  62          $this->add_join('JOIN {' . report::TABLE . '} rb ON rb.id = sc.reportid');
  63  
  64          $this->add_base_condition_simple('sc.reportid', $this->get_parameter('reportid', 0, PARAM_INT));
  65  
  66          // Select fields required for actions, permission checks, and row class callbacks.
  67          $this->add_base_fields('sc.id, sc.name, sc.enabled, rb.contextid');
  68  
  69          // Join user entity for "User modified" column.
  70          $entityuser = new user();
  71          $entityuseralias = $entityuser->get_table_alias('user');
  72  
  73          $this->add_entity($entityuser
  74              ->add_join("JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = sc.usermodified")
  75          );
  76  
  77          // Define our internal entity for schedule elements.
  78          $this->annotate_entity($this->get_schedule_entity_name(),
  79              new lang_string('schedules', 'core_reportbuilder'));
  80  
  81          $this->add_columns();
  82          $this->add_filters();
  83          $this->add_actions();
  84  
  85          $this->set_downloadable(false);
  86      }
  87  
  88      /**
  89       * Ensure we can view the report
  90       *
  91       * @return bool
  92       */
  93      protected function can_view(): bool {
  94          return permission::can_view_reports_list();
  95      }
  96  
  97      /**
  98       * Dim the table row for disabled schedules
  99       *
 100       * @param stdClass $row
 101       * @return string
 102       */
 103      public function get_row_class(stdClass $row): string {
 104          return $row->enabled ? '' : 'text-muted';
 105      }
 106  
 107      /**
 108       * Add columns to report
 109       */
 110      protected function add_columns(): void {
 111          $tablealias = $this->get_main_table_alias();
 112  
 113          // Enable toggle column.
 114          $this->add_column((new column(
 115              'enabled',
 116              null,
 117              $this->get_schedule_entity_name()
 118          ))
 119              ->set_type(column::TYPE_BOOLEAN)
 120              ->add_fields("{$tablealias}.enabled, {$tablealias}.id")
 121              ->set_is_sortable(false)
 122              ->set_callback(static function(bool $enabled, stdClass $row): string {
 123                  global $PAGE;
 124  
 125                  $renderer = $PAGE->get_renderer('core_reportbuilder');
 126                  $attributes = [
 127                      ['name' => 'id', 'value' => $row->id],
 128                      ['name' => 'action', 'value' => 'schedule-toggle'],
 129                      ['name' => 'state', 'value' => $row->enabled],
 130                  ];
 131                  $label = $row->enabled ? get_string('disableschedule', 'core_reportbuilder')
 132                      : get_string('enableschedule', 'core_reportbuilder');
 133                  return $renderer->render_from_template('core/toggle', [
 134                      'id' => 'schedule-toggle-' . $row->id,
 135                      'checked' => $row->enabled,
 136                      'dataattributes' => $attributes,
 137                      'label' => $label,
 138                      'labelclasses' => 'sr-only'
 139                  ]);
 140              })
 141          );
 142  
 143          // Report name column.
 144          $this->add_column((new column(
 145              'name',
 146              new lang_string('name'),
 147              $this->get_schedule_entity_name()
 148          ))
 149              ->set_type(column::TYPE_TEXT)
 150              // We need enough fields to re-create the persistent and pass to the editable component.
 151              ->add_fields("{$tablealias}.id, {$tablealias}.name, {$tablealias}.reportid")
 152              ->set_is_sortable(true, ["{$tablealias}.name"])
 153              ->add_callback(function(string $value, stdClass $schedule): string {
 154                  global $PAGE;
 155  
 156                  $editable = new schedule_name_editable(0, new schedule(0, $schedule));
 157                  return $editable->render($PAGE->get_renderer('core'));
 158              })
 159          );
 160  
 161          // Time scheduled column.
 162          $this->add_column((new column(
 163              'timescheduled',
 164              new lang_string('startingfrom'),
 165              $this->get_schedule_entity_name()
 166          ))
 167              ->set_type(column::TYPE_TIMESTAMP)
 168              ->add_fields("{$tablealias}.timescheduled")
 169              ->set_is_sortable(true)
 170              ->add_callback([format::class, 'userdate'])
 171          );
 172  
 173          // Time last sent column.
 174          $this->add_column((new column(
 175              'timelastsent',
 176              new lang_string('timelastsent', 'core_reportbuilder'),
 177              $this->get_schedule_entity_name()
 178          ))
 179              ->set_type(column::TYPE_TIMESTAMP)
 180              ->add_fields("{$tablealias}.timelastsent")
 181              ->set_is_sortable(true)
 182              ->add_callback(static function(int $timelastsent, stdClass $row): string {
 183                  if ($timelastsent === 0) {
 184                      return get_string('never');
 185                  }
 186  
 187                  return format::userdate($timelastsent, $row);
 188              })
 189          );
 190  
 191          // Format column.
 192          $this->add_column((new column(
 193              'format',
 194              new lang_string('format'),
 195              $this->get_schedule_entity_name()
 196          ))
 197              ->set_type(column::TYPE_TEXT)
 198              ->add_fields("{$tablealias}.format")
 199              ->set_is_sortable(true)
 200              ->add_callback(static function(string $format): string {
 201                  if (get_string_manager()->string_exists('dataformat', 'dataformat_' . $format)) {
 202                      return get_string('dataformat', 'dataformat_' . $format);
 203                  } else {
 204                      return $format;
 205                  }
 206              })
 207          );
 208  
 209          // Time created column.
 210          $this->add_column((new column(
 211              'timecreated',
 212              new lang_string('timecreated', 'core_reportbuilder'),
 213              $this->get_schedule_entity_name()
 214          ))
 215              ->set_type(column::TYPE_TIMESTAMP)
 216              ->add_fields("{$tablealias}.timecreated")
 217              ->set_is_sortable(true)
 218              ->add_callback([format::class, 'userdate'])
 219          );
 220  
 221          // Time modified column.
 222          $this->add_column((new column(
 223              'timemodified',
 224              new lang_string('timemodified', 'core_reportbuilder'),
 225              $this->get_schedule_entity_name()
 226          ))
 227              ->set_type(column::TYPE_TIMESTAMP)
 228              ->add_fields("{$tablealias}.timemodified")
 229              ->set_is_sortable(true)
 230              ->add_callback([format::class, 'userdate'])
 231          );
 232  
 233          // The user who modified the schedule.
 234          $this->add_column_from_entity('user:fullname')
 235              ->set_title(new lang_string('usermodified', 'core_reportbuilder'));
 236  
 237          // Initial sorting.
 238          $this->set_initial_sort_column('schedule:timecreated', SORT_DESC);
 239      }
 240  
 241      /**
 242       * Add filters to report
 243       */
 244      protected function add_filters(): void {
 245          $tablealias = $this->get_main_table_alias();
 246  
 247          // Name filter.
 248          $this->add_filter((new filter(
 249              text::class,
 250              'name',
 251              new lang_string('name'),
 252              $this->get_schedule_entity_name(),
 253              "{$tablealias}.name"
 254          )));
 255  
 256          // Time created filter.
 257          $this->add_filter((new filter(
 258              date::class,
 259              'timelastsent',
 260              new lang_string('timelastsent', 'core_reportbuilder'),
 261              $this->get_schedule_entity_name(),
 262              "{$tablealias}.timelastsent"
 263          ))
 264              ->set_limited_operators([
 265                  date::DATE_ANY,
 266                  date::DATE_EMPTY,
 267                  date::DATE_RANGE,
 268                  date::DATE_PREVIOUS,
 269                  date::DATE_CURRENT,
 270              ])
 271          );
 272  
 273      }
 274  
 275      /**
 276       * Add actions to report
 277       */
 278      protected function add_actions(): void {
 279          // Edit action.
 280          $this->add_action(new action(
 281              new moodle_url('#'),
 282              new pix_icon('t/edit', ''),
 283              ['data-action' => 'schedule-edit', 'data-schedule-id' => ':id'],
 284              false,
 285              new lang_string('editscheduledetails', 'core_reportbuilder')
 286          ));
 287  
 288          // Send now action.
 289          $this->add_action((new action(
 290              new moodle_url('#'),
 291              new pix_icon('t/email', ''),
 292              ['data-action' => 'schedule-send', 'data-schedule-id' => ':id', 'data-schedule-name' => ':name'],
 293              false,
 294              new lang_string('sendschedule', 'core_reportbuilder')
 295          ))
 296              ->add_callback(function(stdClass $row): bool {
 297  
 298                  // Ensure data name attribute is properly formatted.
 299                  $row->name = (new schedule(0, $row))->get_formatted_name(
 300                      context::instance_by_id($row->contextid));
 301  
 302                  return true;
 303              })
 304          );
 305  
 306          // Delete action.
 307          $this->add_action((new action(
 308              new moodle_url('#'),
 309              new pix_icon('t/delete', ''),
 310              ['data-action' => 'schedule-delete', 'data-schedule-id' => ':id', 'data-schedule-name' => ':name'],
 311              false,
 312              new lang_string('deleteschedule', 'core_reportbuilder')
 313          ))
 314              ->add_callback(function(stdClass $row): bool {
 315  
 316                  // Ensure data name attribute is properly formatted.
 317                  $row->name = (new schedule(0, $row))->get_formatted_name(
 318                      context::instance_by_id($row->contextid));
 319  
 320                  return true;
 321              })
 322          );
 323      }
 324  }