Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * Output rendering for the plugin.
  20   *
  21   * @package     tool_task
  22   * @copyright   2014 Damyon Wiese
  23   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  use core\task\scheduled_task;
  29  
  30  
  31  /**
  32   * Implements the plugin renderer
  33   *
  34   * @copyright 2014 Damyon Wiese
  35   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class tool_task_renderer extends plugin_renderer_base {
  38      /**
  39       * This function will render one beautiful table with all the scheduled tasks.
  40       *
  41       * @param \core\task\scheduled_task[] $tasks - list of all scheduled tasks.
  42       * @param string $lastchanged (optional) the last task edited. Gets highlighted in teh table.
  43       * @return string HTML to output.
  44       */
  45      public function scheduled_tasks_table($tasks, $lastchanged = '') {
  46          global $CFG;
  47  
  48          $showloglink = \core\task\logmanager::has_log_report();
  49  
  50          $table = new html_table();
  51          $table->caption = get_string('scheduledtasks', 'tool_task');
  52          $table->head = [
  53              get_string('name'),
  54              get_string('component', 'tool_task'),
  55              get_string('edit'),
  56              get_string('logs'),
  57              get_string('lastruntime', 'tool_task'),
  58              get_string('nextruntime', 'tool_task'),
  59              get_string('taskscheduleminute', 'tool_task'),
  60              get_string('taskschedulehour', 'tool_task'),
  61              get_string('taskscheduleday', 'tool_task'),
  62              get_string('taskscheduledayofweek', 'tool_task'),
  63              get_string('taskschedulemonth', 'tool_task'),
  64              get_string('faildelay', 'tool_task'),
  65              get_string('default', 'tool_task'),
  66          ];
  67  
  68          $table->attributes['class'] = 'admintable generaltable';
  69          $table->colclasses = [];
  70  
  71          if (!$showloglink) {
  72              // Hide the log links.
  73              $table->colclasses['3'] = 'hidden';
  74          }
  75  
  76          $data = [];
  77          $yes = get_string('yes');
  78          $no = get_string('no');
  79          $canruntasks = \core\task\manager::is_runnable();
  80          foreach ($tasks as $task) {
  81              $classname = get_class($task);
  82              $defaulttask = \core\task\manager::get_default_scheduled_task($classname, false);
  83  
  84              $customised = $task->is_customised() ? $no : $yes;
  85              if (empty($CFG->preventscheduledtaskchanges) && !$task->is_overridden()) {
  86                  $configureurl = new moodle_url('/admin/tool/task/scheduledtasks.php',
  87                          ['action' => 'edit', 'task' => $classname]);
  88                  $editlink = $this->output->action_icon($configureurl, new pix_icon('t/edit',
  89                          get_string('edittaskschedule', 'tool_task', $task->get_name())));
  90              } else {
  91                  $editlink = $this->render(new pix_icon('t/locked',
  92                          get_string('scheduledtaskchangesdisabled', 'tool_task')));
  93              }
  94  
  95              $loglink = '';
  96              if ($showloglink) {
  97                  $loglink = $this->output->action_icon(
  98                      \core\task\logmanager::get_url_for_task_class($classname),
  99                      new pix_icon('e/file-text', get_string('viewlogs', 'tool_task', $task->get_name())
 100                  ));
 101              }
 102  
 103              $namecellcontent = $task->get_name() . "\n" .
 104                  html_writer::span('\\' . $classname, 'task-class text-ltr');
 105              if ($task->is_overridden()) {
 106                  // Let the user know the scheduled task is defined in config.
 107                  $namecellcontent .= "\n" . html_writer::div(get_string('configoverride', 'admin'), 'alert-info');
 108              }
 109              $namecell = new html_table_cell($namecellcontent);
 110              $namecell->header = true;
 111  
 112              $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
 113              $plugindisabled = $plugininfo && $plugininfo->is_enabled() === false &&
 114                      !$task->get_run_if_component_disabled();
 115              $disabled = $plugindisabled || $task->get_disabled();
 116  
 117              $runnow = '';
 118              if (!$plugindisabled && get_config('tool_task', 'enablerunnow') && $canruntasks ) {
 119                  $runnow = html_writer::div(html_writer::link(
 120                          new moodle_url('/admin/tool/task/schedule_task.php',
 121                              ['task' => $classname]),
 122                          get_string('runnow', 'tool_task')), 'task-runnow');
 123              }
 124  
 125              $faildelaycell = new html_table_cell($task->get_fail_delay());
 126              if ($task->get_fail_delay()) {
 127                  $faildelaycell->text .= html_writer::div(html_writer::link(
 128                          new moodle_url('/admin/tool/task/clear_fail_delay.php',
 129                                  ['task' => $classname, 'sesskey' => sesskey()]),
 130                          get_string('clear')), 'task-clearfaildelay');
 131                  $faildelaycell->attributes['class'] = 'table-danger';
 132              }
 133  
 134              $row = new html_table_row([
 135                          $namecell,
 136                          new html_table_cell($this->component_name($task->get_component())),
 137                          new html_table_cell($editlink),
 138                          new html_table_cell($loglink),
 139                          new html_table_cell($this->last_run_time($task) . $runnow),
 140                          new html_table_cell($this->next_run_time($task)),
 141                          $this->time_cell($task->get_minute(), $defaulttask->get_minute()),
 142                          $this->time_cell($task->get_hour(), $defaulttask->get_hour()),
 143                          $this->time_cell($task->get_day(), $defaulttask->get_day()),
 144                          $this->time_cell($task->get_day_of_week(), $defaulttask->get_day_of_week()),
 145                          $this->time_cell($task->get_month(), $defaulttask->get_month()),
 146                          $faildelaycell,
 147                          new html_table_cell($customised)]);
 148  
 149              $classes = [];
 150              if ($disabled) {
 151                  $classes[] = 'disabled';
 152              }
 153              if (get_class($task) == $lastchanged) {
 154                  $classes[] = 'table-primary';
 155              }
 156              $row->attributes['class'] = implode(' ', $classes);
 157              $data[] = $row;
 158          }
 159          $table->data = $data;
 160          if ($lastchanged) {
 161              // IE does not support this, and the ancient version of Firefox we use for Behat
 162              // has the method, but then errors on 'centre'. So, just try to scroll, and if it fails, don't care.
 163              $this->page->requires->js_init_code(
 164                      'try{document.querySelector("tr.table-primary").scrollIntoView({block: "center"});}catch(e){}');
 165          }
 166          return html_writer::table($table);
 167      }
 168  
 169      /**
 170       * Nicely display the name of a component, with its disabled status and internal name.
 171       *
 172       * @param string $component component name, e.g. 'core' or 'mod_forum'.
 173       * @return string HTML.
 174       */
 175      public function component_name(string $component): string {
 176          list($type) = core_component::normalize_component($component);
 177          if ($type === 'core') {
 178              return get_string('corecomponent', 'tool_task');
 179          }
 180  
 181          $plugininfo = core_plugin_manager::instance()->get_plugin_info($component);
 182          if (!$plugininfo) {
 183              return $component;
 184          }
 185  
 186          $plugininfo->init_display_name();
 187  
 188          $componentname = $plugininfo->displayname;
 189          if ($plugininfo->is_enabled() === false) {
 190              $componentname .= ' ' . html_writer::span(
 191                              get_string('disabled', 'tool_task'), 'badge badge-secondary');
 192          }
 193          $componentname .= "\n" . html_writer::span($plugininfo->component, 'task-class text-ltr');
 194  
 195          return $componentname;
 196      }
 197  
 198      /**
 199       * Standard display of a tasks last run time.
 200       *
 201       * @param scheduled_task $task
 202       * @return string HTML.
 203       */
 204      public function last_run_time(scheduled_task $task): string {
 205          if ($task->get_last_run_time()) {
 206              return userdate($task->get_last_run_time());
 207          } else {
 208              return get_string('never');
 209          }
 210      }
 211  
 212      /**
 213       * Standard display of a tasks next run time.
 214       *
 215       * @param scheduled_task $task
 216       * @return string HTML.
 217       */
 218      public function next_run_time(scheduled_task $task): string {
 219          $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
 220  
 221          $nextrun = $task->get_next_run_time();
 222          if ($plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled()) {
 223              $nextrun = get_string('plugindisabled', 'tool_task');
 224          } else if ($task->get_disabled()) {
 225              $nextrun = get_string('taskdisabled', 'tool_task');
 226          } else if ($nextrun > time()) {
 227              $nextrun = userdate($nextrun);
 228          } else {
 229              $nextrun = get_string('asap', 'tool_task');
 230          }
 231  
 232          return $nextrun;
 233      }
 234  
 235      /**
 236       * Get a table cell to show one time, comparing it to the default.
 237       *
 238       * @param string $current the current setting.
 239       * @param string $default the default setting from the db/tasks.php file.
 240       * @return html_table_cell for use in the table.
 241       */
 242      protected function time_cell(string $current, string $default): html_table_cell {
 243          $cell = new html_table_cell($current);
 244          // Cron-style values must always be LTR.
 245          $cell->attributes['class'] = 'text-ltr';
 246  
 247          // If the current value is default, that is all we want to do.
 248          if ($default === '*') {
 249              if ($current === '*') {
 250                  return $cell;
 251              }
 252          } else if ($default === 'R' ) {
 253              if (is_numeric($current)) {
 254                  return $cell;
 255              }
 256          } else {
 257              if ($default === $current) {
 258                  return $cell;
 259              }
 260          }
 261  
 262          // Otherwise, highlight and show the default.
 263          $cell->attributes['class'] .= ' table-warning';
 264          $cell->text .= ' ' . html_writer::span(
 265                  get_string('defaultx', 'tool_task', $default), 'task-class');
 266          return $cell;
 267      }
 268  
 269      /**
 270       * Displays a warning on the page if cron is disabled.
 271       *
 272       * @return string HTML code for information about cron being disabled
 273       * @throws moodle_exception
 274       */
 275      public function cron_disabled(): string {
 276          return $this->output->notification(get_string('crondisabled', 'tool_task'), 'warning');
 277      }
 278  
 279      /**
 280       * Renders a link back to the scheduled tasks page (used from the 'run now' screen).
 281       *
 282       * @param string $taskclassname if specified, the list of tasks will scroll to show this task.
 283       * @return string HTML code
 284       */
 285      public function link_back($taskclassname = '') {
 286          $url = new moodle_url('/admin/tool/task/scheduledtasks.php');
 287          if ($taskclassname) {
 288              $url->param('lastchanged', $taskclassname);
 289          }
 290          return $this->render_from_template('tool_task/link_back', ['url' => $url]);
 291      }
 292  }