diff --git a/backup/moodle2/restore_activity_task.class.php b/backup/moodle2/restore_activity_task.class.php index a1b9b8bd1f5..c254db1942d 100644 --- a/backup/moodle2/restore_activity_task.class.php +++ b/backup/moodle2/restore_activity_task.class.php @@ -182,6 +182,13 @@ abstract class restore_activity_task extends restore_task { // Activity competencies. $this->add_step(new restore_activity_competencies_structure_step('activity_competencies', 'competencies.xml')); + // Search reindexing, if enabled and if not restoring entire course. + if (\core_search\manager::is_indexing_enabled() && + !($this->get_target() == backup::TARGET_NEW_COURSE || + $this->get_setting_value('overwrite_conf'))) { + $this->add_step(new restore_activity_search_index('activity_search_index')); + } + // At the end, mark it as built $this->built = true; } diff --git a/backup/moodle2/restore_block_task.class.php b/backup/moodle2/restore_block_task.class.php index 64e5b994698..164f37c80bc 100644 --- a/backup/moodle2/restore_block_task.class.php +++ b/backup/moodle2/restore_block_task.class.php @@ -98,6 +98,13 @@ abstract class restore_block_task extends restore_task { $this->add_step(new restore_comments_structure_step('block_comments', 'comments.xml')); } + // Search reindexing (if enabled). + if (\core_search\manager::is_indexing_enabled() && + !($this->get_target() == backup::TARGET_NEW_COURSE || + $this->get_setting_value('overwrite_conf'))) { + $this->add_step(new restore_block_search_index('block_search_index')); + } + // At the end, mark it as built $this->built = true; } diff --git a/backup/moodle2/restore_course_task.class.php b/backup/moodle2/restore_course_task.class.php index 74bfa6c17c3..2121c02b06c 100644 --- a/backup/moodle2/restore_course_task.class.php +++ b/backup/moodle2/restore_course_task.class.php @@ -69,6 +69,11 @@ class restore_course_task extends restore_task { // Executed conditionally if restoring to new course or if overwrite_conf setting is enabled if ($this->get_target() == backup::TARGET_NEW_COURSE || $this->get_setting_value('overwrite_conf') == true) { $this->add_step(new restore_course_structure_step('course_info', 'course.xml')); + + // Search reindexing (if enabled). + if (\core_search\manager::is_indexing_enabled()) { + $this->add_step(new restore_course_search_index('course_search_index')); + } } $this->add_step(new restore_course_legacy_files_step('legacy_files')); diff --git a/backup/moodle2/restore_final_task.class.php b/backup/moodle2/restore_final_task.class.php index 1bb3e51e638..34c93d466e6 100644 --- a/backup/moodle2/restore_final_task.class.php +++ b/backup/moodle2/restore_final_task.class.php @@ -114,6 +114,13 @@ class restore_final_task extends restore_task { // Clean the temp dir (conditionally) and drop temp table $this->add_step(new restore_drop_and_clean_temp_stuff('drop_and_clean_temp_stuff')); + // If restoring to a new course or overwriting config, reindex the whole course. + if (\core_search\manager::is_indexing_enabled() && + ($this->get_target() == backup::TARGET_NEW_COURSE || + $this->get_setting_value('overwrite_conf'))) { + $this->add_step(new restore_course_search_index('course_search_index')); + } + $this->built = true; } diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 10872f824f1..b53ffa67e18 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -5544,6 +5544,58 @@ class restore_completion_defaults_structure_step extends restore_structure_step $this->set_mapping('course_completion_defaults', $oldid, $newid); } } + +/** + * Index course after restore. + * + * @package core_backup + * @copyright 2017 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_course_search_index extends restore_execution_step { + /** + * When this step is executed, we add the course context to the queue for reindexing. + */ + protected function define_execution() { + $context = \context_course::instance($this->task->get_courseid()); + \core_search\manager::request_index($context); + } +} + +/** + * Index activity after restore (when not restoring whole course). + * + * @package core_backup + * @copyright 2017 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_activity_search_index extends restore_execution_step { + /** + * When this step is executed, we add the activity context to the queue for reindexing. + */ + protected function define_execution() { + $context = \context::instance_by_id($this->task->get_contextid()); + \core_search\manager::request_index($context); + } +} + +/** + * Index block after restore (when not restoring whole course). + * + * @package core_backup + * @copyright 2017 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_block_search_index extends restore_execution_step { + /** + * When this step is executed, we add the block context to the queue for reindexing. + */ + protected function define_execution() { + $context = \context_block::instance($this->task->get_blockid()); + \core_search\manager::request_index($context); + } +} + /** * Restore action events. * diff --git a/backup/moodle2/tests/moodle2_test.php b/backup/moodle2/tests/moodle2_test.php index 21773b902b8..3b45eea4601 100644 --- a/backup/moodle2/tests/moodle2_test.php +++ b/backup/moodle2/tests/moodle2_test.php @@ -867,4 +867,92 @@ class core_backup_moodle2_testcase extends advanced_testcase { $this->assertTrue($before <= $blockdata->timecreated && $after >= $blockdata->timecreated); $this->assertTrue($before <= $blockdata->timemodified && $after >= $blockdata->timemodified); } + + /** + * When you restore a site with global search (or search indexing) turned on, then it should + * add entries to the search index requests table so that the data gets indexed. + */ + public function test_restore_search_index_requests() { + global $DB, $CFG, $USER; + + $this->resetAfterTest(true); + $this->setAdminUser(); + $CFG->enableglobalsearch = true; + + // Create a course. + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + + // Add a forum. + $forum = $generator->create_module('forum', ['course' => $course->id]); + + // Add a block. + $context = context_course::instance($course->id); + $page = new moodle_page(); + $page->set_context($context); + $page->set_course($course); + $page->set_pagelayout('standard'); + $page->set_pagetype('course-view'); + $page->blocks->load_blocks(); + $page->blocks->add_block_at_end_of_default_region('html'); + + // Initially there should be no search index requests. + $this->assertEquals(0, $DB->count_records('search_index_requests')); + + // Do backup and restore. + $newcourseid = $this->backup_and_restore($course); + + // Now the course should be requested for index (all search areas). + $newcontext = context_course::instance($newcourseid); + $requests = array_values($DB->get_records('search_index_requests')); + $this->assertCount(1, $requests); + $this->assertEquals($newcontext->id, $requests[0]->contextid); + $this->assertEquals('', $requests[0]->searcharea); + + get_fast_modinfo($newcourseid); + + // Backup the new course... + $CFG->backup_file_logger_level = backup::LOG_NONE; + $bc = new backup_controller(backup::TYPE_1COURSE, $newcourseid, + backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_IMPORT, + $USER->id); + $backupid = $bc->get_backupid(); + $bc->execute_plan(); + $bc->destroy(); + + // Restore it on top of old course (should duplicate the forum). + $rc = new restore_controller($backupid, $course->id, + backup::INTERACTIVE_NO, backup::MODE_GENERAL, $USER->id, + backup::TARGET_EXISTING_ADDING); + $this->assertTrue($rc->execute_precheck()); + $rc->execute_plan(); + $rc->destroy(); + + // Get the forums now on the old course. + $modinfo = get_fast_modinfo($course->id); + $forums = $modinfo->get_instances_of('forum'); + $this->assertCount(2, $forums); + + // The newer one will be the one with larger ID. (Safe to assume for unit test.) + $biggest = null; + foreach ($forums as $forum) { + if ($biggest === null || $biggest->id < $forum->id) { + $biggest = $forum; + } + } + $restoredforumcontext = \context_module::instance($biggest->id); + + // Get the HTML blocks now on the old course. + $blockdata = array_values($DB->get_records('block_instances', + ['blockname' => 'html', 'parentcontextid' => $context->id], 'id DESC')); + $restoredblockcontext = \context_block::instance($blockdata[0]->id); + + // Check that we have requested index update on both the module and the block. + $requests = array_values($DB->get_records('search_index_requests', null, 'id')); + $this->assertCount(3, $requests); + $this->assertEquals($restoredblockcontext->id, $requests[1]->contextid); + $this->assertEquals('', $requests[1]->searcharea); + $this->assertEquals($restoredforumcontext->id, $requests[2]->contextid); + $this->assertEquals('', $requests[2]->searcharea); + } }