diff --git a/mod/wiki/classes/external.php b/mod/wiki/classes/external.php index 957a6683d9b..4d8f00b533d 100644 --- a/mod/wiki/classes/external.php +++ b/mod/wiki/classes/external.php @@ -1075,4 +1075,109 @@ class mod_wiki_external extends external_api { ); } + /** + * Describes the parameters for edit_page. + * + * @return external_function_parameters + * @since Moodle 3.1 + */ + public static function edit_page_parameters() { + return new external_function_parameters ( + array( + 'pageid' => new external_value(PARAM_INT, 'Page ID.'), + 'content' => new external_value(PARAM_RAW, 'Page contents.'), + 'section' => new external_value(PARAM_TEXT, 'Section page title.', VALUE_DEFAULT, null) + ) + ); + } + + /** + * Edit a page contents. + * + * @param int $pageid The page ID. + * @param string $content Page contents. + * @param int $section Section to be edited. + * @return array of warnings and page data. + * @since Moodle 3.1 + */ + public static function edit_page($pageid, $content, $section = null) { + global $USER; + + $params = self::validate_parameters(self::edit_page_parameters(), + array( + 'pageid' => $pageid, + 'content' => $content, + 'section' => $section + ) + ); + $warnings = array(); + + // Get wiki page. + if (!$page = wiki_get_page($params['pageid'])) { + throw new moodle_exception('incorrectpageid', 'wiki'); + } + + // Get wiki instance. + if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) { + throw new moodle_exception('incorrectwikiid', 'wiki'); + } + + // Get subwiki instance. + if (!$subwiki = wiki_get_subwiki($page->subwikiid)) { + throw new moodle_exception('incorrectsubwikiid', 'wiki'); + } + + // Permission validation. + $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course); + $context = context_module::instance($cm->id); + self::validate_context($context); + + if (!wiki_user_can_edit($subwiki)) { + throw new moodle_exception('cannoteditpage', 'wiki'); + } + + if (wiki_is_page_section_locked($page->id, $USER->id, $params['section'])) { + throw new moodle_exception('pageislocked', 'wiki'); + } + + // Save content. + if (!is_null($params['section'])) { + $version = wiki_get_current_version($page->id); + $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $params['section'], false); + if (!$content) { + throw new moodle_exception('invalidsection', 'wiki'); + } + + $save = wiki_save_section($page, $params['section'], $params['content'], $USER->id); + } else { + $save = wiki_save_page($page, $params['content'], $USER->id); + } + + wiki_delete_locks($page->id, $USER->id, $params['section']); + + if (!$save) { + throw new moodle_exception('savingerror', 'wiki'); + } + + $result = array(); + $result['pageid'] = $page->id; + $result['warnings'] = $warnings; + return $result; + } + + /** + * Describes the edit_page return value. + * + * @return external_single_structure + * @since Moodle 3.1 + */ + public static function edit_page_returns() { + return new external_single_structure( + array( + 'pageid' => new external_value(PARAM_INT, 'Edited page id.'), + 'warnings' => new external_warnings() + ) + ); + } + } diff --git a/mod/wiki/db/services.php b/mod/wiki/db/services.php index 7aa2968b5fc..90e3eb85e80 100644 --- a/mod/wiki/db/services.php +++ b/mod/wiki/db/services.php @@ -105,5 +105,14 @@ $functions = array( 'type' => 'write', 'capabilities' => 'mod/wiki:editpage', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), + + 'mod_wiki_edit_page' => array( + 'classname' => 'mod_wiki_external', + 'methodname' => 'edit_page', + 'description' => 'Save the contents of a page.', + 'type' => 'write', + 'capabilities' => 'mod/wiki:editpage', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ) ); diff --git a/mod/wiki/tests/externallib_test.php b/mod/wiki/tests/externallib_test.php index 1abc2c7dc1c..3cb4e83965d 100644 --- a/mod/wiki/tests/externallib_test.php +++ b/mod/wiki/tests/externallib_test.php @@ -1239,4 +1239,68 @@ class mod_wiki_external_testcase extends externallib_advanced_testcase { } + /** + * Test edit_page. We won't test all the possible cases because that's already + * done in the tests for wiki_save_section / wiki_save_page. + */ + public function test_edit_page() { + + $this->create_individual_wikis_with_groups(); + + // Test user with full capabilities. + $this->setUser($this->student); + + $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page($this->wikisepind, + array('group' => $this->group1->id, 'content' => 'Test')); + + // Test edit whole page. + $sectioncontent = '

Title1

Text inside section'; + $newpagecontent = $sectioncontent.'

Title2

Text inside section'; + + $result = mod_wiki_external::edit_page($newpage->id, $newpagecontent); + $result = external_api::clean_returnvalue(mod_wiki_external::edit_page_returns(), $result); + $this->assertInternalType('int', $result['pageid']); + + $version = wiki_get_current_version($result['pageid']); + $this->assertEquals($newpagecontent, $version->content); + + // Test edit section. + $newsectioncontent = '

Title2

New test2'; + $section = 'Title2'; + + $result = mod_wiki_external::edit_page($newpage->id, $newsectioncontent, $section); + $result = external_api::clean_returnvalue(mod_wiki_external::edit_page_returns(), $result); + $this->assertInternalType('int', $result['pageid']); + + $expected = $sectioncontent . $newsectioncontent; + + $version = wiki_get_current_version($result['pageid']); + $this->assertEquals($expected, $version->content); + + // Test locked section. + $newsectioncontent = '

Title2

New test2'; + $section = 'Title2'; + + try { + // Using user 1 to avoid other users to edit. + wiki_set_lock($newpage->id, 1, $section, true); + mod_wiki_external::edit_page($newpage->id, $newsectioncontent, $section); + $this->fail('Exception expected due to locked section'); + } catch (moodle_exception $e) { + $this->assertEquals('pageislocked', $e->errorcode); + } + + // Test edit non existing section. + $newsectioncontent = '

Title3

New test3'; + $section = 'Title3'; + + try { + mod_wiki_external::edit_page($newpage->id, $newsectioncontent, $section); + $this->fail('Exception expected due to non existing section in the page.'); + } catch (moodle_exception $e) { + $this->assertEquals('invalidsection', $e->errorcode); + } + + } + }