From 5d94e34322d14578870dec8dcc6eb28fe9d383ed Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 30 Oct 2015 12:20:33 +0100 Subject: [PATCH 1/2] MDL-51986 wiki: New WS mod_wiki_get_page_contents --- mod/wiki/classes/external.php | 105 ++++++++++++++++++++++++++++++++++ mod/wiki/db/services.php | 9 +++ mod/wiki/version.php | 2 +- 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/mod/wiki/classes/external.php b/mod/wiki/classes/external.php index a6634c51ed6..767a6624048 100644 --- a/mod/wiki/classes/external.php +++ b/mod/wiki/classes/external.php @@ -594,4 +594,109 @@ class mod_wiki_external extends external_api { ); } + /** + * Describes the parameters for get_page_contents. + * + * @return external_function_parameters + * @since Moodle 3.1 + */ + public static function get_page_contents_parameters() { + return new external_function_parameters ( + array( + 'pageid' => new external_value(PARAM_INT, 'Page ID.') + ) + ); + } + + /** + * Get a page contents. + * + * @param int $pageid The page ID. + * @return array of warnings and page data. + * @since Moodle 3.1 + */ + public static function get_page_contents($pageid) { + + $params = self::validate_parameters(self::get_page_contents_parameters(), + array( + 'pageid' => $pageid + ) + ); + $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'); + } + + // Permission validation. + $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course); + $context = context_module::instance($cm->id); + self::validate_context($context); + + // Check if user can view this wiki. + if (!$subwiki = wiki_get_subwiki($page->subwikiid)) { + throw new moodle_exception('incorrectsubwikiid', 'wiki'); + } + if (!wiki_user_can_view($subwiki, $wiki)) { + throw new moodle_exception('cannotviewpage', 'wiki'); + } + + $returnedpage = array(); + $returnedpage['id'] = $page->id; + $returnedpage['wikiid'] = $wiki->id; + $returnedpage['subwikiid'] = $page->subwikiid; + $returnedpage['groupid'] = $subwiki->groupid; + $returnedpage['userid'] = $subwiki->userid; + $returnedpage['title'] = $page->title; + + // Refresh page cached content if needed. + if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) { + if ($content = wiki_refresh_cachedcontent($page)) { + $page = $content['page']; + } + } + + list($returnedpage['cachedcontent'], $returnedpage['contentformat']) = external_format_text( + $page->cachedcontent, FORMAT_HTML, $context->id, 'mod_wiki', 'attachments', $subwiki->id); + $returnedpage['caneditpage'] = wiki_user_can_edit($subwiki); + + $result = array(); + $result['page'] = $returnedpage; + $result['warnings'] = $warnings; + return $result; + } + + /** + * Describes the get_page_contents return value. + * + * @return external_single_structure + * @since Moodle 3.1 + */ + public static function get_page_contents_returns() { + return new external_single_structure( + array( + 'page' => new external_single_structure( + array( + 'id' => new external_value(PARAM_INT, 'Page ID.'), + 'wikiid' => new external_value(PARAM_INT, 'Page\'s wiki ID.'), + 'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.'), + 'groupid' => new external_value(PARAM_INT, 'Page\'s group ID.'), + 'userid' => new external_value(PARAM_INT, 'Page\'s user ID.'), + 'title' => new external_value(PARAM_RAW, 'Page title.'), + 'cachedcontent' => new external_value(PARAM_RAW, 'Page contents.'), + 'contentformat' => new external_format_value('cachedcontent', VALUE_OPTIONAL), + 'caneditpage' => new external_value(PARAM_BOOL, 'True if user can edit the page.') + ), 'Page' + ), + 'warnings' => new external_warnings() + ) + ); + } + } diff --git a/mod/wiki/db/services.php b/mod/wiki/db/services.php index 68942601349..396e572fb61 100644 --- a/mod/wiki/db/services.php +++ b/mod/wiki/db/services.php @@ -69,5 +69,14 @@ $functions = array( 'type' => 'read', 'capabilities' => 'mod/wiki:viewpage', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), + + 'mod_wiki_get_page_contents' => array( + 'classname' => 'mod_wiki_external', + 'methodname' => 'get_page_contents', + 'description' => 'Returns the contents of a page.', + 'type' => 'read', + 'capabilities' => 'mod/wiki:viewpage', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ) ); diff --git a/mod/wiki/version.php b/mod/wiki/version.php index b7707efd2c1..f0472bd6972 100644 --- a/mod/wiki/version.php +++ b/mod/wiki/version.php @@ -33,7 +33,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016011102; // The current module version (Date: YYYYMMDDXX) +$plugin->version = 2016011103; // The current module version (Date: YYYYMMDDXX) $plugin->requires = 2015111000; // Requires this Moodle version $plugin->component = 'mod_wiki'; // Full name of the plugin (used for diagnostics) $plugin->cron = 0; From 9a4c52221e4e71e7d9483be34ec1cf3b7790fb11 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 30 Oct 2015 13:43:39 +0100 Subject: [PATCH 2/2] MDL-51986 wiki: Add tests for mod_wiki_get_page_contents --- mod/wiki/tests/externallib_test.php | 134 ++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/mod/wiki/tests/externallib_test.php b/mod/wiki/tests/externallib_test.php index ec1ddf840ea..31e24be61e8 100644 --- a/mod/wiki/tests/externallib_test.php +++ b/mod/wiki/tests/externallib_test.php @@ -873,4 +873,138 @@ class mod_wiki_external_testcase extends externallib_advanced_testcase { $this->assertEquals($expectedpages, $result['pages']); } + /** + * Test get_page_contents using an invalid pageid. + */ + public function test_get_page_contents_invalid_pageid() { + $this->setExpectedException('moodle_exception'); + mod_wiki_external::get_page_contents(0); + } + + /** + * Test get_page_contents using a user not enrolled in the course. + */ + public function test_get_page_contents_unenrolled_user() { + // Create and use the user. + $usernotenrolled = self::getDataGenerator()->create_user(); + $this->setUser($usernotenrolled); + + $this->setExpectedException('require_login_exception'); + mod_wiki_external::get_page_contents($this->firstpage->id); + } + + /** + * Test get_page_contents using a hidden wiki as student. + */ + public function test_get_page_contents_hidden_wiki_as_student() { + // Create a hidden wiki and try to get a page contents. + $hiddenwiki = $this->getDataGenerator()->create_module('wiki', + array('course' => $this->course->id, 'visible' => false)); + $hiddenpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page($hiddenwiki); + + $this->setUser($this->student); + $this->setExpectedException('require_login_exception'); + mod_wiki_external::get_page_contents($hiddenpage->id); + } + + /** + * Test get_page_contents without the viewpage capability. + */ + public function test_get_page_contents_without_viewpage_capability() { + // Prohibit capability = mod/wiki:viewpage on the course for students. + $contextcourse = context_course::instance($this->course->id); + assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $contextcourse->id); + accesslib_clear_all_caches_for_unit_testing(); + + $this->setUser($this->student); + $this->setExpectedException('moodle_exception'); + mod_wiki_external::get_page_contents($this->firstpage->id); + } + + /** + * Test get_page_contents, check that a student can't get a page from another group when + * using separate groups. + */ + public function test_get_page_contents_separate_groups_student_see_other_group() { + // Create testing data. + $this->create_individual_wikis_with_groups(); + + $this->setUser($this->student); + $this->setExpectedException('moodle_exception'); + mod_wiki_external::get_page_contents($this->fpsepg2indt->id); + } + + /** + * Test get_page_contents without groups. We won't test all the possible cases because that's already + * done in the tests for get_subwiki_pages. + */ + public function test_get_page_contents() { + + // Test user with full capabilities. + $this->setUser($this->student); + + // Set expected result: first page. + $expectedpage = array( + 'id' => $this->firstpage->id, + 'wikiid' => $this->wiki->id, + 'subwikiid' => $this->firstpage->subwikiid, + 'groupid' => 0, // No groups. + 'userid' => 0, // Collaborative. + 'title' => $this->firstpage->title, + 'cachedcontent' => $this->firstpage->cachedcontent, + 'contentformat' => 1, + 'caneditpage' => true + ); + + $result = mod_wiki_external::get_page_contents($this->firstpage->id); + $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result); + $this->assertEquals($expectedpage, $result['page']); + + // Add a new page to the wiki and test with it. + $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page($this->wiki); + + $expectedpage['id'] = $newpage->id; + $expectedpage['title'] = $newpage->title; + $expectedpage['cachedcontent'] = $newpage->cachedcontent; + + $result = mod_wiki_external::get_page_contents($newpage->id); + $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result); + $this->assertEquals($expectedpage, $result['page']); + } + + /** + * Test get_page_contents with groups. We won't test all the possible cases because that's already + * done in the tests for get_subwiki_pages. + */ + public function test_get_page_contents_with_groups() { + + // Create testing data. + $this->create_individual_wikis_with_groups(); + + // Try to get page from a valid group in separate groups wiki. + $this->setUser($this->student); + + $expectedfpsepg1indstu = array( + 'id' => $this->fpsepg1indstu->id, + 'wikiid' => $this->wikisepind->id, + 'subwikiid' => $this->fpsepg1indstu->subwikiid, + 'groupid' => $this->group1->id, + 'userid' => $this->student->id, + 'title' => $this->fpsepg1indstu->title, + 'cachedcontent' => $this->fpsepg1indstu->cachedcontent, + 'contentformat' => 1, + 'caneditpage' => true + ); + + $result = mod_wiki_external::get_page_contents($this->fpsepg1indstu->id); + $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result); + $this->assertEquals($expectedfpsepg1indstu, $result['page']); + + // Check that teacher can view a group pages without belonging to it. + $this->setUser($this->teacher); + $result = mod_wiki_external::get_page_contents($this->fpsepg1indstu->id); + $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result); + $this->assertEquals($expectedfpsepg1indstu, $result['page']); + } + }