Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.
   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_admin\local\entities;
  18  
  19  use core_reportbuilder\local\filters\date;
  20  use core_reportbuilder\local\filters\duration;
  21  use core_reportbuilder\local\filters\select;
  22  use core_reportbuilder\local\filters\text;
  23  use core_reportbuilder\local\helpers\format;
  24  use lang_string;
  25  use core_reportbuilder\local\entities\base;
  26  use core_reportbuilder\local\report\column;
  27  use core_reportbuilder\local\report\filter;
  28  use stdClass;
  29  
  30  /**
  31   * Task log entity class implementation
  32   *
  33   * @package    core_admin
  34   * @copyright  2021 David Matamoros <davidmc@moodle.com>
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class task_log extends base {
  38  
  39      /** @var int Result success */
  40      protected const SUCCESS = 0;
  41  
  42      /** @var int Result failed */
  43      protected const FAILED = 1;
  44  
  45      /**
  46       * Database tables that this entity uses and their default aliases
  47       *
  48       * @return array
  49       */
  50      protected function get_default_table_aliases(): array {
  51          return ['task_log' => 'tl'];
  52      }
  53  
  54      /**
  55       * The default title for this entity in the list of columns/conditions/filters in the report builder
  56       *
  57       * @return lang_string
  58       */
  59      protected function get_default_entity_title(): lang_string {
  60          return new lang_string('entitytasklog', 'admin');
  61      }
  62  
  63      /**
  64       * The default machine-readable name for this entity that will be used in the internal names of the columns/filters
  65       *
  66       * @return string
  67       */
  68      protected function get_default_entity_name(): string {
  69          return 'task_log';
  70      }
  71  
  72      /**
  73       * Initialise the entity
  74       *
  75       * @return base
  76       */
  77      public function initialise(): base {
  78          $columns = $this->get_all_columns();
  79          foreach ($columns as $column) {
  80              $this->add_column($column);
  81          }
  82  
  83          $filters = $this->get_all_filters();
  84          foreach ($filters as $filter) {
  85              $this->add_filter($filter);
  86          }
  87  
  88          return $this;
  89      }
  90  
  91      /**
  92       * Returns list of all available columns
  93       *
  94       * @return column[]
  95       */
  96      protected function get_all_columns(): array {
  97  
  98          $tablealias = $this->get_table_alias('task_log');
  99  
 100          // Name column.
 101          $columns[] = (new column(
 102              'name',
 103              new lang_string('name'),
 104              $this->get_entity_name()
 105          ))
 106              ->add_joins($this->get_joins())
 107              ->set_type(column::TYPE_TEXT)
 108              ->add_field("$tablealias.classname")
 109              ->set_is_sortable(true)
 110              ->add_callback(static function(string $value): string {
 111                  $output = '';
 112                  if (class_exists($value)) {
 113                      $task = new $value;
 114                      if ($task instanceof \core\task\scheduled_task) {
 115                          $output = $task->get_name();
 116                      }
 117                  }
 118                  $output .= \html_writer::tag('div', "\\{$value}", [
 119                      'class' => 'task-class',
 120                  ]);
 121                  return $output;
 122              });
 123  
 124          // Type column.
 125          $columns[] = (new column(
 126              'type',
 127              new lang_string('tasktype', 'admin'),
 128              $this->get_entity_name()
 129          ))
 130              ->add_joins($this->get_joins())
 131              ->set_type(column::TYPE_INTEGER)
 132              ->add_field("{$tablealias}.type")
 133              ->set_is_sortable(true)
 134              ->add_callback(static function(int $value): string {
 135                  if (\core\task\database_logger::TYPE_SCHEDULED === $value) {
 136                      return get_string('task_type:scheduled', 'admin');
 137                  }
 138                  return get_string('task_type:adhoc', 'admin');
 139              });
 140  
 141          // Start time column.
 142          $columns[] = (new column(
 143              'starttime',
 144              new lang_string('task_starttime', 'admin'),
 145              $this->get_entity_name()
 146          ))
 147              ->add_joins($this->get_joins())
 148              ->set_type(column::TYPE_TIMESTAMP)
 149              ->add_field("{$tablealias}.timestart")
 150              ->set_is_sortable(true)
 151              ->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
 152  
 153          // Duration column.
 154          $columns[] = (new column(
 155              'duration',
 156              new lang_string('task_duration', 'admin'),
 157              $this->get_entity_name()
 158          ))
 159              ->add_joins($this->get_joins())
 160              ->set_type(column::TYPE_FLOAT)
 161              ->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
 162              ->set_is_sortable(true)
 163              ->add_callback(static function(float $value): string {
 164                  $duration = round($value, 2);
 165                  if (empty($duration)) {
 166                      // The format_time function returns 'now' when the difference is exactly 0.
 167                      // Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
 168                      return '0 ' . get_string('secs', 'moodle');
 169                  }
 170                  return format_time($duration);
 171              });
 172  
 173          // Hostname column.
 174          $columns[] = (new column(
 175              'hostname',
 176              new lang_string('hostname', 'admin'),
 177              $this->get_entity_name()
 178          ))
 179              ->add_joins($this->get_joins())
 180              ->set_type(column::TYPE_TEXT)
 181              ->add_field("$tablealias.hostname")
 182              ->set_is_sortable(true);
 183  
 184          // PID column.
 185          $columns[] = (new column(
 186              'pid',
 187              new lang_string('pid', 'admin'),
 188              $this->get_entity_name()
 189          ))
 190              ->add_joins($this->get_joins())
 191              ->set_type(column::TYPE_INTEGER)
 192              ->add_field("{$tablealias}.pid")
 193              ->set_is_sortable(true);
 194  
 195          // Database column.
 196          $columns[] = (new column(
 197              'database',
 198              new lang_string('task_dbstats', 'admin'),
 199              $this->get_entity_name()
 200          ))
 201              ->add_joins($this->get_joins())
 202              ->set_type(column::TYPE_INTEGER)
 203              ->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
 204              ->set_is_sortable(true)
 205              ->add_callback(static function(int $value, stdClass $row): string {
 206                  $output = '';
 207                  $output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
 208                  $output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
 209                  return $output;
 210              });
 211  
 212          // Result column.
 213          $columns[] = (new column(
 214              'result',
 215              new lang_string('task_result', 'admin'),
 216              $this->get_entity_name()
 217          ))
 218              ->add_joins($this->get_joins())
 219              ->set_type(column::TYPE_INTEGER)
 220              ->add_field("$tablealias.result")
 221              ->set_is_sortable(true)
 222              ->add_callback(static function(int $value): string {
 223                  if ($value) {
 224                      return get_string('task_result:failed', 'admin');
 225                  }
 226                  return get_string('success');
 227              });
 228  
 229          return $columns;
 230      }
 231  
 232      /**
 233       * Return list of all available filters
 234       *
 235       * @return filter[]
 236       */
 237      protected function get_all_filters(): array {
 238          $filters = [];
 239  
 240          $tablealias = $this->get_table_alias('task_log');
 241  
 242          // Name filter (Filter by classname).
 243          $filters[] = (new filter(
 244              text::class,
 245              'name',
 246              new lang_string('classname', 'tool_task'),
 247              $this->get_entity_name(),
 248              "{$tablealias}.classname"
 249          ))
 250              ->add_joins($this->get_joins());
 251  
 252          // Output filter (Filter by task output).
 253          $filters[] = (new filter(
 254              text::class,
 255              'output',
 256              new lang_string('task_logoutput', 'admin'),
 257              $this->get_entity_name(),
 258              "{$tablealias}.output"
 259          ))
 260              ->add_joins($this->get_joins());
 261  
 262          // Result filter.
 263          $filters[] = (new filter(
 264              select::class,
 265              'result',
 266              new lang_string('task_result', 'admin'),
 267              $this->get_entity_name(),
 268              "{$tablealias}.result"
 269          ))
 270              ->add_joins($this->get_joins())
 271              ->set_options([
 272                  self::SUCCESS => get_string('success'),
 273                  self::FAILED => get_string('task_result:failed', 'admin'),
 274              ]);
 275  
 276          // Start time filter.
 277          $filters[] = (new filter(
 278              date::class,
 279              'timestart',
 280              new lang_string('task_starttime', 'admin'),
 281              $this->get_entity_name(),
 282              "{$tablealias}.timestart"
 283          ))
 284              ->add_joins($this->get_joins())
 285              ->set_limited_operators([
 286                  date::DATE_ANY,
 287                  date::DATE_RANGE,
 288                  date::DATE_PREVIOUS,
 289                  date::DATE_CURRENT,
 290              ]);
 291  
 292          // Duration filter.
 293          $filters[] = (new filter(
 294              duration::class,
 295              'duration',
 296              new lang_string('task_duration', 'admin'),
 297              $this->get_entity_name(),
 298              "$tablealias}.timeend - {$tablealias}.timestart"
 299          ))
 300              ->add_joins($this->get_joins());
 301  
 302          return $filters;
 303      }
 304  }