2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * Wiki module external API.
22 * @copyright 2015 Dani Palou <dani@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die;
29 require_once($CFG->libdir . '/externallib.php');
30 require_once($CFG->dirroot . '/mod/wiki/lib.php');
31 require_once($CFG->dirroot . '/mod/wiki/locallib.php');
34 * Wiki module external functions.
38 * @copyright 2015 Dani Palou <dani@moodle.com>
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42 class mod_wiki_external extends external_api {
45 * Describes the parameters for get_wikis_by_courses.
47 * @return external_function_parameters
50 public static function get_wikis_by_courses_parameters() {
51 return new external_function_parameters (
53 'courseids' => new external_multiple_structure(
54 new external_value(PARAM_INT, 'Course ID'), 'Array of course ids.', VALUE_DEFAULT, array()
61 * Returns a list of wikis in a provided list of courses,
62 * if no list is provided all wikis that the user can view will be returned.
64 * @param array $courseids The courses IDs.
65 * @return array Containing a list of warnings and a list of wikis.
68 public static function get_wikis_by_courses($courseids = array()) {
70 $returnedwikis = array();
73 $params = self::validate_parameters(self::get_wikis_by_courses_parameters(), array('courseids' => $courseids));
76 if (empty($params['courseids'])) {
77 $mycourses = enrol_get_my_courses();
78 $params['courseids'] = array_keys($mycourses);
81 // Ensure there are courseids to loop through.
82 if (!empty($params['courseids'])) {
84 list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses);
86 // Get the wikis in this course, this function checks users visibility permissions.
87 // We can avoid then additional validate_context calls.
88 $wikis = get_all_instances_in_courses('wiki', $courses);
90 foreach ($wikis as $wiki) {
92 $context = context_module::instance($wiki->coursemodule);
97 // First, we return information that any user can see in (or can deduce from) the web interface.
98 $module['id'] = $wiki->id;
99 $module['coursemodule'] = $wiki->coursemodule;
100 $module['course'] = $wiki->course;
101 $module['name'] = external_format_string($wiki->name, $context->id);
103 $viewablefields = [];
104 if (has_capability('mod/wiki:viewpage', $context)) {
105 list($module['intro'], $module['introformat']) =
106 external_format_text($wiki->intro, $wiki->introformat, $context->id, 'mod_wiki', 'intro', $wiki->id);
107 $module['introfiles'] = external_util::get_area_files($context->id, 'mod_wiki', 'intro', false, false);
109 $viewablefields = array('firstpagetitle', 'wikimode', 'defaultformat', 'forceformat', 'editbegin', 'editend',
110 'section', 'visible', 'groupmode', 'groupingid');
113 // Check additional permissions for returning optional private settings.
114 if (has_capability('moodle/course:manageactivities', $context)) {
115 $additionalfields = array('timecreated', 'timemodified');
116 $viewablefields = array_merge($viewablefields, $additionalfields);
119 foreach ($viewablefields as $field) {
120 $module[$field] = $wiki->{$field};
123 // Check if user can add new pages.
124 $module['cancreatepages'] = wiki_can_create_pages($context);
126 $returnedwikis[] = $module;
131 $result['wikis'] = $returnedwikis;
132 $result['warnings'] = $warnings;
137 * Describes the get_wikis_by_courses return value.
139 * @return external_single_structure
142 public static function get_wikis_by_courses_returns() {
144 return new external_single_structure(
146 'wikis' => new external_multiple_structure(
147 new external_single_structure(
149 'id' => new external_value(PARAM_INT, 'Wiki ID.'),
150 'coursemodule' => new external_value(PARAM_INT, 'Course module ID.'),
151 'course' => new external_value(PARAM_INT, 'Course ID.'),
152 'name' => new external_value(PARAM_RAW, 'Wiki name.'),
153 'intro' => new external_value(PARAM_RAW, 'Wiki intro.', VALUE_OPTIONAL),
154 'introformat' => new external_format_value('Wiki intro format.', VALUE_OPTIONAL),
155 'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
156 'timecreated' => new external_value(PARAM_INT, 'Time of creation.', VALUE_OPTIONAL),
157 'timemodified' => new external_value(PARAM_INT, 'Time of last modification.', VALUE_OPTIONAL),
158 'firstpagetitle' => new external_value(PARAM_RAW, 'First page title.', VALUE_OPTIONAL),
159 'wikimode' => new external_value(PARAM_TEXT, 'Wiki mode (individual, collaborative).', VALUE_OPTIONAL),
160 'defaultformat' => new external_value(PARAM_TEXT, 'Wiki\'s default format (html, creole, nwiki).',
162 'forceformat' => new external_value(PARAM_INT, '1 if format is forced, 0 otherwise.',
164 'editbegin' => new external_value(PARAM_INT, 'Edit begin.', VALUE_OPTIONAL),
165 'editend' => new external_value(PARAM_INT, 'Edit end.', VALUE_OPTIONAL),
166 'section' => new external_value(PARAM_INT, 'Course section ID.', VALUE_OPTIONAL),
167 'visible' => new external_value(PARAM_INT, '1 if visible, 0 otherwise.', VALUE_OPTIONAL),
168 'groupmode' => new external_value(PARAM_INT, 'Group mode.', VALUE_OPTIONAL),
169 'groupingid' => new external_value(PARAM_INT, 'Group ID.', VALUE_OPTIONAL),
170 'cancreatepages' => new external_value(PARAM_BOOL, 'True if user can create pages.'),
174 'warnings' => new external_warnings(),
180 * Describes the parameters for view_wiki.
182 * @return external_function_parameters
185 public static function view_wiki_parameters() {
186 return new external_function_parameters (
188 'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.')
194 * Trigger the course module viewed event and update the module completion status.
196 * @param int $wikiid The wiki instance ID.
197 * @return array of warnings and status result.
200 public static function view_wiki($wikiid) {
202 $params = self::validate_parameters(self::view_wiki_parameters(),
208 // Get wiki instance.
209 if (!$wiki = wiki_get_wiki($params['wikiid'])) {
210 throw new moodle_exception('incorrectwikiid', 'wiki');
213 // Permission validation.
214 list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
215 $context = context_module::instance($cm->id);
216 self::validate_context($context);
218 // Check if user can view this wiki.
219 // We don't use wiki_user_can_view because it requires to have a valid subwiki for the user.
220 if (!has_capability('mod/wiki:viewpage', $context)) {
221 throw new moodle_exception('cannotviewpage', 'wiki');
224 // Trigger course_module_viewed event and completion.
225 wiki_view($wiki, $course, $cm, $context);
228 $result['status'] = true;
229 $result['warnings'] = $warnings;
234 * Describes the view_wiki return value.
236 * @return external_single_structure
239 public static function view_wiki_returns() {
240 return new external_single_structure(
242 'status' => new external_value(PARAM_BOOL, 'Status: true if success.'),
243 'warnings' => new external_warnings()
249 * Describes the parameters for view_page.
251 * @return external_function_parameters
254 public static function view_page_parameters() {
255 return new external_function_parameters (
257 'pageid' => new external_value(PARAM_INT, 'Wiki page ID.'),
263 * Trigger the page viewed event and update the module completion status.
265 * @param int $pageid The page ID.
266 * @return array of warnings and status result.
268 * @throws moodle_exception if page is not valid.
270 public static function view_page($pageid) {
272 $params = self::validate_parameters(self::view_page_parameters(),
279 if (!$page = wiki_get_page($params['pageid'])) {
280 throw new moodle_exception('incorrectpageid', 'wiki');
283 // Get wiki instance.
284 if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
285 throw new moodle_exception('incorrectwikiid', 'wiki');
288 // Permission validation.
289 list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
290 $context = context_module::instance($cm->id);
291 self::validate_context($context);
293 // Check if user can view this wiki.
294 if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
295 throw new moodle_exception('incorrectsubwikiid', 'wiki');
297 if (!wiki_user_can_view($subwiki, $wiki)) {
298 throw new moodle_exception('cannotviewpage', 'wiki');
301 // Trigger page_viewed event and completion.
302 wiki_page_view($wiki, $page, $course, $cm, $context);
305 $result['status'] = true;
306 $result['warnings'] = $warnings;
311 * Describes the view_page return value.
313 * @return external_single_structure
316 public static function view_page_returns() {
317 return new external_single_structure(
319 'status' => new external_value(PARAM_BOOL, 'Status: true if success.'),
320 'warnings' => new external_warnings()
326 * Describes the parameters for get_subwikis.
328 * @return external_function_parameters
331 public static function get_subwikis_parameters() {
332 return new external_function_parameters (
334 'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.')
340 * Returns the list of subwikis the user can see in a specific wiki.
342 * @param int $wikiid The wiki instance ID.
343 * @return array Containing a list of warnings and a list of subwikis.
346 public static function get_subwikis($wikiid) {
351 $params = self::validate_parameters(self::get_subwikis_parameters(), array('wikiid' => $wikiid));
353 // Get wiki instance.
354 if (!$wiki = wiki_get_wiki($params['wikiid'])) {
355 throw new moodle_exception('incorrectwikiid', 'wiki');
358 // Validate context and capabilities.
359 list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
360 $context = context_module::instance($cm->id);
361 self::validate_context($context);
362 require_capability('mod/wiki:viewpage', $context);
364 $returnedsubwikis = wiki_get_visible_subwikis($wiki, $cm, $context);
365 foreach ($returnedsubwikis as $subwiki) {
366 $subwiki->canedit = wiki_user_can_edit($subwiki);
370 $result['subwikis'] = $returnedsubwikis;
371 $result['warnings'] = $warnings;
376 * Describes the get_subwikis return value.
378 * @return external_single_structure
381 public static function get_subwikis_returns() {
382 return new external_single_structure(
384 'subwikis' => new external_multiple_structure(
385 new external_single_structure(
387 'id' => new external_value(PARAM_INT, 'Subwiki ID.'),
388 'wikiid' => new external_value(PARAM_INT, 'Wiki ID.'),
389 'groupid' => new external_value(PARAM_RAW, 'Group ID.'),
390 'userid' => new external_value(PARAM_INT, 'User ID.'),
391 'canedit' => new external_value(PARAM_BOOL, 'True if user can edit the subwiki.'),
395 'warnings' => new external_warnings(),
401 * Describes the parameters for get_subwiki_pages.
403 * @return external_function_parameters
406 public static function get_subwiki_pages_parameters() {
407 return new external_function_parameters (
409 'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.'),
410 'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID, -1 means current group. It will be ignored'
411 . ' if the wiki doesn\'t use groups.', VALUE_DEFAULT, -1),
412 'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID, 0 means current user. It will be ignored'
413 .' in collaborative wikis.', VALUE_DEFAULT, 0),
414 'options' => new external_single_structure(
416 'sortby' => new external_value(PARAM_ALPHA,
417 'Field to sort by (id, title, ...).', VALUE_DEFAULT, 'title'),
418 'sortdirection' => new external_value(PARAM_ALPHA,
419 'Sort direction: ASC or DESC.', VALUE_DEFAULT, 'ASC'),
420 'includecontent' => new external_value(PARAM_INT,
421 'Include each page contents or just the contents size.', VALUE_DEFAULT, 1),
422 ), 'Options', VALUE_DEFAULT, array()),
428 * Returns the list of pages from a specific subwiki.
430 * @param int $wikiid The wiki instance ID.
431 * @param int $groupid The group ID. If not defined, use current group.
432 * @param int $userid The user ID. If not defined, use current user.
433 * @param array $options Several options like sort by, sort direction, ...
434 * @return array Containing a list of warnings and a list of pages.
437 public static function get_subwiki_pages($wikiid, $groupid = -1, $userid = 0, $options = array()) {
439 $returnedpages = array();
442 $params = self::validate_parameters(self::get_subwiki_pages_parameters(),
445 'groupid' => $groupid,
447 'options' => $options
451 // Get wiki instance.
452 if (!$wiki = wiki_get_wiki($params['wikiid'])) {
453 throw new moodle_exception('incorrectwikiid', 'wiki');
455 list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
456 $context = context_module::instance($cm->id);
457 self::validate_context($context);
459 // Determine groupid and userid to use.
460 list($groupid, $userid) = self::determine_group_and_user($cm, $wiki, $params['groupid'], $params['userid']);
462 // Get subwiki and validate it.
463 $subwiki = wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid);
465 if ($subwiki === false) {
466 throw new moodle_exception('cannotviewpage', 'wiki');
467 } else if ($subwiki->id != -1) {
470 $options = $params['options'];
471 if (!empty($options['sortby'])) {
472 if ($options['sortdirection'] != 'ASC' && $options['sortdirection'] != 'DESC') {
473 // Invalid sort direction. Use default.
474 $options['sortdirection'] = 'ASC';
476 $sort = $options['sortby'] . ' ' . $options['sortdirection'];
479 $pages = wiki_get_page_list($subwiki->id, $sort);
480 $caneditpages = wiki_user_can_edit($subwiki);
481 $firstpage = wiki_get_first_page($subwiki->id);
483 foreach ($pages as $page) {
486 'subwikiid' => $page->subwikiid,
487 'title' => external_format_string($page->title, $context->id),
488 'timecreated' => $page->timecreated,
489 'timemodified' => $page->timemodified,
490 'timerendered' => $page->timerendered,
491 'userid' => $page->userid,
492 'pageviews' => $page->pageviews,
493 'readonly' => $page->readonly,
494 'caneditpage' => $caneditpages,
495 'firstpage' => $page->id == $firstpage->id
498 // Refresh page cached content if needed.
499 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
500 if ($content = wiki_refresh_cachedcontent($page)) {
501 $page = $content['page'];
504 list($cachedcontent, $contentformat) = external_format_text(
505 $page->cachedcontent, FORMAT_HTML, $context->id, 'mod_wiki', 'attachments', $subwiki->id);
507 if ($options['includecontent']) {
508 // Return the page content.
509 $retpage['cachedcontent'] = $cachedcontent;
510 $retpage['contentformat'] = $contentformat;
512 // Return the size of the content.
513 if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
514 $retpage['contentsize'] = mb_strlen($cachedcontent, '8bit');
516 $retpage['contentsize'] = strlen($cachedcontent);
520 $returnedpages[] = $retpage;
525 $result['pages'] = $returnedpages;
526 $result['warnings'] = $warnings;
531 * Describes the get_subwiki_pages return value.
533 * @return external_single_structure
536 public static function get_subwiki_pages_returns() {
538 return new external_single_structure(
540 'pages' => new external_multiple_structure(
541 new external_single_structure(
543 'id' => new external_value(PARAM_INT, 'Page ID.'),
544 'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.'),
545 'title' => new external_value(PARAM_RAW, 'Page title.'),
546 'timecreated' => new external_value(PARAM_INT, 'Time of creation.'),
547 'timemodified' => new external_value(PARAM_INT, 'Time of last modification.'),
548 'timerendered' => new external_value(PARAM_INT, 'Time of last renderization.'),
549 'userid' => new external_value(PARAM_INT, 'ID of the user that last modified the page.'),
550 'pageviews' => new external_value(PARAM_INT, 'Number of times the page has been viewed.'),
551 'readonly' => new external_value(PARAM_INT, '1 if readonly, 0 otherwise.'),
552 'caneditpage' => new external_value(PARAM_BOOL, 'True if user can edit the page.'),
553 'firstpage' => new external_value(PARAM_BOOL, 'True if it\'s the first page.'),
554 'cachedcontent' => new external_value(PARAM_RAW, 'Page contents.', VALUE_OPTIONAL),
555 'contentformat' => new external_format_value('cachedcontent', VALUE_OPTIONAL),
556 'contentsize' => new external_value(PARAM_INT, 'Size of page contents in bytes (doesn\'t include'.
557 ' size of attached files).', VALUE_OPTIONAL),
561 'warnings' => new external_warnings(),
567 * Describes the parameters for get_page_contents.
569 * @return external_function_parameters
572 public static function get_page_contents_parameters() {
573 return new external_function_parameters (
575 'pageid' => new external_value(PARAM_INT, 'Page ID.')
581 * Get a page contents.
583 * @param int $pageid The page ID.
584 * @return array of warnings and page data.
587 public static function get_page_contents($pageid) {
589 $params = self::validate_parameters(self::get_page_contents_parameters(),
597 if (!$page = wiki_get_page($params['pageid'])) {
598 throw new moodle_exception('incorrectpageid', 'wiki');
601 // Get wiki instance.
602 if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
603 throw new moodle_exception('incorrectwikiid', 'wiki');
606 // Permission validation.
607 $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
608 $context = context_module::instance($cm->id);
609 self::validate_context($context);
611 // Check if user can view this wiki.
612 if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
613 throw new moodle_exception('incorrectsubwikiid', 'wiki');
615 if (!wiki_user_can_view($subwiki, $wiki)) {
616 throw new moodle_exception('cannotviewpage', 'wiki');
619 $returnedpage = array();
620 $returnedpage['id'] = $page->id;
621 $returnedpage['wikiid'] = $wiki->id;
622 $returnedpage['subwikiid'] = $page->subwikiid;
623 $returnedpage['groupid'] = $subwiki->groupid;
624 $returnedpage['userid'] = $subwiki->userid;
625 $returnedpage['title'] = $page->title;
627 // Refresh page cached content if needed.
628 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
629 if ($content = wiki_refresh_cachedcontent($page)) {
630 $page = $content['page'];
634 list($returnedpage['cachedcontent'], $returnedpage['contentformat']) = external_format_text(
635 $page->cachedcontent, FORMAT_HTML, $context->id, 'mod_wiki', 'attachments', $subwiki->id);
636 $returnedpage['caneditpage'] = wiki_user_can_edit($subwiki);
639 $result['page'] = $returnedpage;
640 $result['warnings'] = $warnings;
645 * Describes the get_page_contents return value.
647 * @return external_single_structure
650 public static function get_page_contents_returns() {
651 return new external_single_structure(
653 'page' => new external_single_structure(
655 'id' => new external_value(PARAM_INT, 'Page ID.'),
656 'wikiid' => new external_value(PARAM_INT, 'Page\'s wiki ID.'),
657 'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.'),
658 'groupid' => new external_value(PARAM_INT, 'Page\'s group ID.'),
659 'userid' => new external_value(PARAM_INT, 'Page\'s user ID.'),
660 'title' => new external_value(PARAM_RAW, 'Page title.'),
661 'cachedcontent' => new external_value(PARAM_RAW, 'Page contents.'),
662 'contentformat' => new external_format_value('cachedcontent', VALUE_OPTIONAL),
663 'caneditpage' => new external_value(PARAM_BOOL, 'True if user can edit the page.')
666 'warnings' => new external_warnings()
672 * Describes the parameters for get_subwiki_files.
674 * @return external_function_parameters
677 public static function get_subwiki_files_parameters() {
678 return new external_function_parameters (
680 'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.'),
681 'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID, -1 means current group. It will be ignored'
682 . ' if the wiki doesn\'t use groups.', VALUE_DEFAULT, -1),
683 'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID, 0 means current user. It will be ignored'
684 .' in collaborative wikis.', VALUE_DEFAULT, 0)
690 * Returns the list of files from a specific subwiki.
692 * @param int $wikiid The wiki instance ID.
693 * @param int $groupid The group ID. If not defined, use current group.
694 * @param int $userid The user ID. If not defined, use current user.
695 * @return array Containing a list of warnings and a list of files.
697 * @throws moodle_exception
699 public static function get_subwiki_files($wikiid, $groupid = -1, $userid = 0) {
701 $returnedfiles = array();
704 $params = self::validate_parameters(self::get_subwiki_files_parameters(),
707 'groupid' => $groupid,
712 // Get wiki instance.
713 if (!$wiki = wiki_get_wiki($params['wikiid'])) {
714 throw new moodle_exception('incorrectwikiid', 'wiki');
716 list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
717 $context = context_module::instance($cm->id);
718 self::validate_context($context);
720 // Determine groupid and userid to use.
721 list($groupid, $userid) = self::determine_group_and_user($cm, $wiki, $params['groupid'], $params['userid']);
723 // Get subwiki and validate it.
724 $subwiki = wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid);
726 // Get subwiki based on group and user.
727 if ($subwiki === false) {
728 throw new moodle_exception('cannotviewfiles', 'wiki');
729 } else if ($subwiki->id != -1) {
730 // The subwiki exists, let's get the files.
731 $fs = get_file_storage();
732 if ($files = $fs->get_area_files($context->id, 'mod_wiki', 'attachments', $subwiki->id, 'filename', false)) {
733 foreach ($files as $file) {
734 $filename = $file->get_filename();
735 $fileurl = moodle_url::make_webservice_pluginfile_url(
736 $context->id, 'mod_wiki', 'attachments', $subwiki->id, '/', $filename);
738 $returnedfiles[] = array(
739 'filename' => $filename,
740 'mimetype' => $file->get_mimetype(),
741 'fileurl' => $fileurl->out(false),
742 'filepath' => $file->get_filepath(),
743 'filesize' => $file->get_filesize(),
744 'timemodified' => $file->get_timemodified()
751 $result['files'] = $returnedfiles;
752 $result['warnings'] = $warnings;
757 * Describes the get_subwiki_pages return value.
759 * @return external_single_structure
762 public static function get_subwiki_files_returns() {
764 return new external_single_structure(
766 'files' => new external_multiple_structure(
767 new external_single_structure(
769 'filename' => new external_value(PARAM_FILE, 'File name.'),
770 'filepath' => new external_value(PARAM_PATH, 'File path.'),
771 'filesize' => new external_value(PARAM_INT, 'File size.'),
772 'fileurl' => new external_value(PARAM_URL, 'Downloadable file url.'),
773 'timemodified' => new external_value(PARAM_INT, 'Time modified.'),
774 'mimetype' => new external_value(PARAM_RAW, 'File mime type.'),
778 'warnings' => new external_warnings(),
784 * Utility function for determining the groupid and userid to use.
786 * @param stdClass $cm The course module.
787 * @param stdClass $wiki The wiki.
788 * @param int $groupid Group ID. If not defined, use current group.
789 * @param int $userid User ID. If not defined, use current user.
790 * @return array Array containing the courseid and userid.
793 protected static function determine_group_and_user($cm, $wiki, $groupid = -1, $userid = 0) {
796 $currentgroup = groups_get_activity_group($cm);
797 if ($currentgroup === false) {
798 // Activity doesn't use groups.
800 } else if ($groupid == -1) {
801 // Use current group.
802 $groupid = !empty($currentgroup) ? $currentgroup : 0;
806 if ($wiki->wikimode == 'collaborative') {
807 // Collaborative wikis don't use userid in subwikis.
809 } else if (empty($userid)) {
814 return array($groupid, $userid);
818 * Describes the parameters for get_page_for_editing.
820 * @return external_function_parameters
823 public static function get_page_for_editing_parameters() {
824 return new external_function_parameters (
826 'pageid' => new external_value(PARAM_INT, 'Page ID to edit.'),
827 'section' => new external_value(PARAM_RAW, 'Section page title.', VALUE_DEFAULT, null)
833 * Locks and retrieves info of page-section to be edited.
835 * @param int $pageid The page ID.
836 * @param string $section Section page title.
837 * @return array of warnings and page data.
840 public static function get_page_for_editing($pageid, $section = null) {
843 $params = self::validate_parameters(self::get_page_for_editing_parameters(),
846 'section' => $section
853 if (!$page = wiki_get_page($params['pageid'])) {
854 throw new moodle_exception('incorrectpageid', 'wiki');
857 // Get wiki instance.
858 if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
859 throw new moodle_exception('incorrectwikiid', 'wiki');
862 // Get subwiki instance.
863 if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
864 throw new moodle_exception('incorrectsubwikiid', 'wiki');
867 // Permission validation.
868 $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
869 $context = context_module::instance($cm->id);
870 self::validate_context($context);
872 if (!wiki_user_can_edit($subwiki)) {
873 throw new moodle_exception('cannoteditpage', 'wiki');
876 if (!wiki_set_lock($params['pageid'], $USER->id, $params['section'], true)) {
877 throw new moodle_exception('pageislocked', 'wiki');
880 $version = wiki_get_current_version($page->id);
881 if (empty($version)) {
882 throw new moodle_exception('versionerror', 'wiki');
885 if (!is_null($params['section'])) {
886 $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $params['section']);
888 $content = $version->content;
891 $pagesection = array();
892 $pagesection['content'] = $content;
893 $pagesection['contentformat'] = $version->contentformat;
894 $pagesection['version'] = $version->version;
897 $result['pagesection'] = $pagesection;
898 $result['warnings'] = $warnings;
904 * Describes the get_page_for_editing return value.
906 * @return external_single_structure
909 public static function get_page_for_editing_returns() {
910 return new external_single_structure(
912 'pagesection' => new external_single_structure(
914 'content' => new external_value(PARAM_RAW, 'The contents of the page-section to be edited.'),
915 'contentformat' => new external_value(PARAM_TEXT, 'Format of the original content of the page.'),
916 'version' => new external_value(PARAM_INT, 'Latest version of the page.'),
917 'warnings' => new external_warnings()
925 * Describes the parameters for new_page.
927 * @return external_function_parameters
930 public static function new_page_parameters() {
931 return new external_function_parameters (
933 'title' => new external_value(PARAM_TEXT, 'New page title.'),
934 'content' => new external_value(PARAM_RAW, 'Page contents.'),
935 'contentformat' => new external_value(PARAM_TEXT, 'Page contents format. If an invalid format is provided, default
936 wiki format is used.', VALUE_DEFAULT, null),
937 'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.', VALUE_DEFAULT, null),
938 'wikiid' => new external_value(PARAM_INT, 'Page\'s wiki ID. Used if subwiki does not exists.', VALUE_DEFAULT,
940 'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID. Used if subwiki does not exists.', VALUE_DEFAULT,
942 'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID. Used if subwiki does not exists.', VALUE_DEFAULT,
949 * Creates a new page.
951 * @param string $title New page title.
952 * @param string $content Page contents.
953 * @param int $contentformat Page contents format. If an invalid format is provided, default wiki format is used.
954 * @param int $subwikiid The Subwiki ID where to store the page.
955 * @param int $wikiid Page\'s wiki ID. Used if subwiki does not exists.
956 * @param int $userid Subwiki\'s user ID. Used if subwiki does not exists.
957 * @param int $groupid Subwiki\'s group ID. Used if subwiki does not exists.
958 * @return array of warnings and page data.
961 public static function new_page($title, $content, $contentformat = null, $subwikiid = null, $wikiid = null, $userid = null,
965 $params = self::validate_parameters(self::new_page_parameters(),
968 'content' => $content,
969 'contentformat' => $contentformat,
970 'subwikiid' => $subwikiid,
973 'groupid' => $groupid
979 // Get wiki and subwiki instances.
980 if (!empty($params['subwikiid'])) {
981 if (!$subwiki = wiki_get_subwiki($params['subwikiid'])) {
982 throw new moodle_exception('incorrectsubwikiid', 'wiki');
985 if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
986 throw new moodle_exception('incorrectwikiid', 'wiki');
989 // Permission validation.
990 $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
991 $context = context_module::instance($cm->id);
992 self::validate_context($context);
995 if (!$wiki = wiki_get_wiki($params['wikiid'])) {
996 throw new moodle_exception('incorrectwikiid', 'wiki');
999 // Permission validation.
1000 $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
1001 $context = context_module::instance($cm->id);
1002 self::validate_context($context);
1004 // Determine groupid and userid to use.
1005 list($groupid, $userid) = self::determine_group_and_user($cm, $wiki, $params['groupid'], $params['userid']);
1007 // Get subwiki and validate it.
1008 $subwiki = wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid);
1010 if ($subwiki === false) {
1011 // User cannot view page.
1012 throw new moodle_exception('cannoteditpage', 'wiki');
1013 } else if ($subwiki->id < 0) {
1014 // Subwiki needed to check edit permissions.
1015 if (!wiki_user_can_edit($subwiki)) {
1016 throw new moodle_exception('cannoteditpage', 'wiki');
1019 // Subwiki does not exists and it can be created.
1020 $swid = wiki_add_subwiki($wiki->id, $groupid, $userid);
1021 if (!$subwiki = wiki_get_subwiki($swid)) {
1022 throw new moodle_exception('incorrectsubwikiid', 'wiki');
1027 // Subwiki needed to check edit permissions.
1028 if (!wiki_user_can_edit($subwiki)) {
1029 throw new moodle_exception('cannoteditpage', 'wiki');
1032 if ($page = wiki_get_page_by_title($subwiki->id, $params['title'])) {
1033 throw new moodle_exception('pageexists', 'wiki');
1036 // Ignore invalid formats and use default instead.
1037 if (!$params['contentformat'] || $wiki->forceformat) {
1038 $params['contentformat'] = $wiki->defaultformat;
1040 $formats = wiki_get_formats();
1041 if (!in_array($params['contentformat'], $formats)) {
1042 $params['contentformat'] = $wiki->defaultformat;
1046 $newpageid = wiki_create_page($subwiki->id, $params['title'], $params['contentformat'], $USER->id);
1048 if (!$page = wiki_get_page($newpageid)) {
1049 throw new moodle_exception('incorrectpageid', 'wiki');
1053 $save = wiki_save_page($page, $params['content'], $USER->id);
1056 throw new moodle_exception('savingerror', 'wiki');
1060 $result['pageid'] = $page->id;
1061 $result['warnings'] = $warnings;
1066 * Describes the new_page return value.
1068 * @return external_single_structure
1071 public static function new_page_returns() {
1072 return new external_single_structure(
1074 'pageid' => new external_value(PARAM_INT, 'New page id.'),
1075 'warnings' => new external_warnings()
1081 * Describes the parameters for edit_page.
1083 * @return external_function_parameters
1086 public static function edit_page_parameters() {
1087 return new external_function_parameters (
1089 'pageid' => new external_value(PARAM_INT, 'Page ID.'),
1090 'content' => new external_value(PARAM_RAW, 'Page contents.'),
1091 'section' => new external_value(PARAM_RAW, 'Section page title.', VALUE_DEFAULT, null)
1097 * Edit a page contents.
1099 * @param int $pageid The page ID.
1100 * @param string $content Page contents.
1101 * @param int $section Section to be edited.
1102 * @return array of warnings and page data.
1105 public static function edit_page($pageid, $content, $section = null) {
1108 $params = self::validate_parameters(self::edit_page_parameters(),
1110 'pageid' => $pageid,
1111 'content' => $content,
1112 'section' => $section
1115 $warnings = array();
1118 if (!$page = wiki_get_page($params['pageid'])) {
1119 throw new moodle_exception('incorrectpageid', 'wiki');
1122 // Get wiki instance.
1123 if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
1124 throw new moodle_exception('incorrectwikiid', 'wiki');
1127 // Get subwiki instance.
1128 if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
1129 throw new moodle_exception('incorrectsubwikiid', 'wiki');
1132 // Permission validation.
1133 $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
1134 $context = context_module::instance($cm->id);
1135 self::validate_context($context);
1137 if (!wiki_user_can_edit($subwiki)) {
1138 throw new moodle_exception('cannoteditpage', 'wiki');
1141 if (wiki_is_page_section_locked($page->id, $USER->id, $params['section'])) {
1142 throw new moodle_exception('pageislocked', 'wiki');
1146 if (!is_null($params['section'])) {
1147 $version = wiki_get_current_version($page->id);
1148 $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $params['section'], false);
1150 throw new moodle_exception('invalidsection', 'wiki');
1153 $save = wiki_save_section($page, $params['section'], $params['content'], $USER->id);
1155 $save = wiki_save_page($page, $params['content'], $USER->id);
1158 wiki_delete_locks($page->id, $USER->id, $params['section']);
1161 throw new moodle_exception('savingerror', 'wiki');
1165 $result['pageid'] = $page->id;
1166 $result['warnings'] = $warnings;
1171 * Describes the edit_page return value.
1173 * @return external_single_structure
1176 public static function edit_page_returns() {
1177 return new external_single_structure(
1179 'pageid' => new external_value(PARAM_INT, 'Edited page id.'),
1180 'warnings' => new external_warnings()