diff --git a/admin/classes/local/settings/setting_scheduled_task_status.php b/admin/classes/local/settings/setting_scheduled_task_status.php new file mode 100644 index 00000000000..b878036a6d7 --- /dev/null +++ b/admin/classes/local/settings/setting_scheduled_task_status.php @@ -0,0 +1,121 @@ +. + +/** + * Admin setting to show current scheduled task's status. + * + * @package core + * @copyright 2021 Universitat Rovira i Virgili + * @author Jordi Pujol-Ahulló + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace core_admin\local\settings; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->libdir . '/moodlelib.php'); + +use admin_setting_description; +use core\task\manager; +use core\task\scheduled_task; +use html_writer; +use lang_string; +use moodle_url; +use stdClass; + +/** + * This admin setting tells whether a given scheduled task is enabled, providing a link to its configuration page. + * + * The goal of this setting is to help contextualizing the configuration settings with related scheduled task status, + * providing the big picture of that part of the system. + * + * @package core + * @copyright 2021 Universitat Rovira i Virgili + * @author Jordi Pujol-Ahulló + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class setting_scheduled_task_status extends admin_setting_description { + /** + * @var string fully qualified class name of a scheduled task. + */ + private $classname; + /** + * @var string additional text to append to the description. + */ + private $extradescription; + + /** + * setting_scheduled_task_status constructor. + * @param string $name unique setting name. + * @param string $scheduledtaskclassname full classpath class name of the scheduled task. + * @param string $extradescription extra detail to append to the scheduled task status to add context in the setting + * page. + */ + public function __construct(string $name, string $scheduledtaskclassname, string $extradescription = '') { + $visiblename = new lang_string('task_status', 'admin'); + $this->classname = $scheduledtaskclassname; + $this->extradescription = $extradescription; + + parent::__construct($name, $visiblename, ''); + } + + /** + * Calculates lazily the content of the description. + * @param mixed $data nothing expected in this case. + * @param string $query nothing expected in this case. + * @return string the HTML content to print for this setting. + */ + public function output_html($data, $query = ''): string { + if (empty($this->description)) { + $this->description = $this->get_task_description(); + } + + return parent::output_html($data, $query); + } + + /** + * Returns the HTML to print as the description. + * @return string description to be printed. + */ + private function get_task_description(): string { + $task = manager::get_scheduled_task($this->classname); + if ($task->is_enabled()) { + $taskenabled = get_string('enabled', 'admin'); + } else { + $taskenabled = get_string('disabled', 'admin'); + } + $taskenabled = strtolower($taskenabled); + $gotourl = new moodle_url( + '/admin/tool/task/scheduledtasks.php', + [], + scheduled_task::get_html_id($this->classname) + ); + if (!empty($this->extradescription)) { + $this->extradescription = '
' . $this->extradescription; + } + + $taskdetail = new stdClass(); + $taskdetail->class = $this->classname; + $taskdetail->name = $task->get_name(); + $taskdetail->status = $taskenabled; + $taskdetail->gotourl = $gotourl->out(false); + $taskdetail->extradescription = $this->extradescription; + + return html_writer::tag('p', get_string('task_status_desc', 'admin', $taskdetail)); + } +} diff --git a/admin/settings/language.php b/admin/settings/language.php index c865dfbfc2f..97fb85d8f15 100644 --- a/admin/settings/language.php +++ b/admin/settings/language.php @@ -2,6 +2,8 @@ // This file defines settingpages and externalpages under the "appearance" category +use core_admin\local\settings\setting_scheduled_task_status; + if ($hassiteconfig) { // "languageandlocation" settingpage @@ -16,6 +18,7 @@ if ($hassiteconfig) { $temp->add(new admin_setting_configcheckbox('langstringcache', new lang_string('langstringcache', 'admin'), new lang_string('configlangstringcache', 'admin'), 1)); $temp->add(new admin_setting_configtext('locale', new lang_string('localetext', 'admin'), new lang_string('configlocale', 'admin'), '', PARAM_FILE)); $temp->add(new admin_setting_configselect('latinexcelexport', new lang_string('latinexcelexport', 'admin'), new lang_string('configlatinexcelexport', 'admin'), '0', array('0'=>'Unicode','1'=>'Latin'))); + $temp->add(new setting_scheduled_task_status('langimporttaskstatus', '\tool_langimport\task\update_langpacks_task')); $ADMIN->add('language', $temp); diff --git a/admin/tool/task/renderer.php b/admin/tool/task/renderer.php index cdf7457d348..1491ef28184 100644 --- a/admin/tool/task/renderer.php +++ b/admin/tool/task/renderer.php @@ -76,7 +76,7 @@ class tool_task_renderer extends plugin_renderer_base { $data = []; $yes = get_string('yes'); $no = get_string('no'); - $canruntasks = \core\task\manager::is_runnable(); + $canruntasks = \core\task\manager::is_runnable() && get_config('tool_task', 'enablerunnow'); foreach ($tasks as $task) { $classname = get_class($task); $defaulttask = \core\task\manager::get_default_scheduled_task($classname, false); @@ -108,14 +108,11 @@ class tool_task_renderer extends plugin_renderer_base { } $namecell = new html_table_cell($namecellcontent); $namecell->header = true; - - $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component()); - $plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && - !$task->get_run_if_component_disabled(); - $disabled = $plugindisabled || $task->get_disabled(); + $namecell->id = scheduled_task::get_html_id($classname); $runnow = ''; - if (!$plugindisabled && get_config('tool_task', 'enablerunnow') && $canruntasks ) { + $canrunthistask = $canruntasks && $task->can_run(); + if ($canrunthistask) { $runnow = html_writer::div(html_writer::link( new moodle_url('/admin/tool/task/schedule_task.php', ['task' => $classname]), @@ -147,7 +144,7 @@ class tool_task_renderer extends plugin_renderer_base { new html_table_cell($customised)]); $classes = []; - if ($disabled) { + if (!$task->is_enabled()) { $classes[] = 'disabled'; } if (get_class($task) == $lastchanged) { diff --git a/admin/tool/task/styles.css b/admin/tool/task/styles.css index f297fd6afaf..7f37541c7ec 100644 --- a/admin/tool/task/styles.css +++ b/admin/tool/task/styles.css @@ -15,3 +15,7 @@ #page-admin-tool-task-scheduledtasks .task-clearfaildelay { font-size: 0.75em; } + +#page-admin-tool-task-scheduledtasks :target { + scroll-margin-top: 60px; +} diff --git a/lang/en/admin.php b/lang/en/admin.php index bf35822dff2..c7886306789 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -1300,6 +1300,8 @@ $string['task_type:scheduled'] = 'Scheduled'; $string['task_result:failed'] = 'Fail'; $string['task_stats:dbreads'] = '{$a} reads'; $string['task_stats:dbwrites'] = '{$a} writes'; +$string['task_status'] = 'Task status'; +$string['task_status_desc'] = 'The task {$a->name} is {$a->status}.
See its details.
Class: {$a->class}{$a->extradescription}'; $string['task_starttime'] = 'Start time'; $string['task_duration'] = 'Duration'; $string['task_dbstats'] = 'Database'; diff --git a/lib/classes/task/scheduled_task.php b/lib/classes/task/scheduled_task.php index 04fbd1feba6..85e94082107 100644 --- a/lib/classes/task/scheduled_task.php +++ b/lib/classes/task/scheduled_task.php @@ -429,6 +429,33 @@ abstract class scheduled_task extends task_base { return $nexttime; } + /** + * Informs whether this task can be run. + * @return bool true when this task can be run. false otherwise. + */ + public function can_run(): bool { + return $this->is_component_enabled() || $this->get_run_if_component_disabled(); + } + + /** + * Checks whether the component and the task disabled flag enables to run this task. + * This do not checks whether the task manager allows running them or if the + * site allows tasks to "run now". + * @return bool true if task is enabled. false otherwise. + */ + public function is_enabled(): bool { + return $this->can_run() && !$this->get_disabled(); + } + + /** + * Produces a valid id string to use as id attribute based on the given FQCN class name. + * @param string $classname FQCN of a task. + * @return string valid string to be used as id attribute. + */ + public static function get_html_id(string $classname): string { + return str_replace('\\', '-', ltrim($classname, '\\')); + } + /** * Get a descriptive name for this task (shown to admins). * diff --git a/lib/classes/task/task_base.php b/lib/classes/task/task_base.php index bffd73682d7..ecc89d15ea2 100644 --- a/lib/classes/task/task_base.php +++ b/lib/classes/task/task_base.php @@ -208,4 +208,13 @@ abstract class task_base { public function get_pid() { return $this->pid; } + + /** + * Informs whether the task's component is enabled. + * @return bool true when enabled. false otherwise. + */ + public function is_component_enabled(): bool { + $plugininfo = \core_plugin_manager::instance()->get_plugin_info($this->get_component()); + return $plugininfo && $plugininfo->is_enabled(); + } }