diff --git a/mod/wiki/backup/moodle2/restore_wiki_stepslib.php b/mod/wiki/backup/moodle2/restore_wiki_stepslib.php index 4a93bcffc6d..1a2facd4a58 100644 --- a/mod/wiki/backup/moodle2/restore_wiki_stepslib.php +++ b/mod/wiki/backup/moodle2/restore_wiki_stepslib.php @@ -61,6 +61,7 @@ class restore_wiki_activity_structure_step extends restore_activity_structure_st // See MDL-9367. $data->editbegin = $this->apply_date_offset($data->editbegin); $data->editend = $this->apply_date_offset($data->editend); + $data->defaultformat = clean_param($data->defaultformat, PARAM_ALPHA); // insert the wiki record $newitemid = $DB->insert_record('wiki', $data); @@ -120,7 +121,7 @@ class restore_wiki_activity_structure_step extends restore_activity_structure_st $oldid = $data->id; $data->pageid = $this->get_new_parentid('wiki_page'); $data->userid = $this->get_mappingid('user', $data->userid); - + $data->contentformat = clean_param($data->contentformat, PARAM_ALPHA); $newitemid = $DB->insert_record('wiki_versions', $data); $this->set_mapping('wiki_version', $oldid, $newitemid); } diff --git a/mod/wiki/parser/parser.php b/mod/wiki/parser/parser.php index a8bd62f17e6..1865a2f590b 100644 --- a/mod/wiki/parser/parser.php +++ b/mod/wiki/parser/parser.php @@ -44,16 +44,20 @@ defined('MOODLE_INTERNAL') || die(); * @package mod_wiki */ class wiki_parser_proxy { - private static $parsers = array(); - private static $basepath = ""; - - public static function parse(&$string, $type, $options = array()) { - - if (empty(self::$basepath)) { - global $CFG; - self::$basepath = $CFG->dirroot . '/mod/wiki/parser/'; - } + /** + * @var array $parsers Array of parser instances + */ + private static $parsers = []; + /** + * Parse a string using a specific parser + * + * @param string $string The string to parse + * @param string $type The parser type + * @param array $options The parser options + * @return mixed The parsed string or false if the parser type is not found + */ + public static function parse(&$string, $type, $options = []) { $type = strtolower($type); self::$parsers[$type] = null; // Reset the current parser because it may have other options. if (self::create_parser_instance($type)) { @@ -86,8 +90,14 @@ class wiki_parser_proxy { } private static function create_parser_instance($type) { + global $CFG; + $type = clean_param($type, PARAM_ALPHA); if (empty(self::$parsers[$type])) { - include_once(self::$basepath . "markups/$type.php"); + $path = "$CFG->dirroot/mod/wiki/parser/markups/$type.php"; + if (!file_exists($path)) { + throw new moodle_exception("Parser type $type not found"); + } + include_once($path); $class = strtolower($type) . "_parser"; if (class_exists($class)) { self::$parsers[$type] = new $class; diff --git a/mod/wiki/tests/backup/restore_format_test.php b/mod/wiki/tests/backup/restore_format_test.php new file mode 100644 index 00000000000..0c4ff22f62a --- /dev/null +++ b/mod/wiki/tests/backup/restore_format_test.php @@ -0,0 +1,80 @@ +. + +namespace mod_wiki\backup; + +/** + * Unit tests for wiki restoration process + * + * @package mod_wiki + * @copyright 2024 Laurent David + * + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_format_test extends \advanced_testcase { + + /** + * Data provider for test_duplicating_wiki_removes_unwanted_formats. + * + * @return array[] + */ + public static function restore_format_test_provider(): array { + return [ + 'creole' => [ + 'data' => 'creole', + 'expected' => 'creole', + ], + 'html' => [ + 'data' => 'html', + 'expected' => 'html', + ], + 'wikimarkup' => [ + 'data' => 'nwiki', + 'expected' => 'nwiki', + ], + 'wrong format' => [ + 'data' => '../wrongformat123', + 'expected' => 'wrongformat', + ], + ]; + } + + /** + * Test that duplicating a wiki removes unwanted / invalid format. + * + * @param string $format The format of the wiki. + * @param string $expected The expected format of the wiki after duplication. + * + * @covers \restore_wiki_activity_structure_step + * @dataProvider restore_format_test_provider + */ + public function test_duplicating_wiki_removes_unwanted_formats(string $format, string $expected): void { + global $DB; + + $this->resetAfterTest(); + $this->setAdminUser(); + + // Make a test course. + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + $wiki = $generator->create_module('wiki', array_merge(['course' => $course->id, 'defaultformat' => $format])); + // Duplicate the wiki. + $newwikicm = duplicate_module($course, get_fast_modinfo($course)->get_cm($wiki->cmid)); + // Verify the settings of the duplicated activity. + $newwiki = $DB->get_record('wiki', ['id' => $newwikicm->instance]); + $this->assertEquals($expected, $newwiki->defaultformat); + } +} diff --git a/mod/wiki/tests/wikiparser_test.php b/mod/wiki/tests/wikiparser_test.php index 3ce41fd87a9..d267cb5b517 100644 --- a/mod/wiki/tests/wikiparser_test.php +++ b/mod/wiki/tests/wikiparser_test.php @@ -39,7 +39,7 @@ require_once($CFG->dirroot . '/mod/wiki/parser/parser.php'); * * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class wikiparser_test extends \basic_testcase { +class wikiparser_test extends \advanced_testcase { /** * URL inside the clickable text of some link should not be turned into a new link via the url_tag_rule. @@ -332,4 +332,52 @@ class wikiparser_test extends \basic_testcase { $this->assertNotEquals(false, $section); } + /** + * Test that format that are not supported are raising an exception + * + * @param string $format + * @param string $expected + * @covers \wiki_parser_proxy::parse + * @dataProvider format_parser_provider + */ + public function test_format_parser(string $format, string $expected) { + $this->resetAfterTest(); + $this->setAdminUser(); + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + $wiki = $generator->create_module('wiki', array_merge(['course' => $course->id, 'defaultformat' => $format])); + $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki'); + if ($expected === 'exception') { + $this->expectException(\moodle_exception::class); + } + $page = $wikigenerator->create_page($wiki); + $version = wiki_get_current_version($page->id); + $this->assertEquals($expected, $version->contentformat); + } + + /** + * Data provider for test_format_parser + * + * @return array[] + */ + public static function format_parser_provider(): array { + return [ + 'creole' => [ + 'data' => 'creole', + 'expected' => 'creole', + ], + 'html' => [ + 'data' => 'html', + 'expected' => 'html', + ], + 'wikimarkup' => [ + 'data' => 'nwiki', + 'expected' => 'nwiki', + ], + 'wrong format' => [ + 'data' => '../wrongformat123', + 'expected' => 'exception', + ], + ]; + } }