From cc341d85fd7bfaa47f9f5ce17defdb4e407e3ce6 Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Wed, 24 Mar 2021 21:18:34 +0000 Subject: [PATCH 1/2] MDL-70427 admin: remove plugin adhoc tasks during uninstall. --- lib/adminlib.php | 1 + lib/tests/task_logging_test.php | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/adminlib.php b/lib/adminlib.php index 0905a69b30a..0bcd7cfd4b6 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -209,6 +209,7 @@ function uninstall_plugin($type, $name) { $DB->delete_records('event', ['component' => $component]); // Delete scheduled tasks. + $DB->delete_records('task_adhoc', ['component' => $component]); $DB->delete_records('task_scheduled', array('component' => $component)); // Delete Inbound Message datakeys. diff --git a/lib/tests/task_logging_test.php b/lib/tests/task_logging_test.php index 39b86cd0729..0aff4da5a0a 100644 --- a/lib/tests/task_logging_test.php +++ b/lib/tests/task_logging_test.php @@ -441,6 +441,7 @@ class core_task_logmanager extends advanced_testcase { */ protected function get_test_adhoc_task() : \core\task\adhoc_task { $task = $this->getMockForAbstractClass(\core\task\adhoc_task::class); + $task->set_component('core'); // Mock a lock on the task. $lock = $this->getMockBuilder(\core\lock\lock::class) From aa6e48c6be0a0f04e6b4f2e5bcf61f16bfb7552a Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Wed, 9 Jun 2021 23:53:22 +0100 Subject: [PATCH 2/2] MDL-70427 task: correct missing component when queuing adhoc task. If the task belongs to a component, and doesn't have it's own component property set then we can lazy-load it based on class namespace. --- lib/classes/task/task_base.php | 22 +++++++++++++++ lib/tests/adhoc_task_test.php | 40 ++++++++++++++++++++++++++++ lib/tests/fixtures/task_fixtures.php | 8 ++++++ 3 files changed, 70 insertions(+) diff --git a/lib/classes/task/task_base.php b/lib/classes/task/task_base.php index bffd73682d7..6ccd782fccb 100644 --- a/lib/classes/task/task_base.php +++ b/lib/classes/task/task_base.php @@ -136,6 +136,28 @@ abstract class task_base { * @return string */ public function get_component() { + if (empty($this->component)) { + // The component should be the root of the class namespace. + $classname = get_class($this); + $parts = explode('\\', $classname); + + if (count($parts) === 1) { + $component = substr($classname, 0, strpos($classname, '_task')); + } else { + [$component] = $parts; + } + + // Load component information from plugin manager. + if ($component !== 'core' && strpos($component, 'core_') !== 0) { + $plugininfo = \core_plugin_manager::instance()->get_plugin_info($component); + if ($plugininfo && $plugininfo->component) { + $this->set_component($plugininfo->component); + } else { + debugging("Component not set and the class namespace does not match a valid component ({$component})."); + } + } + } + return $this->component; } diff --git a/lib/tests/adhoc_task_test.php b/lib/tests/adhoc_task_test.php index b0fdbb52f67..cc9b135e943 100644 --- a/lib/tests/adhoc_task_test.php +++ b/lib/tests/adhoc_task_test.php @@ -110,6 +110,46 @@ class core_adhoc_task_testcase extends advanced_testcase { \core\task\manager::adhoc_task_complete($task); } + /** + * Test queueing an adhoc task belonging to a component, where we set the task component accordingly + */ + public function test_queue_adhoc_task_for_component(): void { + $this->resetAfterTest(); + + $task = new \mod_forum\task\refresh_forum_post_counts(); + $task->set_component('mod_test'); + + \core\task\manager::queue_adhoc_task($task); + $this->assertDebuggingNotCalled(); + } + + /** + * Test queueing an adhoc task belonging to a component, where we do not set the task component + */ + public function test_queue_task_for_component_without_set_component(): void { + $this->resetAfterTest(); + + $task = new \mod_forum\task\refresh_forum_post_counts(); + + \core\task\manager::queue_adhoc_task($task); + $this->assertDebuggingNotCalled(); + + // Assert the missing component was set. + $this->assertEquals('mod_forum', $task->get_component()); + } + + /** + * Test queueing an adhoc task belonging to an invalid component, where we do not set the task component + */ + public function test_queue_task_for_invalid_component_without_set_component(): void { + $this->resetAfterTest(); + + $task = new \mod_fake\task\adhoc_component_task(); + + \core\task\manager::queue_adhoc_task($task); + $this->assertDebuggingCalled('Component not set and the class namespace does not match a valid component (mod_fake).'); + } + /** * Test empty set of adhoc tasks */ diff --git a/lib/tests/fixtures/task_fixtures.php b/lib/tests/fixtures/task_fixtures.php index ead50031c3a..9ece85de681 100644 --- a/lib/tests/fixtures/task_fixtures.php +++ b/lib/tests/fixtures/task_fixtures.php @@ -62,3 +62,11 @@ class scheduled_test3_task extends \core\task\scheduled_task { public function execute() { } } + +namespace mod_fake\task; + +class adhoc_component_task extends \core\task\adhoc_task { + public function execute() { + + } +}