diff --git a/admin/tool/task/classes/edit_scheduled_task_form.php b/admin/tool/task/classes/edit_scheduled_task_form.php index 43ff051db3c..7b593cafd3f 100644 --- a/admin/tool/task/classes/edit_scheduled_task_form.php +++ b/admin/tool/task/classes/edit_scheduled_task_form.php @@ -34,42 +34,44 @@ require_once($CFG->libdir.'/formslib.php'); */ class tool_task_edit_scheduled_task_form extends moodleform { public function definition() { - global $CFG; - $mform = $this->_form; + /** @var \core\task\scheduled_task $task */ $task = $this->_customdata; - $never = get_string('never'); - $none = get_string('none'); - $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : $never; - $nextrun = $task->get_next_run_time() ? userdate($task->get_next_run_time()) : $none; + $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : get_string('never'); + $nextrun = $task->get_next_run_time(); + if ($task->get_disabled()) { + $nextrun = get_string('disabled', 'tool_task'); + } else if ($nextrun > time()) { + $nextrun = userdate($nextrun); + } else { + $nextrun = get_string('asap', 'tool_task'); + } $mform->addElement('static', 'lastrun', get_string('lastruntime', 'tool_task'), $lastrun); $mform->addElement('static', 'nextrun', get_string('nextruntime', 'tool_task'), $nextrun); $mform->addElement('text', 'minute', get_string('taskscheduleminute', 'tool_task')); $mform->setType('minute', PARAM_RAW); $mform->addHelpButton('minute', 'taskscheduleminute', 'tool_task'); - $mform->setDefault('minute', $task->get_minute()); $mform->addElement('text', 'hour', get_string('taskschedulehour', 'tool_task')); $mform->setType('hour', PARAM_RAW); $mform->addHelpButton('hour', 'taskschedulehour', 'tool_task'); - $mform->setDefault('hour', $task->get_hour()); $mform->addElement('text', 'day', get_string('taskscheduleday', 'tool_task')); $mform->setType('day', PARAM_RAW); $mform->addHelpButton('day', 'taskscheduleday', 'tool_task'); - $mform->setDefault('day', $task->get_day()); $mform->addElement('text', 'month', get_string('taskschedulemonth', 'tool_task')); $mform->setType('month', PARAM_RAW); $mform->addHelpButton('month', 'taskschedulemonth', 'tool_task'); - $mform->setDefault('month', $task->get_month()); $mform->addElement('text', 'dayofweek', get_string('taskscheduledayofweek', 'tool_task')); $mform->setType('dayofweek', PARAM_RAW); $mform->addHelpButton('dayofweek', 'taskscheduledayofweek', 'tool_task'); - $mform->setDefault('dayofweek', $task->get_day_of_week()); + + $mform->addElement('advcheckbox', 'disabled', get_string('disabled', 'tool_task')); + $mform->addHelpButton('disabled', 'disabled', 'tool_task'); $mform->addElement('advcheckbox', 'resettodefaults', get_string('resettasktodefaults', 'tool_task')); $mform->addHelpButton('resettodefaults', 'resettasktodefaults', 'tool_task'); @@ -79,12 +81,16 @@ class tool_task_edit_scheduled_task_form extends moodleform { $mform->disabledIf('day', 'resettodefaults', 'checked'); $mform->disabledIf('dayofweek', 'resettodefaults', 'checked'); $mform->disabledIf('month', 'resettodefaults', 'checked'); + $mform->disabledIf('disabled', 'resettodefaults', 'checked'); $mform->addElement('hidden', 'task', get_class($task)); $mform->setType('task', PARAM_RAW); $mform->addElement('hidden', 'action', 'edit'); $mform->setType('action', PARAM_ALPHANUMEXT); $this->add_action_buttons(true, get_string('savechanges')); + + // Do not use defaults for existing values, the set_data() is the correct way. + $this->set_data(\core\task\manager::record_from_scheduled_task($task)); } } diff --git a/admin/tool/task/cli/schedule_task.php b/admin/tool/task/cli/schedule_task.php index 0b56ac55891..0660eff0556 100644 --- a/admin/tool/task/cli/schedule_task.php +++ b/admin/tool/task/cli/schedule_task.php @@ -70,7 +70,15 @@ if ($options['list']) { . $task->get_day_of_week() . ' ' . $task->get_month() . ' ' . $task->get_day_of_week(); - $nextrun = $task->get_next_run_time() ? userdate($task->get_next_run_time(), $shorttime) : 'asap'; + $nextrun = $task->get_next_run_time(); + + if ($task->get_disabled()) { + $nextrun = get_string('disabled', 'tool_task'); + } else if ($nextrun > time()) { + $nextrun = userdate($nextrun); + } else { + $nextrun = get_string('asap', 'tool_task'); + } echo str_pad($class, 50, ' ') . ' ' . str_pad($schedule, 17, ' ') . ' ' . $nextrun . "\n"; } diff --git a/admin/tool/task/lang/en/tool_task.php b/admin/tool/task/lang/en/tool_task.php index a4f5e7233a4..493fa1dea90 100644 --- a/admin/tool/task/lang/en/tool_task.php +++ b/admin/tool/task/lang/en/tool_task.php @@ -22,10 +22,13 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['asap'] = 'ASAP'; $string['blocking'] = 'Blocking'; $string['component'] = 'Component'; $string['corecomponent'] = 'Core'; $string['default'] = 'Default'; +$string['disabled'] = 'Disabled'; +$string['disabled_help'] = 'Disabled scheduled tasks are not executed from cron, however they can still be executed manually via the CLI tool.'; $string['edittaskschedule'] = 'Edit task schedule: {$a}'; $string['faildelay'] = 'Fail delay'; $string['lastruntime'] = 'Last run'; diff --git a/admin/tool/task/renderer.php b/admin/tool/task/renderer.php index 4a51116e1c3..b0da7053bed 100644 --- a/admin/tool/task/renderer.php +++ b/admin/tool/task/renderer.php @@ -57,11 +57,19 @@ class tool_task_renderer extends plugin_renderer_base { $yes = get_string('yes'); $no = get_string('no'); $never = get_string('never'); - $now = get_string('now'); + $asap = get_string('asap', 'tool_task'); + $disabled = get_string('disabled', 'tool_task'); foreach ($tasks as $task) { $customised = $task->is_customised() ? $no : $yes; $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : $never; - $nextrun = $task->get_next_run_time() ? userdate($task->get_next_run_time()) : $now; + $nextrun = $task->get_next_run_time(); + if ($task->get_disabled()) { + $nextrun = $disabled; + } else if ($nextrun > time()) { + $nextrun = userdate($nextrun); + } else { + $nextrun = $asap; + } $configureurl = new moodle_url('/admin/tool/task/scheduledtasks.php', array('action'=>'edit', 'task' => get_class($task))); $editlink = $this->action_icon($configureurl, new pix_icon('t/edit', get_string('edittaskschedule', 'tool_task', $task->get_name()))); diff --git a/admin/tool/task/scheduledtasks.php b/admin/tool/task/scheduledtasks.php index 27796151d63..2b38300e9ea 100644 --- a/admin/tool/task/scheduledtasks.php +++ b/admin/tool/task/scheduledtasks.php @@ -73,6 +73,7 @@ if ($mform && $mform->is_cancelled()) { $task->set_month($defaulttask->get_month()); $task->set_day_of_week($defaulttask->get_day_of_week()); $task->set_day($defaulttask->get_day()); + $task->set_disabled($defaulttask->get_disabled()); $task->set_customised(false); } else { $task->set_minute($data->minute); @@ -80,6 +81,7 @@ if ($mform && $mform->is_cancelled()) { $task->set_month($data->month); $task->set_day_of_week($data->dayofweek); $task->set_day($data->day); + $task->set_disabled($data->disabled); $task->set_customised(true); } diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php index ea573c9efa7..be60ee2a9a1 100644 --- a/lib/classes/task/manager.php +++ b/lib/classes/task/manager.php @@ -198,6 +198,7 @@ class manager { $record->day = $task->get_day(); $record->dayofweek = $task->get_day_of_week(); $record->month = $task->get_month(); + $record->disabled = $task->get_disabled(); return $record; } @@ -306,6 +307,9 @@ class manager { if (isset($record->faildelay)) { $task->set_fail_delay($record->faildelay); } + if (isset($record->disabled)) { + $task->set_disabled($record->disabled); + } return $task; } @@ -446,7 +450,9 @@ class manager { throw new \moodle_exception('locktimeout'); } - $where = '(lastruntime IS NULL OR lastruntime < :timestart1) AND (nextruntime IS NULL OR nextruntime < :timestart2)'; + $where = "(lastruntime IS NULL OR lastruntime < :timestart1) + AND (nextruntime IS NULL OR nextruntime < :timestart2) + AND disabled = 0"; $params = array('timestart1' => $timestart, 'timestart2' => $timestart); $records = $DB->get_records_select('task_scheduled', $where, $params); diff --git a/lib/classes/task/scheduled_task.php b/lib/classes/task/scheduled_task.php index 1c36b07e434..f7fb050a74f 100644 --- a/lib/classes/task/scheduled_task.php +++ b/lib/classes/task/scheduled_task.php @@ -52,6 +52,9 @@ abstract class scheduled_task extends task_base { /** @var boolean $customised - Has this task been changed from it's default schedule? */ private $customised = false; + /** @var int $disabled - Is this task disabled in cron? */ + private $disabled = false; + /** * Get the last run time for this scheduled task. * @return int @@ -164,6 +167,22 @@ abstract class scheduled_task extends task_base { return $this->dayofweek; } + /** + * Setter for $disabled. + * @param bool $disabled + */ + public function set_disabled($disabled) { + $this->disabled = (bool)$disabled; + } + + /** + * Getter for $disabled. + * @return bool + */ + public function get_disabled() { + return $this->disabled; + } + /** * Take a cron field definition and return an array of valid numbers with the range min-max. * diff --git a/lib/classes/task/task_base.php b/lib/classes/task/task_base.php index 2faabe67c64..05e68a5b36a 100644 --- a/lib/classes/task/task_base.php +++ b/lib/classes/task/task_base.php @@ -75,8 +75,8 @@ abstract class task_base { } /** - * Get the last run time for this task. - * @return int + * Get the next run time for this task. + * @return int timestamp */ public function get_next_run_time() { return $this->nextruntime; diff --git a/lib/db/install.xml b/lib/db/install.xml index 5f186240f3f..3627e91373a 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -1465,7 +1465,7 @@ - + @@ -1476,9 +1476,9 @@ - - - + + +
@@ -3074,6 +3074,7 @@ + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 2ce903ca933..4677e107f76 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -3085,6 +3085,7 @@ function xmldb_main_upgrade($oldversion) { $table->add_field('dayofweek', XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, null); $table->add_field('faildelay', XMLDB_TYPE_INTEGER, '10', null, null, null, null); $table->add_field('customised', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('disabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); // Adding keys to table task_scheduled. $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); @@ -3331,5 +3332,20 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2014032600.02); } + if ($oldversion < 2014032700.01) { + + // Define field disabled to be added to task_scheduled. + $table = new xmldb_table('task_scheduled'); + $field = new xmldb_field('disabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'customised'); + + // Conditionally launch add field disabled. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2014032700.01); + } + return true; } diff --git a/lib/tests/adhoc_task_test.php b/lib/tests/adhoc_task_test.php index ebe592f207e..174e54c2852 100644 --- a/lib/tests/adhoc_task_test.php +++ b/lib/tests/adhoc_task_test.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * This file contains the unittests for the css optimiser in csslib.php + * This file contains the unittests for adhock tasks. * * @package core * @category phpunit @@ -24,6 +24,7 @@ */ defined('MOODLE_INTERNAL') || die(); +require_once(__DIR__ . '/fixtures/task_fixtures.php'); /** @@ -34,14 +35,12 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class adhoc_task_testcase extends advanced_testcase { +class core_adhoc_task_testcase extends advanced_testcase { public function test_get_next_adhoc_task() { - global $DB; - $this->resetAfterTest(true); // Create an adhoc task. - $task = new testable_adhoc_task(); + $task = new \core\task\adhoc_test_task(); // Queue it. $task = \core\task\manager::queue_adhoc_task($task); @@ -69,8 +68,3 @@ class adhoc_task_testcase extends advanced_testcase { $this->assertNull($task); } } - -class testable_adhoc_task extends \core\task\adhoc_task { - public function execute() { - } -} diff --git a/lib/tests/fixtures/task_fixtures.php b/lib/tests/fixtures/task_fixtures.php new file mode 100644 index 00000000000..6ec619ff0e9 --- /dev/null +++ b/lib/tests/fixtures/task_fixtures.php @@ -0,0 +1,59 @@ +. + +/** + * Fixtures for task tests. + * + * @package core + * @category phpunit + * @copyright 2014 Petr Skoda + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core\task; +defined('MOODLE_INTERNAL') || die(); + +class adhoc_test_task extends \core\task\adhoc_task { + public function execute() { + } +} + +class scheduled_test_task extends \core\task\scheduled_task { + public function get_name() { + return "Test task"; + } + + public function execute() { + } +} + +class scheduled_test2_task extends \core\task\scheduled_task { + public function get_name() { + return "Test task 2"; + } + + public function execute() { + } +} + +class scheduled_test3_task extends \core\task\scheduled_task { + public function get_name() { + return "Test task 3"; + } + + public function execute() { + } +} diff --git a/lib/tests/scheduled_task_test.php b/lib/tests/scheduled_task_test.php index 648fb4062eb..e60b99a52da 100644 --- a/lib/tests/scheduled_task_test.php +++ b/lib/tests/scheduled_task_test.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * This file contains the unittests for the css optimiser in csslib.php + * This file contains the unittests for scheduled tasks. * * @package core * @category phpunit @@ -24,7 +24,7 @@ */ defined('MOODLE_INTERNAL') || die(); - +require_once(__DIR__ . '/fixtures/task_fixtures.php'); /** * Test class for scheduled task. @@ -34,13 +34,13 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduled_task_testcase extends advanced_testcase { +class core_scheduled_task_testcase extends advanced_testcase { /** * Test the cron scheduling method */ public function test_eval_cron_field() { - $testclass = new testable_scheduled_task(); + $testclass = new \core\task\scheduled_test_task(); $this->assertEquals(20, count($testclass->eval_cron_field('*/3', 0, 59))); $this->assertEquals(31, count($testclass->eval_cron_field('1,*/2', 0, 59))); @@ -52,7 +52,7 @@ class scheduled_task_testcase extends advanced_testcase { public function test_get_next_scheduled_time() { // Test job run at 1 am. - $testclass = new testable_scheduled_task(); + $testclass = new \core\task\scheduled_test_task(); // All fields default to '*'. $testclass->set_hour('1'); @@ -68,8 +68,13 @@ class scheduled_task_testcase extends advanced_testcase { $this->assertEquals($oneam, $nexttime, 'Next scheduled time is 1am.'); + // Disabled flag does not affect next time. + $testclass->set_disabled(true); + $nexttime = $testclass->get_next_scheduled_time(); + $this->assertEquals($oneam, $nexttime, 'Next scheduled time is 1am.'); + // Now test for job run every 10 minutes. - $testclass = new testable_scheduled_task(); + $testclass = new \core\task\scheduled_test_task(); // All fields default to '*'. $testclass->set_minute('*/10'); @@ -80,6 +85,11 @@ class scheduled_task_testcase extends advanced_testcase { $nexttenminutes = mktime(date('H'), $minutes, 0); $this->assertEquals($nexttenminutes, $nexttime, 'Next scheduled time is in 10 minutes.'); + + // Disabled flag does not affect next time. + $testclass->set_disabled(true); + $nexttime = $testclass->get_next_scheduled_time(); + $this->assertEquals($nexttenminutes, $nexttime, 'Next scheduled time is in 10 minutes.'); } public function test_timezones() { @@ -103,7 +113,7 @@ class scheduled_task_testcase extends advanced_testcase { // GMT-04:30. $CFG->timezone = 'America/Caracas'; - $testclass = new testable_scheduled_task(); + $testclass = new \core\task\scheduled_test_task(); // Scheduled tasks should always use servertime - so this is 03:30 GMT. $testclass->set_hour('1'); @@ -142,23 +152,28 @@ class scheduled_task_testcase extends advanced_testcase { $record->day = '*'; $record->month = '*'; $record->component = 'test_scheduled_task'; - $record->classname = '\\testable_scheduled_task'; + $record->classname = '\core\task\scheduled_test_task'; $DB->insert_record('task_scheduled', $record); // And another one to test failures. - $record->classname = '\\testable_scheduled_task2'; + $record->classname = '\core\task\scheduled_test2_task'; $DB->insert_record('task_scheduled', $record); + // And disabled test. + $record->classname = '\core\task\scheduled_test3_task'; + $record->disabled = 1; + $DB->insert_record('task_scheduled', $record); + $now = time(); // Should get handed the first task. $task = \core\task\manager::get_next_scheduled_task($now); - $this->assertNotNull($task); + $this->assertInstanceOf('\core\task\scheduled_test_task', $task); $task->execute(); \core\task\manager::scheduled_task_complete($task); // Should get handed the second task. $task = \core\task\manager::get_next_scheduled_task($now); - $this->assertNotNull($task); + $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); $task->execute(); \core\task\manager::scheduled_task_failed($task); @@ -168,7 +183,7 @@ class scheduled_task_testcase extends advanced_testcase { // Should get the second task (retry after delay). $task = \core\task\manager::get_next_scheduled_task($now + 120); - $this->assertNotNull($task); + $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); $task->execute(); \core\task\manager::scheduled_task_complete($task); @@ -178,22 +193,3 @@ class scheduled_task_testcase extends advanced_testcase { $this->assertNull($task); } } - -class testable_scheduled_task extends \core\task\scheduled_task { - public function get_name() { - return "Test task"; - } - - public function execute() { - } -} - -class testable_scheduled_task2 extends \core\task\scheduled_task { - public function get_name() { - return "Test task 2"; - } - - public function execute() { - } -} - diff --git a/version.php b/version.php index 08647491be3..b140eccc083 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2014032700.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2014032700.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.