c79f54482a29a5999d23e03789e4416c82d549c1
[moodle.git] / mod / wiki / classes / external.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
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.
8 //
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.
13 //
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/>.
17 /**
18  * Wiki module external API.
19  *
20  * @package    mod_wiki
21  * @category   external
22  * @copyright  2015 Dani Palou <dani@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @since      Moodle 3.1
25  */
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');
33 /**
34  * Wiki module external functions.
35  *
36  * @package    mod_wiki
37  * @category   external
38  * @copyright  2015 Dani Palou <dani@moodle.com>
39  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40  * @since      Moodle 3.1
41  */
42 class mod_wiki_external extends external_api {
44     /**
45      * Describes the parameters for get_wikis_by_courses.
46      *
47      * @return external_function_parameters
48      * @since Moodle 3.1
49      */
50     public static function get_wikis_by_courses_parameters() {
51         return new external_function_parameters (
52             array(
53                 'courseids' => new external_multiple_structure(
54                     new external_value(PARAM_INT, 'Course ID'), 'Array of course ids.', VALUE_DEFAULT, array()
55                 ),
56             )
57         );
58     }
60     /**
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.
63      *
64      * @param array $courseids The courses IDs.
65      * @return array Containing a list of warnings and a list of wikis.
66      * @since Moodle 3.1
67      */
68     public static function get_wikis_by_courses($courseids = array()) {
70         $returnedwikis = array();
71         $warnings = array();
73         $params = self::validate_parameters(self::get_wikis_by_courses_parameters(), array('courseids' => $courseids));
75         $mycourses = array();
76         if (empty($params['courseids'])) {
77             $mycourses = enrol_get_my_courses();
78             $params['courseids'] = array_keys($mycourses);
79         }
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);
94                 // Entry to return.
95                 $module = array();
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');
111                 }
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);
117                 }
119                 foreach ($viewablefields as $field) {
120                     $module[$field] = $wiki->{$field};
121                 }
123                 // Check if user can add new pages.
124                 $module['cancreatepages'] = wiki_can_create_pages($context);
126                 $returnedwikis[] = $module;
127             }
128         }
130         $result = array();
131         $result['wikis'] = $returnedwikis;
132         $result['warnings'] = $warnings;
133         return $result;
134     }
136     /**
137      * Describes the get_wikis_by_courses return value.
138      *
139      * @return external_single_structure
140      * @since Moodle 3.1
141      */
142     public static function get_wikis_by_courses_returns() {
144         return new external_single_structure(
145             array(
146                 'wikis' => new external_multiple_structure(
147                     new external_single_structure(
148                         array(
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).',
161                                                                             VALUE_OPTIONAL),
162                             'forceformat' => new external_value(PARAM_INT, '1 if format is forced, 0 otherwise.',
163                                                                             VALUE_OPTIONAL),
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.'),
171                         ), 'Wikis'
172                     )
173                 ),
174                 'warnings' => new external_warnings(),
175             )
176         );
177     }
179     /**
180      * Describes the parameters for view_wiki.
181      *
182      * @return external_function_parameters
183      * @since Moodle 3.1
184      */
185     public static function view_wiki_parameters() {
186         return new external_function_parameters (
187             array(
188                 'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.')
189             )
190         );
191     }
193     /**
194      * Trigger the course module viewed event and update the module completion status.
195      *
196      * @param int $wikiid The wiki instance ID.
197      * @return array of warnings and status result.
198      * @since Moodle 3.1
199      */
200     public static function view_wiki($wikiid) {
202         $params = self::validate_parameters(self::view_wiki_parameters(),
203                                             array(
204                                                 'wikiid' => $wikiid
205                                             ));
206         $warnings = array();
208         // Get wiki instance.
209         if (!$wiki = wiki_get_wiki($params['wikiid'])) {
210             throw new moodle_exception('incorrectwikiid', 'wiki');
211         }
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');
222         }
224         // Trigger course_module_viewed event and completion.
225         wiki_view($wiki, $course, $cm, $context);
227         $result = array();
228         $result['status'] = true;
229         $result['warnings'] = $warnings;
230         return $result;
231     }
233     /**
234      * Describes the view_wiki return value.
235      *
236      * @return external_single_structure
237      * @since Moodle 3.1
238      */
239     public static function view_wiki_returns() {
240         return new external_single_structure(
241             array(
242                 'status' => new external_value(PARAM_BOOL, 'Status: true if success.'),
243                 'warnings' => new external_warnings()
244             )
245         );
246     }
248     /**
249      * Describes the parameters for view_page.
250      *
251      * @return external_function_parameters
252      * @since Moodle 3.1
253      */
254     public static function view_page_parameters() {
255         return new external_function_parameters (
256             array(
257                 'pageid' => new external_value(PARAM_INT, 'Wiki page ID.'),
258             )
259         );
260     }
262     /**
263      * Trigger the page viewed event and update the module completion status.
264      *
265      * @param int $pageid The page ID.
266      * @return array of warnings and status result.
267      * @since Moodle 3.1
268      * @throws moodle_exception if page is not valid.
269      */
270     public static function view_page($pageid) {
272         $params = self::validate_parameters(self::view_page_parameters(),
273                                             array(
274                                                 'pageid' => $pageid
275                                             ));
276         $warnings = array();
278         // Get wiki page.
279         if (!$page = wiki_get_page($params['pageid'])) {
280             throw new moodle_exception('incorrectpageid', 'wiki');
281         }
283         // Get wiki instance.
284         if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
285             throw new moodle_exception('incorrectwikiid', 'wiki');
286         }
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');
296         }
297         if (!wiki_user_can_view($subwiki, $wiki)) {
298             throw new moodle_exception('cannotviewpage', 'wiki');
299         }
301         // Trigger page_viewed event and completion.
302         wiki_page_view($wiki, $page, $course, $cm, $context);
304         $result = array();
305         $result['status'] = true;
306         $result['warnings'] = $warnings;
307         return $result;
308     }
310     /**
311      * Describes the view_page return value.
312      *
313      * @return external_single_structure
314      * @since Moodle 3.1
315      */
316     public static function view_page_returns() {
317         return new external_single_structure(
318             array(
319                 'status' => new external_value(PARAM_BOOL, 'Status: true if success.'),
320                 'warnings' => new external_warnings()
321             )
322         );
323     }
325     /**
326      * Describes the parameters for get_subwikis.
327      *
328      * @return external_function_parameters
329      * @since Moodle 3.1
330      */
331     public static function get_subwikis_parameters() {
332         return new external_function_parameters (
333             array(
334                 'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.')
335             )
336         );
337     }
339     /**
340      * Returns the list of subwikis the user can see in a specific wiki.
341      *
342      * @param int $wikiid The wiki instance ID.
343      * @return array Containing a list of warnings and a list of subwikis.
344      * @since Moodle 3.1
345      */
346     public static function get_subwikis($wikiid) {
347         global $USER;
349         $warnings = array();
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');
356         }
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);
367         }
369         $result = array();
370         $result['subwikis'] = $returnedsubwikis;
371         $result['warnings'] = $warnings;
372         return $result;
373     }
375     /**
376      * Describes the get_subwikis return value.
377      *
378      * @return external_single_structure
379      * @since Moodle 3.1
380      */
381     public static function get_subwikis_returns() {
382         return new external_single_structure(
383             array(
384                 'subwikis' => new external_multiple_structure(
385                     new external_single_structure(
386                         array(
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.'),
392                         ), 'Subwikis'
393                     )
394                 ),
395                 'warnings' => new external_warnings(),
396             )
397         );
398     }
400     /**
401      * Describes the parameters for get_subwiki_pages.
402      *
403      * @return external_function_parameters
404      * @since Moodle 3.1
405      */
406     public static function get_subwiki_pages_parameters() {
407         return new external_function_parameters (
408             array(
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(
415                             array(
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()),
423             )
424         );
425     }
427     /**
428      * Returns the list of pages from a specific subwiki.
429      *
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.
435      * @since Moodle 3.1
436      */
437     public static function get_subwiki_pages($wikiid, $groupid = -1, $userid = 0, $options = array()) {
439         $returnedpages = array();
440         $warnings = array();
442         $params = self::validate_parameters(self::get_subwiki_pages_parameters(),
443                                             array(
444                                                 'wikiid' => $wikiid,
445                                                 'groupid' => $groupid,
446                                                 'userid' => $userid,
447                                                 'options' => $options
448                                                 )
449             );
451         // Get wiki instance.
452         if (!$wiki = wiki_get_wiki($params['wikiid'])) {
453             throw new moodle_exception('incorrectwikiid', 'wiki');
454         }
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) {
469             // Set sort param.
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';
475                 }
476                 $sort = $options['sortby'] . ' ' . $options['sortdirection'];
477             }
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) {
484                 $retpage = array(
485                         'id' => $page->id,
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
496                     );
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'];
502                     }
503                 }
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;
511                 } else {
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');
515                     } else {
516                         $retpage['contentsize'] = strlen($cachedcontent);
517                     }
518                 }
520                 $returnedpages[] = $retpage;
521             }
522         }
524         $result = array();
525         $result['pages'] = $returnedpages;
526         $result['warnings'] = $warnings;
527         return $result;
528     }
530     /**
531      * Describes the get_subwiki_pages return value.
532      *
533      * @return external_single_structure
534      * @since Moodle 3.1
535      */
536     public static function get_subwiki_pages_returns() {
538         return new external_single_structure(
539             array(
540                 'pages' => new external_multiple_structure(
541                     new external_single_structure(
542                         array(
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),
558                         ), 'Pages'
559                     )
560                 ),
561                 'warnings' => new external_warnings(),
562             )
563         );
564     }
566     /**
567      * Describes the parameters for get_page_contents.
568      *
569      * @return external_function_parameters
570      * @since Moodle 3.1
571      */
572     public static function get_page_contents_parameters() {
573         return new external_function_parameters (
574             array(
575                 'pageid' => new external_value(PARAM_INT, 'Page ID.')
576             )
577         );
578     }
580     /**
581      * Get a page contents.
582      *
583      * @param int $pageid The page ID.
584      * @return array of warnings and page data.
585      * @since Moodle 3.1
586      */
587     public static function get_page_contents($pageid) {
589         $params = self::validate_parameters(self::get_page_contents_parameters(),
590                                             array(
591                                                 'pageid' => $pageid
592                                             )
593             );
594         $warnings = array();
596         // Get wiki page.
597         if (!$page = wiki_get_page($params['pageid'])) {
598             throw new moodle_exception('incorrectpageid', 'wiki');
599         }
601         // Get wiki instance.
602         if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
603             throw new moodle_exception('incorrectwikiid', 'wiki');
604         }
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');
614         }
615         if (!wiki_user_can_view($subwiki, $wiki)) {
616             throw new moodle_exception('cannotviewpage', 'wiki');
617         }
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'];
631             }
632         }
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);
638         $result = array();
639         $result['page'] = $returnedpage;
640         $result['warnings'] = $warnings;
641         return $result;
642     }
644     /**
645      * Describes the get_page_contents return value.
646      *
647      * @return external_single_structure
648      * @since Moodle 3.1
649      */
650     public static function get_page_contents_returns() {
651         return new external_single_structure(
652             array(
653                 'page' => new external_single_structure(
654                     array(
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.')
664                     ), 'Page'
665                 ),
666                 'warnings' => new external_warnings()
667             )
668         );
669     }
671     /**
672      * Describes the parameters for get_subwiki_files.
673      *
674      * @return external_function_parameters
675      * @since Moodle 3.1
676      */
677     public static function get_subwiki_files_parameters() {
678         return new external_function_parameters (
679             array(
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)
685             )
686         );
687     }
689     /**
690      * Returns the list of files from a specific subwiki.
691      *
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.
696      * @since Moodle 3.1
697      * @throws moodle_exception
698      */
699     public static function get_subwiki_files($wikiid, $groupid = -1, $userid = 0) {
701         $returnedfiles = array();
702         $warnings = array();
704         $params = self::validate_parameters(self::get_subwiki_files_parameters(),
705                                             array(
706                                                 'wikiid' => $wikiid,
707                                                 'groupid' => $groupid,
708                                                 'userid' => $userid
709                                                 )
710             );
712         // Get wiki instance.
713         if (!$wiki = wiki_get_wiki($params['wikiid'])) {
714             throw new moodle_exception('incorrectwikiid', 'wiki');
715         }
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()
745                     );
746                 }
747             }
748         }
750         $result = array();
751         $result['files'] = $returnedfiles;
752         $result['warnings'] = $warnings;
753         return $result;
754     }
756     /**
757      * Describes the get_subwiki_pages return value.
758      *
759      * @return external_single_structure
760      * @since Moodle 3.1
761      */
762     public static function get_subwiki_files_returns() {
764         return new external_single_structure(
765             array(
766                 'files' => new external_multiple_structure(
767                     new external_single_structure(
768                         array(
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.'),
775                         ), 'Files'
776                     )
777                 ),
778                 'warnings' => new external_warnings(),
779             )
780         );
781     }
783     /**
784      * Utility function for determining the groupid and userid to use.
785      *
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.
791      * @since  Moodle 3.1
792      */
793     protected static function determine_group_and_user($cm, $wiki, $groupid = -1, $userid = 0) {
794         global $USER;
796         $currentgroup = groups_get_activity_group($cm);
797         if ($currentgroup === false) {
798             // Activity doesn't use groups.
799             $groupid = 0;
800         } else if ($groupid == -1) {
801             // Use current group.
802             $groupid = !empty($currentgroup) ? $currentgroup : 0;
803         }
805         // Determine user.
806         if ($wiki->wikimode == 'collaborative') {
807             // Collaborative wikis don't use userid in subwikis.
808             $userid = 0;
809         } else if (empty($userid)) {
810             // Use current user.
811             $userid = $USER->id;
812         }
814         return array($groupid, $userid);
815     }
817     /**
818      * Describes the parameters for get_page_for_editing.
819      *
820      * @return external_function_parameters
821      * @since Moodle 3.1
822      */
823     public static function get_page_for_editing_parameters() {
824         return new external_function_parameters (
825             array(
826                 'pageid' => new external_value(PARAM_INT, 'Page ID to edit.'),
827                 'section' => new external_value(PARAM_TEXT, 'Section page title.', VALUE_DEFAULT, null)
828             )
829         );
830     }
832     /**
833      * Locks and retrieves info of page-section to be edited.
834      *
835      * @param int $pageid The page ID.
836      * @param string $section Section page title.
837      * @return array of warnings and page data.
838      * @since Moodle 3.1
839      */
840     public static function get_page_for_editing($pageid, $section = null) {
841         global $USER;
843         $params = self::validate_parameters(self::get_page_for_editing_parameters(),
844                                             array(
845                                                 'pageid' => $pageid,
846                                                 'section' => $section
847                                             )
848             );
850         $warnings = array();
852         // Get wiki page.
853         if (!$page = wiki_get_page($params['pageid'])) {
854             throw new moodle_exception('incorrectpageid', 'wiki');
855         }
857         // Get wiki instance.
858         if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
859             throw new moodle_exception('incorrectwikiid', 'wiki');
860         }
862         // Get subwiki instance.
863         if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
864             throw new moodle_exception('incorrectsubwikiid', 'wiki');
865         }
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');
874         }
876         if (!wiki_set_lock($params['pageid'], $USER->id, $params['section'], true)) {
877             throw new moodle_exception('pageislocked', 'wiki');
878         }
880         $version = wiki_get_current_version($page->id);
881         if (empty($version)) {
882             throw new moodle_exception('versionerror', 'wiki');
883         }
885         if (!is_null($params['section'])) {
886             $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $params['section']);
887         } else {
888             $content = $version->content;
889         }
891         $pagesection = array();
892         $pagesection['content'] = $content;
893         $pagesection['contentformat'] = $version->contentformat;
894         $pagesection['version'] = $version->version;
896         $result = array();
897         $result['pagesection'] = $pagesection;
898         $result['warnings'] = $warnings;
899         return $result;
901     }
903     /**
904      * Describes the get_page_for_editing return value.
905      *
906      * @return external_single_structure
907      * @since Moodle 3.1
908      */
909     public static function get_page_for_editing_returns() {
910         return new external_single_structure(
911             array(
912                 'pagesection' => new external_single_structure(
913                     array(
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()
918                     )
919                 )
920             )
921         );
922     }
924     /**
925      * Describes the parameters for new_page.
926      *
927      * @return external_function_parameters
928      * @since Moodle 3.1
929      */
930     public static function new_page_parameters() {
931         return new external_function_parameters (
932             array(
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,
939                     null),
940                 'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID. Used if subwiki does not exists.', VALUE_DEFAULT,
941                     null),
942                 'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID. Used if subwiki does not exists.', VALUE_DEFAULT,
943                     null)
944             )
945         );
946     }
948     /**
949      * Creates a new page.
950      *
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.
959      * @since Moodle 3.1
960      */
961     public static function new_page($title, $content, $contentformat = null, $subwikiid = null, $wikiid = null, $userid = null,
962         $groupid = null) {
963         global $USER;
965         $params = self::validate_parameters(self::new_page_parameters(),
966                                             array(
967                                                 'title' => $title,
968                                                 'content' => $content,
969                                                 'contentformat' => $contentformat,
970                                                 'subwikiid' => $subwikiid,
971                                                 'wikiid' => $wikiid,
972                                                 'userid' => $userid,
973                                                 'groupid' => $groupid
974                                             )
975             );
977         $warnings = array();
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');
983             }
985             if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
986                 throw new moodle_exception('incorrectwikiid', 'wiki');
987             }
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);
994         } else {
995             if (!$wiki = wiki_get_wiki($params['wikiid'])) {
996                 throw new moodle_exception('incorrectwikiid', 'wiki');
997             }
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');
1017                 }
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');
1023                 }
1024             }
1025         }
1027         // Subwiki needed to check edit permissions.
1028         if (!wiki_user_can_edit($subwiki)) {
1029             throw new moodle_exception('cannoteditpage', 'wiki');
1030         }
1032         if ($page = wiki_get_page_by_title($subwiki->id, $params['title'])) {
1033             throw new moodle_exception('pageexists', 'wiki');
1034         }
1036         // Ignore invalid formats and use default instead.
1037         if (!$params['contentformat'] || $wiki->forceformat) {
1038             $params['contentformat'] = $wiki->defaultformat;
1039         } else {
1040             $formats = wiki_get_formats();
1041             if (!in_array($params['contentformat'], $formats)) {
1042                 $params['contentformat'] = $wiki->defaultformat;
1043             }
1044         }
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');
1050         }
1052         // Save content.
1053         $save = wiki_save_page($page, $params['content'], $USER->id);
1055         if (!$save) {
1056             throw new moodle_exception('savingerror', 'wiki');
1057         }
1059         $result = array();
1060         $result['pageid'] = $page->id;
1061         $result['warnings'] = $warnings;
1062         return $result;
1063     }
1065     /**
1066      * Describes the new_page return value.
1067      *
1068      * @return external_single_structure
1069      * @since Moodle 3.1
1070      */
1071     public static function new_page_returns() {
1072         return new external_single_structure(
1073             array(
1074                 'pageid' => new external_value(PARAM_INT, 'New page id.'),
1075                 'warnings' => new external_warnings()
1076             )
1077         );
1078     }
1080     /**
1081      * Describes the parameters for edit_page.
1082      *
1083      * @return external_function_parameters
1084      * @since Moodle 3.1
1085      */
1086     public static function edit_page_parameters() {
1087         return new external_function_parameters (
1088             array(
1089                 'pageid' => new external_value(PARAM_INT, 'Page ID.'),
1090                 'content' => new external_value(PARAM_RAW, 'Page contents.'),
1091                 'section' => new external_value(PARAM_TEXT, 'Section page title.', VALUE_DEFAULT, null)
1092             )
1093         );
1094     }
1096     /**
1097      * Edit a page contents.
1098      *
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.
1103      * @since Moodle 3.1
1104      */
1105     public static function edit_page($pageid, $content, $section = null) {
1106         global $USER;
1108         $params = self::validate_parameters(self::edit_page_parameters(),
1109                                             array(
1110                                                 'pageid' => $pageid,
1111                                                 'content' => $content,
1112                                                 'section' => $section
1113                                             )
1114             );
1115         $warnings = array();
1117         // Get wiki page.
1118         if (!$page = wiki_get_page($params['pageid'])) {
1119             throw new moodle_exception('incorrectpageid', 'wiki');
1120         }
1122         // Get wiki instance.
1123         if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
1124             throw new moodle_exception('incorrectwikiid', 'wiki');
1125         }
1127         // Get subwiki instance.
1128         if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
1129             throw new moodle_exception('incorrectsubwikiid', 'wiki');
1130         }
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');
1139         }
1141         if (wiki_is_page_section_locked($page->id, $USER->id, $params['section'])) {
1142             throw new moodle_exception('pageislocked', 'wiki');
1143         }
1145         // Save content.
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);
1149             if (!$content) {
1150                 throw new moodle_exception('invalidsection', 'wiki');
1151             }
1153             $save = wiki_save_section($page, $params['section'], $params['content'], $USER->id);
1154         } else {
1155             $save = wiki_save_page($page, $params['content'], $USER->id);
1156         }
1158         wiki_delete_locks($page->id, $USER->id, $params['section']);
1160         if (!$save) {
1161             throw new moodle_exception('savingerror', 'wiki');
1162         }
1164         $result = array();
1165         $result['pageid'] = $page->id;
1166         $result['warnings'] = $warnings;
1167         return $result;
1168     }
1170     /**
1171      * Describes the edit_page return value.
1172      *
1173      * @return external_single_structure
1174      * @since Moodle 3.1
1175      */
1176     public static function edit_page_returns() {
1177         return new external_single_structure(
1178             array(
1179                 'pageid' => new external_value(PARAM_INT, 'Edited page id.'),
1180                 'warnings' => new external_warnings()
1181             )
1182         );
1183     }