diff --git a/mod/book/tool/importhtml/locallib.php b/mod/book/tool/importhtml/locallib.php index 3f6714258f7..41da0870731 100644 --- a/mod/book/tool/importhtml/locallib.php +++ b/mod/book/tool/importhtml/locallib.php @@ -134,12 +134,18 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $ // it is either absolute or pluginfile link continue; } - $chapterpath = dirname($chapter->importsrc).'/'.$matches[2][$i]; + + [$path, $anchor] = array_pad(explode('#', $matches[2][$i], 2), 2, ''); + if (!empty($anchor)) { + $anchor = '#' . $anchor; + } + + $chapterpath = dirname($chapter->importsrc).'/'.$path; $chapterpath = toolbook_importhtml_fix_path($chapterpath); foreach ($allchapters as $target) { if ($target->importsrc === $chapterpath) { - $newcontent = str_replace($match, 'href="'.new moodle_url('/mod/book/view.php', - array('id'=>$context->instanceid, 'chapterid'=>$target->id)).'"', $newcontent); + $newcontent = str_replace($match, 'href="' . new moodle_url('/mod/book/view.php', + ['id' => $context->instanceid, 'chapterid' => $target->id]) . $anchor . '"', $newcontent); } } } diff --git a/mod/book/tool/importhtml/tests/fixtures/chapters_links.zip b/mod/book/tool/importhtml/tests/fixtures/chapters_links.zip new file mode 100644 index 00000000000..df9a046a8dc Binary files /dev/null and b/mod/book/tool/importhtml/tests/fixtures/chapters_links.zip differ diff --git a/mod/book/tool/importhtml/tests/locallib_test.php b/mod/book/tool/importhtml/tests/locallib_test.php index 959ab18442c..0f9be881d23 100644 --- a/mod/book/tool/importhtml/tests/locallib_test.php +++ b/mod/book/tool/importhtml/tests/locallib_test.php @@ -39,41 +39,79 @@ require_once($CFG->dirroot.'/mod/book/tool/importhtml/locallib.php'); */ final class locallib_test extends \advanced_testcase { + /** @var object */ + private object $book; + /** @var object */ + private object $context; + /** @var object */ + private object $record; + public function setUp(): void { parent::setUp(); $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $this->book = $this->getDataGenerator()->create_module('book', ['course' => $course->id]); + $this->context = \context_module::instance($this->book->cmid); + $this->record = (object) [ + 'contextid' => $this->context->id, + 'component' => 'phpunit', + 'filearea' => 'test', + 'itemid' => 0, + 'filepath' => '/', + ]; } + /** + * Tests the events within toolbook_importhtml_import_chapters + * @covers ::toolbook_importhtml_import_chapters + */ public function test_import_chapters_events(): void { - $course = $this->getDataGenerator()->create_course(); - $book = $this->getDataGenerator()->create_module('book', array('course' => $course->id)); - $context = \context_module::instance($book->cmid); - $record = new \stdClass(); - $record->contextid = $context->id; - $record->component = 'phpunit'; - $record->filearea = 'test'; - $record->itemid = 0; - $record->filepath = '/'; - $record->filename = 'chapters.zip'; - - $fs = get_file_storage(); - $file = $fs->create_file_from_pathname($record, self::get_fixture_path(__NAMESPACE__, 'chapters.zip')); + $this->record->filename = 'chapters.zip'; + $file = get_file_storage()->create_file_from_pathname( + $this->record, + self::get_fixture_path(__NAMESPACE__, 'chapters.zip') + ); // Importing the chapters. $sink = $this->redirectEvents(); - toolbook_importhtml_import_chapters($file, 2, $book, $context, false); + toolbook_importhtml_import_chapters($file, 2, $this->book, $this->context, false); $events = $sink->get_events(); - // Checking the results. + // Checking the results up to the triggered event. $this->assertCount(5, $events); foreach ($events as $event) { $this->assertInstanceOf('\mod_book\event\chapter_created', $event); - $this->assertEquals($context, $event->get_context()); + $this->assertEquals($this->context, $event->get_context()); $chapter = $event->get_record_snapshot('book_chapters', $event->objectid); $this->assertNotEmpty($chapter); $this->assertEventContextNotUsed($event); } } + /** + * Tests the conversion of (anchored) links within toolbook_importhtml_import_chapters + * @covers ::toolbook_importhtml_import_chapters + */ + public function test_import_chapters_links(): void { + global $DB; + + $this->record->filename = 'chapters_links.zip'; + $file = get_file_storage()->create_file_from_pathname( + $this->record, + self::get_fixture_path(__NAMESPACE__, 'chapters_links.zip') + ); + + toolbook_importhtml_import_chapters($file, 2, $this->book, $this->context, false); + + $chapters = $DB->get_records('book_chapters', ['bookid' => $this->book->id]); + foreach ($chapters as $chapter) { + $this->assertStringNotContainsString('.html', $chapter->content); + $this->assertStringNotContainsString('.html#anchor', $chapter->content); + $this->assertMatchesRegularExpression('/chapterid=[0-9]*"/i', $chapter->content); + $this->assertMatchesRegularExpression('/chapterid=[0-9]*#anchor"/i', $chapter->content); + } + } + }