diff --git a/.upgradenotes/MDL-83479-2025021301170445.yml b/.upgradenotes/MDL-83479-2025021301170445.yml new file mode 100644 index 00000000000..b9e5a8219bf --- /dev/null +++ b/.upgradenotes/MDL-83479-2025021301170445.yml @@ -0,0 +1,12 @@ +issueNumber: MDL-83479 +notes: + core_backup: + - message: >- + Added several hooks to the restore process to 1) Hook to allow extra settings to be defined for the course + restore process. 2) Hook to allow adding extra fields to the copy course form. 3) Hook used by + copy_helper::process_formdata() to expand the list of required fields. 4) Hook used to allow interaction with + the copy task, before the actual task execution takes place. + + Other changes include 1) base_task::add_setting() is now public to allow hook callbacks to add settings. + 2) Settings are now added to the data sent to the course_restored event. + type: improved diff --git a/backup/moodle2/restore_root_task.class.php b/backup/moodle2/restore_root_task.class.php index 2a93bc031d6..b3c31cf246b 100644 --- a/backup/moodle2/restore_root_task.class.php +++ b/backup/moodle2/restore_root_task.class.php @@ -26,6 +26,10 @@ defined('MOODLE_INTERNAL') || die(); +use core\di; +use core\hook\manager; +use core_backup\hook\after_restore_root_define_settings; + /** * Start task that provides all the settings common to all restores and other initial steps * @@ -343,5 +347,9 @@ class restore_root_task extends restore_task { $legacyfiles->set_ui(new backup_setting_ui_checkbox($legacyfiles, get_string('rootsettinglegacyfiles', 'backup'))); $legacyfiles->get_ui()->set_changeable($changeable); $this->add_setting($legacyfiles); + + // Create and dispatch a hook to allow plugins to add other settings for the restore process. + $hook = new after_restore_root_define_settings($this); + di::get(manager::class)->dispatch($hook); } } diff --git a/backup/moodle2/tests/fixtures/restore_task_hook_callbacks.php b/backup/moodle2/tests/fixtures/restore_task_hook_callbacks.php new file mode 100644 index 00000000000..4b61576bf45 --- /dev/null +++ b/backup/moodle2/tests/fixtures/restore_task_hook_callbacks.php @@ -0,0 +1,47 @@ +. + +namespace core_backup\fixtures; + +use base_setting; +use restore_generic_setting; +use backup_setting_ui_checkbox; +use core_backup\hook\after_restore_root_define_settings; + +/** + * Callback class to test after_restore_root_define_settings hook. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_task_hook_callbacks { + /** + * Tests use of after_restore_root_define_settings hook. + * + * @param after_restore_root_define_settings $hook + */ + public static function after_restore_root_define_settings(after_restore_root_define_settings $hook) { + $task = $hook->task; + $defaultvalue = true; + $changeable = true; + + $somebox = new restore_generic_setting('extra_test', base_setting::IS_BOOLEAN, $defaultvalue); + $somebox->set_ui(new backup_setting_ui_checkbox($somebox, 'Extra test')); + $somebox->get_ui()->set_changeable($changeable); + $task->add_setting($somebox); + } +} diff --git a/backup/moodle2/tests/fixtures/restore_task_hooks.php b/backup/moodle2/tests/fixtures/restore_task_hooks.php new file mode 100644 index 00000000000..ff062847916 --- /dev/null +++ b/backup/moodle2/tests/fixtures/restore_task_hooks.php @@ -0,0 +1,40 @@ +. + +/** + * Describes the hook callbacks used to test the restore settings definition. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_backup\fixtures\restore_task_hook_callbacks; +use core_backup\hook\after_restore_root_define_settings; + +require_once(__DIR__ . '/restore_task_hook_callbacks.php'); + +$callbacks = [ + [ + 'hook' => after_restore_root_define_settings::class, + 'callback' => [ + restore_task_hook_callbacks::class, + 'after_restore_root_define_settings', + ], + ], +]; diff --git a/backup/moodle2/tests/restore_stepslib_test.php b/backup/moodle2/tests/restore_stepslib_test.php index 953c34b3898..cc76ebf7917 100644 --- a/backup/moodle2/tests/restore_stepslib_test.php +++ b/backup/moodle2/tests/restore_stepslib_test.php @@ -17,6 +17,9 @@ namespace core_backup; use backup; +use core\di; +use core\hook\manager; +use restore_controller; /** * Tests for Moodle 2 restore steplib classes. @@ -144,4 +147,57 @@ final class restore_stepslib_test extends \advanced_testcase { $this->assertEquals($originalsections[1]->$field, $restoredsections[1]->$field); } } + + /** + * Tests the hooks for restore task settings definition. + * + * @covers \restore_root_task::define_settings + */ + public function test_restore_hook(): void { + // Load the callback classes. + require_once(__DIR__ . '/fixtures/restore_task_hooks.php'); + + $this->resetAfterTest(); + $this->setAdminUser(); + + // Replace the version of the manager in the DI container with a phpunit one. + di::set( + manager::class, + manager::phpunit_get_instance([ + // Load a list of hooks for `test_plugin1` from the fixture file. + 'test_plugin1' => __DIR__ . + '/fixtures/restore_task_hooks.php', + ]), + ); + + global $CFG, $USER; + + // Create course to restore into, and a user to do the restore. + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + + $backupid = $this->backup_course($course); + + // Turn off file logging, otherwise it can't delete the file (Windows). + $CFG->backup_file_logger_level = backup::LOG_NONE; + + $course = $generator->create_course(); + + // Do restore to new course with default settings. + $rc = new restore_controller( + $backupid, + $course->id, + backup::INTERACTIVE_NO, + backup::MODE_GENERAL, + $USER->id, + backup::TARGET_EXISTING_DELETING + ); + + $precheck = $rc->execute_precheck(); + $this->assertTrue($precheck); + $setting = $rc->get_plan()->get_setting('extra_test'); + $this->assertNotEmpty($setting); + $rc->execute_plan(); + $rc->destroy(); + } } diff --git a/backup/tests/hook/copy_course_hook_test.php b/backup/tests/hook/copy_course_hook_test.php new file mode 100644 index 00000000000..8af997cb0e9 --- /dev/null +++ b/backup/tests/hook/copy_course_hook_test.php @@ -0,0 +1,104 @@ +. + +namespace core_backup\hook; + +use core\di; +use copy_helper; +use advanced_testcase; +use core\hook\manager; +use core\task\manager as taskmanager; +use core\event\course_restored; +use core_backup\hook\fixtures\copy_course_hook_callbacks; + +/** + * Class to test the hook inside asynchronous_copy_task. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +final class copy_course_hook_test extends advanced_testcase { + + /** + * Test the hook. + * + * @covers \core\task\asynchronous_copy_task::execute + * @covers \core_backup\hook\before_copy_course_execute + */ + public function test_copy_course_hook(): void { + // Load the callback classes. + require_once(__DIR__ . '/fixtures/copy_course_hooks.php'); + + // Replace the version of the manager in the DI container with a phpunit one. + di::set( + manager::class, + manager::phpunit_get_instance([ + // Load a list of hooks for `test_plugin1` from the fixture file. + 'test_plugin1' => __DIR__ . + '/fixtures/copy_course_hooks.php', + ]), + ); + + $this->resetAfterTest(true); + $this->setAdminUser(); + + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + + $copydata = (object) [ + 'courseid' => $course->id, + 'fullname' => 'Name', + 'shortname' => 'name', + 'category' => 1, + 'visible' => 1, + 'startdate' => '123456789', + 'enddate' => '123456789', + 'idnumber' => 'dnum', + 'userdata' => false, + ]; + + $processed = copy_helper::process_formdata($copydata); + copy_helper::create_copy($processed); + $sink = $this->redirectEvents(); + + // Capture mtrace output. + ob_start(); + + // Execute adhoc task. + $now = time(); + $task = taskmanager::get_next_adhoc_task($now); + $this->assertInstanceOf('\\core\\task\\asynchronous_copy_task', $task); + $task->execute(); + taskmanager::adhoc_task_complete($task); + + ob_get_clean(); + + $this->assertGreaterThan(0, copy_course_hook_callbacks::$count); + + // Check that the restore settings have been added to the event data. + $events = $sink->get_events(); + $count = 0; + foreach ($events as $event) { + if ($event instanceof course_restored) { + $count++; + $data = $event->get_data(); + $this->assertNotEmpty($data['other']['settings']); + } + } + $this->assertGreaterThan(0, $count); + } +} diff --git a/backup/tests/hook/fixtures/copy_course_hook_callbacks.php b/backup/tests/hook/fixtures/copy_course_hook_callbacks.php new file mode 100644 index 00000000000..8f30c6a066f --- /dev/null +++ b/backup/tests/hook/fixtures/copy_course_hook_callbacks.php @@ -0,0 +1,40 @@ +. + +namespace core_backup\hook\fixtures; + +use core_backup\hook\before_copy_course_execute; + +/** + * Callbacks used to test the hooks in the copy course task. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class copy_course_hook_callbacks { + /** @var int Used to keep track oh how many times the callback has been called. */ + public static $count = 0; + + /** + * Callback used to test the before_copy_course_execute hook. + * + * @param before_copy_course_execute $hook + */ + public static function before_copy_course_execute(before_copy_course_execute $hook) { + self::$count++; + } +} diff --git a/backup/tests/hook/fixtures/copy_course_hooks.php b/backup/tests/hook/fixtures/copy_course_hooks.php new file mode 100644 index 00000000000..cf9eb60a6b3 --- /dev/null +++ b/backup/tests/hook/fixtures/copy_course_hooks.php @@ -0,0 +1,40 @@ +. + +/** + * Describes hooks used for testing. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_backup\hook\before_copy_course_execute; +use core_backup\hook\fixtures\copy_course_hook_callbacks; + +require_once(__DIR__ . '/copy_course_hook_callbacks.php'); + +$callbacks = [ + [ + 'hook' => before_copy_course_execute::class, + 'callback' => [ + copy_course_hook_callbacks::class, + 'before_copy_course_execute', + ], + ], +]; diff --git a/backup/util/helper/copy_helper.class.php b/backup/util/helper/copy_helper.class.php index 99f01c3a842..5f1ff595202 100644 --- a/backup/util/helper/copy_helper.class.php +++ b/backup/util/helper/copy_helper.class.php @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +use core\di; +use core\hook\manager; +use core_backup\hook\copy_helper_process_formdata; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); @@ -46,6 +50,11 @@ final class copy_helper { 'userdata', // Integer to determine if the copied course will contain user data. ]; + // Use hook to expand field list. + $hook = new copy_helper_process_formdata(); + di::get(manager::class)->dispatch($hook); + $requiredfields = array_merge($requiredfields, $hook->get_extrafields()); + $missingfields = array_diff($requiredfields, array_keys((array)$formdata)); if ($missingfields) { throw new \moodle_exception('copyfieldnotfound', 'backup', '', null, implode(", ", $missingfields)); diff --git a/backup/util/helper/tests/copy_helper_test.php b/backup/util/helper/tests/copy_helper_test.php index 3fd2f31ca93..8b735559a65 100644 --- a/backup/util/helper/tests/copy_helper_test.php +++ b/backup/util/helper/tests/copy_helper_test.php @@ -17,6 +17,9 @@ namespace core_backup; use backup; +use core\di; +use copy_helper; +use core\hook\manager; defined('MOODLE_INTERNAL') || die(); @@ -836,4 +839,43 @@ final class copy_helper_test extends \advanced_testcase { $copydata = \copy_helper::process_formdata($formdata); \copy_helper::create_copy($copydata); } + + /** + * Test copy_helper_process_formdata hook. + * + * @covers \core_backup\hook\copy_helper_process_formdata + */ + public function test_copy_helper_process_formdata_hook(): void { + // Load the callback classes. + require_once(__DIR__ . '/fixtures/helper_hooks.php'); + + // Replace the version of the manager in the DI container with a phpunit one. + di::set( + manager::class, + manager::phpunit_get_instance([ + // Load a list of hooks for `test_plugin1` from the fixture file. + 'test_plugin1' => __DIR__ . + '/fixtures/helper_hooks.php', + ]), + ); + + $formdata = (object) [ + 'courseid' => 4, + 'fullname' => 'Name', + 'shortname' => 'name', + 'category' => 12, + 'visible' => 1, + 'startdate' => '123456789', + 'enddate' => '123456789', + 'idnumber' => 'dnum', + 'userdata' => false, + 'extra' => 13, + ]; + + $processed = copy_helper::process_formdata($formdata); + + // Check that the extra fields are present. + $this->assertTrue(isset($processed->extra)); + $this->assertEquals(13, $processed->extra); + } } diff --git a/backup/util/helper/tests/fixtures/helper_hook_callbacks.php b/backup/util/helper/tests/fixtures/helper_hook_callbacks.php new file mode 100644 index 00000000000..1be4027f80c --- /dev/null +++ b/backup/util/helper/tests/fixtures/helper_hook_callbacks.php @@ -0,0 +1,37 @@ +. + +namespace core_backup\fixtures; + +use core_backup\hook\copy_helper_process_formdata; + +/** + * Callbacks used to test hook. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class helper_hook_callbacks { + /** + * Constructor. + * + * @param copy_helper_process_formdata $hook + */ + public static function copy_helper_process_formdata(copy_helper_process_formdata $hook) { + $hook->add_extra_field('extra'); + } +} diff --git a/backup/util/helper/tests/fixtures/helper_hooks.php b/backup/util/helper/tests/fixtures/helper_hooks.php new file mode 100644 index 00000000000..5f338dcc726 --- /dev/null +++ b/backup/util/helper/tests/fixtures/helper_hooks.php @@ -0,0 +1,41 @@ +. + +/** + * Hook definitions. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +use core_backup\fixtures\helper_hook_callbacks; +use core_backup\hook\copy_helper_process_formdata; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once(__DIR__ . '/helper_hook_callbacks.php'); + +$callbacks = [ + [ + 'hook' => copy_helper_process_formdata::class, + 'callback' => [ + helper_hook_callbacks::class, + 'copy_helper_process_formdata', + ], + ], +]; diff --git a/backup/util/plan/base_task.class.php b/backup/util/plan/base_task.class.php index 148c0bbe883..009d4464567 100644 --- a/backup/util/plan/base_task.class.php +++ b/backup/util/plan/base_task.class.php @@ -279,7 +279,13 @@ abstract class base_task implements checksumable, executable, loggable { */ abstract protected function define_settings(); - protected function add_setting($setting) { + /** + * Add a setting to the task. + * + * @param base_setting $setting + * @return void + */ + public function add_setting($setting) { if (! $setting instanceof base_setting) { throw new base_setting_exception('wrong_base_setting_specified'); } diff --git a/backup/util/plan/restore_plan.class.php b/backup/util/plan/restore_plan.class.php index 666e81d926a..71f2c7a59f7 100644 --- a/backup/util/plan/restore_plan.class.php +++ b/backup/util/plan/restore_plan.class.php @@ -185,6 +185,9 @@ class restore_plan extends base_plan implements loggable { $otherarray['originalcourseid'] = $this->controller->get_info()->original_course_id; } + // Add the settings to the event data. + $otherarray['settings'] = $this->get_settings(); + // Trigger a course restored event. $event = \core\event\course_restored::create(array( 'objectid' => $this->get_courseid(), diff --git a/backup/util/ui/classes/hook/after_copy_form_definition.php b/backup/util/ui/classes/hook/after_copy_form_definition.php new file mode 100644 index 00000000000..e2b57768acc --- /dev/null +++ b/backup/util/ui/classes/hook/after_copy_form_definition.php @@ -0,0 +1,44 @@ +. + +namespace core_backup\hook; + +use MoodleQuickForm; + +/** + * Hook to allow adding extra fields to the copy course form. + * This should be used together with core_backup\hook\copy_helper_process_formdata + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +#[\core\attribute\label('Use to add extra elements to the copy course form.')] +#[\core\attribute\tags('backup')] +final class after_copy_form_definition { + + /** @var MoodleQuickForm */ + public readonly MoodleQuickForm $mform; + + /** + * Constructor. + * + * @param MoodleQuickForm $mform + */ + public function __construct(MoodleQuickForm $mform) { + $this->mform = $mform; + } +} diff --git a/backup/util/ui/classes/hook/after_restore_root_define_settings.php b/backup/util/ui/classes/hook/after_restore_root_define_settings.php new file mode 100644 index 00000000000..04b7c9ba522 --- /dev/null +++ b/backup/util/ui/classes/hook/after_restore_root_define_settings.php @@ -0,0 +1,43 @@ +. + +namespace core_backup\hook; + +use restore_root_task; + +/** + * Hook to allow extra settings to be defined for the course restore process. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +#[\core\attribute\label('Use to add extra elements to the settings tab of the restore process.')] +#[\core\attribute\tags('backup')] +final class after_restore_root_define_settings { + + /** @var restore_root_task */ + public readonly restore_root_task $task; + + /** + * Constructor. + * + * @param restore_root_task $task + */ + public function __construct(restore_root_task $task) { + $this->task = $task; + } +} diff --git a/backup/util/ui/classes/hook/before_copy_course_execute.php b/backup/util/ui/classes/hook/before_copy_course_execute.php new file mode 100644 index 00000000000..9930351b4e6 --- /dev/null +++ b/backup/util/ui/classes/hook/before_copy_course_execute.php @@ -0,0 +1,49 @@ +. + +namespace core_backup\hook; + +use stdClass; +use restore_plan; + +/** + * Hook used to allow interaction with the copy task, before the actual task execution takes place. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +#[\core\attribute\label('Use to interact with the copy course task before the actual execution takes place.')] +#[\core\attribute\tags('backup')] +final class before_copy_course_execute { + + /** @var restore_plan */ + public readonly restore_plan $plan; + + /** @var stdClass */ + public readonly stdClass $copyinfo; + + /** + * Hook constructor. + * + * @param restore_plan $plan + * @param stdClass $copyinfo + */ + public function __construct(restore_plan $plan, stdClass $copyinfo) { + $this->plan = $plan; + $this->copyinfo = $copyinfo; + } +} diff --git a/backup/util/ui/classes/hook/copy_helper_process_formdata.php b/backup/util/ui/classes/hook/copy_helper_process_formdata.php new file mode 100644 index 00000000000..84cec9f7ea0 --- /dev/null +++ b/backup/util/ui/classes/hook/copy_helper_process_formdata.php @@ -0,0 +1,51 @@ +. + +namespace core_backup\hook; + +/** + * Hook used by copy_helper::process_formdata() to expand the list of required fields. + * This should be used together with core_backup\hook\after_copy_form_definition. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +#[\core\attribute\label('Able to add extra fields to the copy course.')] +#[\core\attribute\tags('backup')] +final class copy_helper_process_formdata { + + /** @var array List of extra fields to be added. */ + protected $extrafields = []; + + /** + * Add an extra field. + * + * @param string $extrafield + */ + public function add_extra_field(string $extrafield) { + $this->extrafields[] = $extrafield; + } + + /** + * Get the extra fields. + * + * @return array + */ + public function get_extrafields(): array { + return $this->extrafields; + } +} diff --git a/backup/util/ui/classes/output/copy_form.php b/backup/util/ui/classes/output/copy_form.php index 9f15e461d71..1e79689421f 100644 --- a/backup/util/ui/classes/output/copy_form.php +++ b/backup/util/ui/classes/output/copy_form.php @@ -25,6 +25,10 @@ namespace core_backup\output; +use core\di; +use core\hook\manager; +use core_backup\hook\after_copy_form_definition; + defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/formslib.php"); @@ -197,6 +201,10 @@ class copy_form extends \moodleform { $this->add_checkbox_controller(2); } + // Dispatch hook to allow more elements to be added to the form. + $hook = new after_copy_form_definition($mform); + di::get(manager::class)->dispatch($hook); + $buttonarray = array(); $buttonarray[] = $mform->createElement('submit', 'submitreturn', get_string('copyreturn', 'backup')); $buttonarray[] = $mform->createElement('submit', 'submitdisplay', get_string('copyview', 'backup')); diff --git a/backup/util/ui/tests/copy_form_hook_test.php b/backup/util/ui/tests/copy_form_hook_test.php new file mode 100644 index 00000000000..cbd7fdb65fe --- /dev/null +++ b/backup/util/ui/tests/copy_form_hook_test.php @@ -0,0 +1,68 @@ +. + +namespace core_backup; + +use core\di; +use core\hook\manager; +use advanced_testcase; +use core_backup\output\copy_form; + +/** + * Tests the after_copy_form_definition hook. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +final class copy_form_hook_test extends advanced_testcase { + /** + * Test the after_copy_form_definition hook. + * + * @covers \core_backup\output\copy_form::definition + */ + public function test_copy_form_hook(): void { + // Load the callback classes. + require_once(__DIR__ . '/fixtures/copy_form_hooks.php'); + + // Replace the version of the manager in the DI container with a phpunit one. + di::set( + manager::class, + manager::phpunit_get_instance([ + // Load a list of hooks for `test_plugin1` from the fixture file. + 'test_plugin1' => __DIR__ . + '/fixtures/copy_form_hooks.php', + ]), + ); + + $this->resetAfterTest(true); + $this->setAdminUser(); + + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + $form = new copy_form( + null, + ['course' => $course, 'returnto' => null, 'returnurl' => null] + ); + ob_start(); + $form->display(); + $html = ob_get_clean(); + + // Check that the wierdtestname element is part of the form. + $pos = strpos($html, 'wierdtestname'); + $this->assertNotFalse($pos); + } +} diff --git a/backup/util/ui/tests/fixtures/copy_form_hook_callbacks.php b/backup/util/ui/tests/fixtures/copy_form_hook_callbacks.php new file mode 100644 index 00000000000..07d8c9e9d8c --- /dev/null +++ b/backup/util/ui/tests/fixtures/copy_form_hook_callbacks.php @@ -0,0 +1,38 @@ +. + +namespace core_backup\fixtures; + +use core_backup\hook\after_copy_form_definition; + +/** + * Callback for testing after_copy_form_definition hook. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class copy_form_hook_callbacks { + /** + * Callback for testing after_copy_form_definition hook. + * + * @param after_copy_form_definition $hook + */ + public static function after_copy_form_definition(after_copy_form_definition $hook) { + $mform = $hook->mform; + $mform->addElement('checkbox', 'wierdtestname', 'Wierd test'); + } +} diff --git a/backup/util/ui/tests/fixtures/copy_form_hooks.php b/backup/util/ui/tests/fixtures/copy_form_hooks.php new file mode 100644 index 00000000000..4e710226122 --- /dev/null +++ b/backup/util/ui/tests/fixtures/copy_form_hooks.php @@ -0,0 +1,40 @@ +. + +/** + * Hooks used in testing. + * + * @package core_backup + * @copyright 2024 Monash University (https://www.monash.edu) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_backup\hook\after_copy_form_definition; +use core_backup\fixtures\copy_form_hook_callbacks; + +require_once(__DIR__ . '/copy_form_hook_callbacks.php'); + +$callbacks = [ + [ + 'hook' => after_copy_form_definition::class, + 'callback' => [ + copy_form_hook_callbacks::class, + 'after_copy_form_definition', + ], + ], +]; diff --git a/lib/classes/task/asynchronous_copy_task.php b/lib/classes/task/asynchronous_copy_task.php index 323ee3e356d..300d63dee4c 100644 --- a/lib/classes/task/asynchronous_copy_task.php +++ b/lib/classes/task/asynchronous_copy_task.php @@ -25,8 +25,11 @@ namespace core\task; +use core\di; use async_helper; use cache_helper; +use core\hook\manager; +use core_backup\hook\before_copy_course_execute; defined('MOODLE_INTERNAL') || die(); @@ -125,6 +128,10 @@ class asynchronous_copy_task extends adhoc_task { $shortname = $plan->get_setting('course_shortname'); $shortname->set_value($copyinfo->shortname); + // Create and dispatch a hook to allow interaction with the task immediately prior to execution. + $hook = new before_copy_course_execute($plan, $copyinfo); + di::get(manager::class)->dispatch($hook); + // Do some preflight checks on the restore. $rc->execute_precheck(); $status = $rc->get_status();