Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
  • Differences Between: [Versions 310 and 311] [Versions 37 and 311] [Versions 38 and 311] [Versions 39 and 311]

       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/>.
      16  
      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   */
      26  
      27  defined('MOODLE_INTERNAL') || die;
      28  
      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');
      32  
      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 {
      43  
      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      }
      59  
      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()) {
      69  
      70          $returnedwikis = array();
      71          $warnings = array();
      72  
      73          $params = self::validate_parameters(self::get_wikis_by_courses_parameters(), array('courseids' => $courseids));
      74  
      75          $mycourses = array();
      76          if (empty($params['courseids'])) {
      77              $mycourses = enrol_get_my_courses();
      78              $params['courseids'] = array_keys($mycourses);
      79          }
      80  
      81          // Ensure there are courseids to loop through.
      82          if (!empty($params['courseids'])) {
      83  
      84              list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses);
      85  
      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);
      89  
      90              foreach ($wikis as $wiki) {
      91  
      92                  $context = context_module::instance($wiki->coursemodule);
      93  
      94                  // Entry to return.
      95                  $module = array();
      96  
      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);
     102  
     103                  $viewablefields = [];
     104                  if (has_capability('mod/wiki:viewpage', $context)) {
     105                      $options = array('noclean' => true);
     106                      list($module['intro'], $module['introformat']) =
     107                          external_format_text($wiki->intro, $wiki->introformat, $context->id, 'mod_wiki', 'intro', null, $options);
     108                      $module['introfiles'] = external_util::get_area_files($context->id, 'mod_wiki', 'intro', false, false);
     109  
     110                      $viewablefields = array('firstpagetitle', 'wikimode', 'defaultformat', 'forceformat', 'editbegin', 'editend',
     111                                              'section', 'visible', 'groupmode', 'groupingid');
     112                  }
     113  
     114                  // Check additional permissions for returning optional private settings.
     115                  if (has_capability('moodle/course:manageactivities', $context)) {
     116                      $additionalfields = array('timecreated', 'timemodified');
     117                      $viewablefields = array_merge($viewablefields, $additionalfields);
     118                  }
     119  
     120                  foreach ($viewablefields as $field) {
     121                      $module[$field] = $wiki->{$field};
     122                  }
     123  
     124                  // Check if user can add new pages.
     125                  $module['cancreatepages'] = wiki_can_create_pages($context);
     126  
     127                  $returnedwikis[] = $module;
     128              }
     129          }
     130  
     131          $result = array();
     132          $result['wikis'] = $returnedwikis;
     133          $result['warnings'] = $warnings;
     134          return $result;
     135      }
     136  
     137      /**
     138       * Describes the get_wikis_by_courses return value.
     139       *
     140       * @return external_single_structure
     141       * @since Moodle 3.1
     142       */
     143      public static function get_wikis_by_courses_returns() {
     144  
     145          return new external_single_structure(
     146              array(
     147                  'wikis' => new external_multiple_structure(
     148                      new external_single_structure(
     149                          array(
     150                              'id' => new external_value(PARAM_INT, 'Wiki ID.'),
     151                              'coursemodule' => new external_value(PARAM_INT, 'Course module ID.'),
     152                              'course' => new external_value(PARAM_INT, 'Course ID.'),
     153                              'name' => new external_value(PARAM_RAW, 'Wiki name.'),
     154                              'intro' => new external_value(PARAM_RAW, 'Wiki intro.', VALUE_OPTIONAL),
     155                              'introformat' => new external_format_value('Wiki intro format.', VALUE_OPTIONAL),
     156                              'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
     157                              'timecreated' => new external_value(PARAM_INT, 'Time of creation.', VALUE_OPTIONAL),
     158                              'timemodified' => new external_value(PARAM_INT, 'Time of last modification.', VALUE_OPTIONAL),
     159                              'firstpagetitle' => new external_value(PARAM_RAW, 'First page title.', VALUE_OPTIONAL),
     160                              'wikimode' => new external_value(PARAM_TEXT, 'Wiki mode (individual, collaborative).', VALUE_OPTIONAL),
     161                              'defaultformat' => new external_value(PARAM_TEXT, 'Wiki\'s default format (html, creole, nwiki).',
     162                                                                              VALUE_OPTIONAL),
     163                              'forceformat' => new external_value(PARAM_INT, '1 if format is forced, 0 otherwise.',
     164                                                                              VALUE_OPTIONAL),
     165                              'editbegin' => new external_value(PARAM_INT, 'Edit begin.', VALUE_OPTIONAL),
     166                              'editend' => new external_value(PARAM_INT, 'Edit end.', VALUE_OPTIONAL),
     167                              'section' => new external_value(PARAM_INT, 'Course section ID.', VALUE_OPTIONAL),
     168                              'visible' => new external_value(PARAM_INT, '1 if visible, 0 otherwise.', VALUE_OPTIONAL),
     169                              'groupmode' => new external_value(PARAM_INT, 'Group mode.', VALUE_OPTIONAL),
     170                              'groupingid' => new external_value(PARAM_INT, 'Group ID.', VALUE_OPTIONAL),
     171                              'cancreatepages' => new external_value(PARAM_BOOL, 'True if user can create pages.'),
     172                          ), 'Wikis'
     173                      )
     174                  ),
     175                  'warnings' => new external_warnings(),
     176              )
     177          );
     178      }
     179  
     180      /**
     181       * Describes the parameters for view_wiki.
     182       *
     183       * @return external_function_parameters
     184       * @since Moodle 3.1
     185       */
     186      public static function view_wiki_parameters() {
     187          return new external_function_parameters (
     188              array(
     189                  'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.')
     190              )
     191          );
     192      }
     193  
     194      /**
     195       * Trigger the course module viewed event and update the module completion status.
     196       *
     197       * @param int $wikiid The wiki instance ID.
     198       * @return array of warnings and status result.
     199       * @since Moodle 3.1
     200       */
     201      public static function view_wiki($wikiid) {
     202  
     203          $params = self::validate_parameters(self::view_wiki_parameters(),
     204                                              array(
     205                                                  'wikiid' => $wikiid
     206                                              ));
     207          $warnings = array();
     208  
     209          // Get wiki instance.
     210          if (!$wiki = wiki_get_wiki($params['wikiid'])) {
     211              throw new moodle_exception('incorrectwikiid', 'wiki');
     212          }
     213  
     214          // Permission validation.
     215          list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
     216          $context = context_module::instance($cm->id);
     217          self::validate_context($context);
     218  
     219          // Check if user can view this wiki.
     220          // We don't use wiki_user_can_view because it requires to have a valid subwiki for the user.
     221          if (!has_capability('mod/wiki:viewpage', $context)) {
     222              throw new moodle_exception('cannotviewpage', 'wiki');
     223          }
     224  
     225          // Trigger course_module_viewed event and completion.
     226          wiki_view($wiki, $course, $cm, $context);
     227  
     228          $result = array();
     229          $result['status'] = true;
     230          $result['warnings'] = $warnings;
     231          return $result;
     232      }
     233  
     234      /**
     235       * Describes the view_wiki return value.
     236       *
     237       * @return external_single_structure
     238       * @since Moodle 3.1
     239       */
     240      public static function view_wiki_returns() {
     241          return new external_single_structure(
     242              array(
     243                  'status' => new external_value(PARAM_BOOL, 'Status: true if success.'),
     244                  'warnings' => new external_warnings()
     245              )
     246          );
     247      }
     248  
     249      /**
     250       * Describes the parameters for view_page.
     251       *
     252       * @return external_function_parameters
     253       * @since Moodle 3.1
     254       */
     255      public static function view_page_parameters() {
     256          return new external_function_parameters (
     257              array(
     258                  'pageid' => new external_value(PARAM_INT, 'Wiki page ID.'),
     259              )
     260          );
     261      }
     262  
     263      /**
     264       * Trigger the page viewed event and update the module completion status.
     265       *
     266       * @param int $pageid The page ID.
     267       * @return array of warnings and status result.
     268       * @since Moodle 3.1
     269       * @throws moodle_exception if page is not valid.
     270       */
     271      public static function view_page($pageid) {
     272  
     273          $params = self::validate_parameters(self::view_page_parameters(),
     274                                              array(
     275                                                  'pageid' => $pageid
     276                                              ));
     277          $warnings = array();
     278  
     279          // Get wiki page.
     280          if (!$page = wiki_get_page($params['pageid'])) {
     281              throw new moodle_exception('incorrectpageid', 'wiki');
     282          }
     283  
     284          // Get wiki instance.
     285          if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
     286              throw new moodle_exception('incorrectwikiid', 'wiki');
     287          }
     288  
     289          // Permission validation.
     290          list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
     291          $context = context_module::instance($cm->id);
     292          self::validate_context($context);
     293  
     294          // Check if user can view this wiki.
     295          if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
     296              throw new moodle_exception('incorrectsubwikiid', 'wiki');
     297          }
     298          if (!wiki_user_can_view($subwiki, $wiki)) {
     299              throw new moodle_exception('cannotviewpage', 'wiki');
     300          }
     301  
     302          // Trigger page_viewed event and completion.
     303          wiki_page_view($wiki, $page, $course, $cm, $context);
     304  
     305          $result = array();
     306          $result['status'] = true;
     307          $result['warnings'] = $warnings;
     308          return $result;
     309      }
     310  
     311      /**
     312       * Describes the view_page return value.
     313       *
     314       * @return external_single_structure
     315       * @since Moodle 3.1
     316       */
     317      public static function view_page_returns() {
     318          return new external_single_structure(
     319              array(
     320                  'status' => new external_value(PARAM_BOOL, 'Status: true if success.'),
     321                  'warnings' => new external_warnings()
     322              )
     323          );
     324      }
     325  
     326      /**
     327       * Describes the parameters for get_subwikis.
     328       *
     329       * @return external_function_parameters
     330       * @since Moodle 3.1
     331       */
     332      public static function get_subwikis_parameters() {
     333          return new external_function_parameters (
     334              array(
     335                  'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.')
     336              )
     337          );
     338      }
     339  
     340      /**
     341       * Returns the list of subwikis the user can see in a specific wiki.
     342       *
     343       * @param int $wikiid The wiki instance ID.
     344       * @return array Containing a list of warnings and a list of subwikis.
     345       * @since Moodle 3.1
     346       */
     347      public static function get_subwikis($wikiid) {
     348          global $USER;
     349  
     350          $warnings = array();
     351  
     352          $params = self::validate_parameters(self::get_subwikis_parameters(), array('wikiid' => $wikiid));
     353  
     354          // Get wiki instance.
     355          if (!$wiki = wiki_get_wiki($params['wikiid'])) {
     356              throw new moodle_exception('incorrectwikiid', 'wiki');
     357          }
     358  
     359          // Validate context and capabilities.
     360          list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
     361          $context = context_module::instance($cm->id);
     362          self::validate_context($context);
     363          require_capability('mod/wiki:viewpage', $context);
     364  
     365          $returnedsubwikis = wiki_get_visible_subwikis($wiki, $cm, $context);
     366          foreach ($returnedsubwikis as $subwiki) {
     367              $subwiki->canedit = wiki_user_can_edit($subwiki);
     368          }
     369  
     370          $result = array();
     371          $result['subwikis'] = $returnedsubwikis;
     372          $result['warnings'] = $warnings;
     373          return $result;
     374      }
     375  
     376      /**
     377       * Describes the get_subwikis return value.
     378       *
     379       * @return external_single_structure
     380       * @since Moodle 3.1
     381       */
     382      public static function get_subwikis_returns() {
     383          return new external_single_structure(
     384              array(
     385                  'subwikis' => new external_multiple_structure(
     386                      new external_single_structure(
     387                          array(
     388                              'id' => new external_value(PARAM_INT, 'Subwiki ID.'),
     389                              'wikiid' => new external_value(PARAM_INT, 'Wiki ID.'),
     390                              'groupid' => new external_value(PARAM_RAW, 'Group ID.'),
     391                              'userid' => new external_value(PARAM_INT, 'User ID.'),
     392                              'canedit' => new external_value(PARAM_BOOL, 'True if user can edit the subwiki.'),
     393                          ), 'Subwikis'
     394                      )
     395                  ),
     396                  'warnings' => new external_warnings(),
     397              )
     398          );
     399      }
     400  
     401      /**
     402       * Describes the parameters for get_subwiki_pages.
     403       *
     404       * @return external_function_parameters
     405       * @since Moodle 3.1
     406       */
     407      public static function get_subwiki_pages_parameters() {
     408          return new external_function_parameters (
     409              array(
     410                  'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.'),
     411                  'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID, -1 means current group. It will be ignored'
     412                                          . ' if the wiki doesn\'t use groups.', VALUE_DEFAULT, -1),
     413                  'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID, 0 means current user. It will be ignored'
     414                                          .' in collaborative wikis.', VALUE_DEFAULT, 0),
     415                  'options' => new external_single_structure(
     416                              array(
     417                                      'sortby' => new external_value(PARAM_ALPHA,
     418                                              'Field to sort by (id, title, ...).', VALUE_DEFAULT, 'title'),
     419                                      'sortdirection' => new external_value(PARAM_ALPHA,
     420                                              'Sort direction: ASC or DESC.', VALUE_DEFAULT, 'ASC'),
     421                                      'includecontent' => new external_value(PARAM_INT,
     422                                              'Include each page contents or just the contents size.', VALUE_DEFAULT, 1),
     423                              ), 'Options', VALUE_DEFAULT, array()),
     424              )
     425          );
     426      }
     427  
     428      /**
     429       * Returns the list of pages from a specific subwiki.
     430       *
     431       * @param int $wikiid The wiki instance ID.
     432       * @param int $groupid The group ID. If not defined, use current group.
     433       * @param int $userid The user ID. If not defined, use current user.
     434       * @param array $options Several options like sort by, sort direction, ...
     435       * @return array Containing a list of warnings and a list of pages.
     436       * @since Moodle 3.1
     437       */
     438      public static function get_subwiki_pages($wikiid, $groupid = -1, $userid = 0, $options = array()) {
     439  
     440          $returnedpages = array();
     441          $warnings = array();
     442  
     443          $params = self::validate_parameters(self::get_subwiki_pages_parameters(),
     444                                              array(
     445                                                  'wikiid' => $wikiid,
     446                                                  'groupid' => $groupid,
     447                                                  'userid' => $userid,
     448                                                  'options' => $options
     449                                                  )
     450              );
     451  
     452          // Get wiki instance.
     453          if (!$wiki = wiki_get_wiki($params['wikiid'])) {
     454              throw new moodle_exception('incorrectwikiid', 'wiki');
     455          }
     456          list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
     457          $context = context_module::instance($cm->id);
     458          self::validate_context($context);
     459  
     460          // Determine groupid and userid to use.
     461          list($groupid, $userid) = self::determine_group_and_user($cm, $wiki, $params['groupid'], $params['userid']);
     462  
     463          // Get subwiki and validate it.
     464          $subwiki = wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid);
     465  
     466          if ($subwiki === false) {
     467              throw new moodle_exception('cannotviewpage', 'wiki');
     468          } else if ($subwiki->id != -1) {
     469  
     470              // Set sort param.
     471              $options = $params['options'];
     472              if (!empty($options['sortby'])) {
     473                  if ($options['sortdirection'] != 'ASC' && $options['sortdirection'] != 'DESC') {
     474                      // Invalid sort direction. Use default.
     475                      $options['sortdirection'] = 'ASC';
     476                  }
     477                  $sort = $options['sortby'] . ' ' . $options['sortdirection'];
     478              }
     479  
     480              $pages = wiki_get_page_list($subwiki->id, $sort);
     481              $caneditpages = wiki_user_can_edit($subwiki);
     482              $firstpage = wiki_get_first_page($subwiki->id);
     483  
     484              foreach ($pages as $page) {
     485                  $retpage = array(
     486                          'id' => $page->id,
     487                          'subwikiid' => $page->subwikiid,
     488                          'title' => external_format_string($page->title, $context->id),
     489                          'timecreated' => $page->timecreated,
     490                          'timemodified' => $page->timemodified,
     491                          'timerendered' => $page->timerendered,
     492                          'userid' => $page->userid,
     493                          'pageviews' => $page->pageviews,
     494                          'readonly' => $page->readonly,
     495                          'caneditpage' => $caneditpages,
     496                          'firstpage' => $page->id == $firstpage->id,
     497                          'tags' => \core_tag\external\util::get_item_tags('mod_wiki', 'wiki_pages', $page->id),
     498                      );
     499  
     500                  // Refresh page cached content if needed.
     501                  if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
     502                      if ($content = wiki_refresh_cachedcontent($page)) {
     503                          $page = $content['page'];
     504                      }
     505                  }
     506                  list($cachedcontent, $contentformat) = external_format_text(
     507                              $page->cachedcontent, FORMAT_HTML, $context->id, 'mod_wiki', 'attachments', $subwiki->id);
     508  
     509                  if ($options['includecontent']) {
     510                      // Return the page content.
     511                      $retpage['cachedcontent'] = $cachedcontent;
     512                      $retpage['contentformat'] = $contentformat;
     513                  } else {
     514                      // Return the size of the content.
     515                      $retpage['contentsize'] = strlen($cachedcontent);
     516                      // TODO: Remove this block of code once PHP 8.0 is the min version supported.
     517                      // For PHP < 8.0, if strlen() was overloaded, calculate
     518                      // the bytes using mb_strlen(..., '8bit').
     519                      if (PHP_VERSION_ID < 80000) {
     520                          if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
     521                              $retpage['contentsize'] = mb_strlen($cachedcontent, '8bit');
     522                          }
     523                      }
     524                  }
     525  
     526                  $returnedpages[] = $retpage;
     527              }
     528          }
     529  
     530          $result = array();
     531          $result['pages'] = $returnedpages;
     532          $result['warnings'] = $warnings;
     533          return $result;
     534      }
     535  
     536      /**
     537       * Describes the get_subwiki_pages return value.
     538       *
     539       * @return external_single_structure
     540       * @since Moodle 3.1
     541       */
     542      public static function get_subwiki_pages_returns() {
     543  
     544          return new external_single_structure(
     545              array(
     546                  'pages' => new external_multiple_structure(
     547                      new external_single_structure(
     548                          array(
     549                              'id' => new external_value(PARAM_INT, 'Page ID.'),
     550                              'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.'),
     551                              'title' => new external_value(PARAM_RAW, 'Page title.'),
     552                              'timecreated' => new external_value(PARAM_INT, 'Time of creation.'),
     553                              'timemodified' => new external_value(PARAM_INT, 'Time of last modification.'),
     554                              'timerendered' => new external_value(PARAM_INT, 'Time of last renderization.'),
     555                              'userid' => new external_value(PARAM_INT, 'ID of the user that last modified the page.'),
     556                              'pageviews' => new external_value(PARAM_INT, 'Number of times the page has been viewed.'),
     557                              'readonly' => new external_value(PARAM_INT, '1 if readonly, 0 otherwise.'),
     558                              'caneditpage' => new external_value(PARAM_BOOL, 'True if user can edit the page.'),
     559                              'firstpage' => new external_value(PARAM_BOOL, 'True if it\'s the first page.'),
     560                              'cachedcontent' => new external_value(PARAM_RAW, 'Page contents.', VALUE_OPTIONAL),
     561                              'contentformat' => new external_format_value('cachedcontent', VALUE_OPTIONAL),
     562                              'contentsize' => new external_value(PARAM_INT, 'Size of page contents in bytes (doesn\'t include'.
     563                                                                              ' size of attached files).', VALUE_OPTIONAL),
     564                              'tags' => new external_multiple_structure(
     565                                  \core_tag\external\tag_item_exporter::get_read_structure(), 'Tags', VALUE_OPTIONAL
     566                              ),
     567                          ), 'Pages'
     568                      )
     569                  ),
     570                  'warnings' => new external_warnings(),
     571              )
     572          );
     573      }
     574  
     575      /**
     576       * Describes the parameters for get_page_contents.
     577       *
     578       * @return external_function_parameters
     579       * @since Moodle 3.1
     580       */
     581      public static function get_page_contents_parameters() {
     582          return new external_function_parameters (
     583              array(
     584                  'pageid' => new external_value(PARAM_INT, 'Page ID.')
     585              )
     586          );
     587      }
     588  
     589      /**
     590       * Get a page contents.
     591       *
     592       * @param int $pageid The page ID.
     593       * @return array of warnings and page data.
     594       * @since Moodle 3.1
     595       */
     596      public static function get_page_contents($pageid) {
     597  
     598          $params = self::validate_parameters(self::get_page_contents_parameters(),
     599                                              array(
     600                                                  'pageid' => $pageid
     601                                              )
     602              );
     603          $warnings = array();
     604  
     605          // Get wiki page.
     606          if (!$page = wiki_get_page($params['pageid'])) {
     607              throw new moodle_exception('incorrectpageid', 'wiki');
     608          }
     609  
     610          // Get wiki instance.
     611          if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
     612              throw new moodle_exception('incorrectwikiid', 'wiki');
     613          }
     614  
     615          // Permission validation.
     616          $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
     617          $context = context_module::instance($cm->id);
     618          self::validate_context($context);
     619  
     620          // Check if user can view this wiki.
     621          if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
     622              throw new moodle_exception('incorrectsubwikiid', 'wiki');
     623          }
     624          if (!wiki_user_can_view($subwiki, $wiki)) {
     625              throw new moodle_exception('cannotviewpage', 'wiki');
     626          }
     627  
     628          $returnedpage = array();
     629          $returnedpage['id'] = $page->id;
     630          $returnedpage['wikiid'] = $wiki->id;
     631          $returnedpage['subwikiid'] = $page->subwikiid;
     632          $returnedpage['groupid'] = $subwiki->groupid;
     633          $returnedpage['userid'] = $subwiki->userid;
     634          $returnedpage['title'] = $page->title;
     635          $returnedpage['tags'] = \core_tag\external\util::get_item_tags('mod_wiki', 'wiki_pages', $page->id);
     636  
     637          // Refresh page cached content if needed.
     638          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
     639              if ($content = wiki_refresh_cachedcontent($page)) {
     640                  $page = $content['page'];
     641              }
     642          }
     643  
     644          list($returnedpage['cachedcontent'], $returnedpage['contentformat']) = external_format_text(
     645                              $page->cachedcontent, FORMAT_HTML, $context->id, 'mod_wiki', 'attachments', $subwiki->id);
     646          $returnedpage['caneditpage'] = wiki_user_can_edit($subwiki);
     647  
     648          // Get page version.
     649          $version = wiki_get_current_version($page->id);
     650          if (!empty($version)) {
     651              $returnedpage['version'] = $version->version;
     652          }
     653  
     654          $result = array();
     655          $result['page'] = $returnedpage;
     656          $result['warnings'] = $warnings;
     657          return $result;
     658      }
     659  
     660      /**
     661       * Describes the get_page_contents return value.
     662       *
     663       * @return external_single_structure
     664       * @since Moodle 3.1
     665       */
     666      public static function get_page_contents_returns() {
     667          return new external_single_structure(
     668              array(
     669                  'page' => new external_single_structure(
     670                      array(
     671                          'id' => new external_value(PARAM_INT, 'Page ID.'),
     672                          'wikiid' => new external_value(PARAM_INT, 'Page\'s wiki ID.'),
     673                          'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.'),
     674                          'groupid' => new external_value(PARAM_INT, 'Page\'s group ID.'),
     675                          'userid' => new external_value(PARAM_INT, 'Page\'s user ID.'),
     676                          'title' => new external_value(PARAM_RAW, 'Page title.'),
     677                          'cachedcontent' => new external_value(PARAM_RAW, 'Page contents.'),
     678                          'contentformat' => new external_format_value('cachedcontent', VALUE_OPTIONAL),
     679                          'caneditpage' => new external_value(PARAM_BOOL, 'True if user can edit the page.'),
     680                          'version' => new external_value(PARAM_INT, 'Latest version of the page.', VALUE_OPTIONAL),
     681                          'tags' => new external_multiple_structure(
     682                              \core_tag\external\tag_item_exporter::get_read_structure(), 'Tags', VALUE_OPTIONAL
     683                          ),
     684                      ), 'Page'
     685                  ),
     686                  'warnings' => new external_warnings()
     687              )
     688          );
     689      }
     690  
     691      /**
     692       * Describes the parameters for get_subwiki_files.
     693       *
     694       * @return external_function_parameters
     695       * @since Moodle 3.1
     696       */
     697      public static function get_subwiki_files_parameters() {
     698          return new external_function_parameters (
     699              array(
     700                  'wikiid' => new external_value(PARAM_INT, 'Wiki instance ID.'),
     701                  'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID, -1 means current group. It will be ignored'
     702                                          . ' if the wiki doesn\'t use groups.', VALUE_DEFAULT, -1),
     703                  'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID, 0 means current user. It will be ignored'
     704                                          .' in collaborative wikis.', VALUE_DEFAULT, 0)
     705              )
     706          );
     707      }
     708  
     709      /**
     710       * Returns the list of files from a specific subwiki.
     711       *
     712       * @param int $wikiid The wiki instance ID.
     713       * @param int $groupid The group ID. If not defined, use current group.
     714       * @param int $userid The user ID. If not defined, use current user.
     715       * @return array Containing a list of warnings and a list of files.
     716       * @since Moodle 3.1
     717       * @throws moodle_exception
     718       */
     719      public static function get_subwiki_files($wikiid, $groupid = -1, $userid = 0) {
     720  
     721          $returnedfiles = array();
     722          $warnings = array();
     723  
     724          $params = self::validate_parameters(self::get_subwiki_files_parameters(),
     725                                              array(
     726                                                  'wikiid' => $wikiid,
     727                                                  'groupid' => $groupid,
     728                                                  'userid' => $userid
     729                                                  )
     730              );
     731  
     732          // Get wiki instance.
     733          if (!$wiki = wiki_get_wiki($params['wikiid'])) {
     734              throw new moodle_exception('incorrectwikiid', 'wiki');
     735          }
     736          list($course, $cm) = get_course_and_cm_from_instance($wiki, 'wiki');
     737          $context = context_module::instance($cm->id);
     738          self::validate_context($context);
     739  
     740          // Determine groupid and userid to use.
     741          list($groupid, $userid) = self::determine_group_and_user($cm, $wiki, $params['groupid'], $params['userid']);
     742  
     743          // Get subwiki and validate it.
     744          $subwiki = wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid);
     745  
     746          // Get subwiki based on group and user.
     747          if ($subwiki === false) {
     748              throw new moodle_exception('cannotviewfiles', 'wiki');
     749          } else if ($subwiki->id != -1) {
     750              // The subwiki exists, let's get the files.
     751              $returnedfiles = external_util::get_area_files($context->id, 'mod_wiki', 'attachments', $subwiki->id);
     752          }
     753  
     754          $result = array();
     755          $result['files'] = $returnedfiles;
     756          $result['warnings'] = $warnings;
     757          return $result;
     758      }
     759  
     760      /**
     761       * Describes the get_subwiki_pages return value.
     762       *
     763       * @return external_single_structure
     764       * @since Moodle 3.1
     765       */
     766      public static function get_subwiki_files_returns() {
     767  
     768          return new external_single_structure(
     769              array(
     770                  'files' => new external_files('Files'),
     771                  'warnings' => new external_warnings(),
     772              )
     773          );
     774      }
     775  
     776      /**
     777       * Utility function for determining the groupid and userid to use.
     778       *
     779       * @param stdClass $cm The course module.
     780       * @param stdClass $wiki The wiki.
     781       * @param int $groupid Group ID. If not defined, use current group.
     782       * @param int $userid User ID. If not defined, use current user.
     783       * @return array Array containing the courseid and userid.
     784       * @since  Moodle 3.1
     785       */
     786      protected static function determine_group_and_user($cm, $wiki, $groupid = -1, $userid = 0) {
     787          global $USER;
     788  
     789          $currentgroup = groups_get_activity_group($cm);
     790          if ($currentgroup === false) {
     791              // Activity doesn't use groups.
     792              $groupid = 0;
     793          } else if ($groupid == -1) {
     794              // Use current group.
     795              $groupid = !empty($currentgroup) ? $currentgroup : 0;
     796          }
     797  
     798          // Determine user.
     799          if ($wiki->wikimode == 'collaborative') {
     800              // Collaborative wikis don't use userid in subwikis.
     801              $userid = 0;
     802          } else if (empty($userid)) {
     803              // Use current user.
     804              $userid = $USER->id;
     805          }
     806  
     807          return array($groupid, $userid);
     808      }
     809  
     810      /**
     811       * Describes the parameters for get_page_for_editing.
     812       *
     813       * @return external_function_parameters
     814       * @since Moodle 3.1
     815       */
     816      public static function get_page_for_editing_parameters() {
     817          return new external_function_parameters (
     818              array(
     819                  'pageid' => new external_value(PARAM_INT, 'Page ID to edit.'),
     820                  'section' => new external_value(PARAM_RAW, 'Section page title.', VALUE_DEFAULT, null),
     821                  'lockonly' => new external_value(PARAM_BOOL, 'Just renew lock and not return content.', VALUE_DEFAULT, false)
     822              )
     823          );
     824      }
     825  
     826      /**
     827       * Locks and retrieves info of page-section to be edited.
     828       *
     829       * @param int $pageid The page ID.
     830       * @param string $section Section page title.
     831       * @param boolean $lockonly If true: Just renew lock and not return content.
     832       * @return array of warnings and page data.
     833       * @since Moodle 3.1
     834       */
     835      public static function get_page_for_editing($pageid, $section = null, $lockonly = false) {
     836          global $USER;
     837  
     838          $params = self::validate_parameters(self::get_page_for_editing_parameters(),
     839                                              array(
     840                                                  'pageid' => $pageid,
     841                                                  'section' => $section,
     842                                                  'lockonly' => $lockonly
     843                                              )
     844              );
     845  
     846          $warnings = array();
     847  
     848          // Get wiki page.
     849          if (!$page = wiki_get_page($params['pageid'])) {
     850              throw new moodle_exception('incorrectpageid', 'wiki');
     851          }
     852  
     853          // Get wiki instance.
     854          if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
     855              throw new moodle_exception('incorrectwikiid', 'wiki');
     856          }
     857  
     858          // Get subwiki instance.
     859          if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
     860              throw new moodle_exception('incorrectsubwikiid', 'wiki');
     861          }
     862  
     863          // Permission validation.
     864          $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
     865          $context = context_module::instance($cm->id);
     866          self::validate_context($context);
     867  
     868          if (!wiki_user_can_edit($subwiki)) {
     869              throw new moodle_exception('cannoteditpage', 'wiki');
     870          }
     871  
     872          if (!wiki_set_lock($params['pageid'], $USER->id, $params['section'], true)) {
     873              throw new moodle_exception('pageislocked', 'wiki');
     874          }
     875  
     876          $version = wiki_get_current_version($page->id);
     877          if (empty($version)) {
     878              throw new moodle_exception('versionerror', 'wiki');
     879          }
     880  
     881          $pagesection = array();
     882          $pagesection['version'] = $version->version;
     883  
     884          // Content requested to be returned.
     885          if (!$lockonly) {
     886              if (!is_null($params['section'])) {
     887                  $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $params['section']);
     888              } else {
     889                  $content = $version->content;
     890              }
     891  
     892              $pagesection['content'] = $content;
     893              $pagesection['contentformat'] = $version->contentformat;
     894          }
     895  
     896          $result = array();
     897          $result['pagesection'] = $pagesection;
     898          $result['warnings'] = $warnings;
     899          return $result;
     900  
     901      }
     902  
     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                              VALUE_OPTIONAL),
     916                          'contentformat' => new external_value(PARAM_TEXT, 'Format of the original content of the page.',
     917                              VALUE_OPTIONAL),
     918                          'version' => new external_value(PARAM_INT, 'Latest version of the page.'),
     919                          'warnings' => new external_warnings()
     920                      )
     921                  )
     922              )
     923          );
     924      }
     925  
     926      /**
     927       * Describes the parameters for new_page.
     928       *
     929       * @return external_function_parameters
     930       * @since Moodle 3.1
     931       */
     932      public static function new_page_parameters() {
     933          return new external_function_parameters (
     934              array(
     935                  'title' => new external_value(PARAM_TEXT, 'New page title.'),
     936                  'content' => new external_value(PARAM_RAW, 'Page contents.'),
     937                  'contentformat' => new external_value(PARAM_TEXT, 'Page contents format. If an invalid format is provided, default
     938                      wiki format is used.', VALUE_DEFAULT, null),
     939                  'subwikiid' => new external_value(PARAM_INT, 'Page\'s subwiki ID.', VALUE_DEFAULT, null),
     940                  'wikiid' => new external_value(PARAM_INT, 'Page\'s wiki ID. Used if subwiki does not exists.', VALUE_DEFAULT,
     941                      null),
     942                  'userid' => new external_value(PARAM_INT, 'Subwiki\'s user ID. Used if subwiki does not exists.', VALUE_DEFAULT,
     943                      null),
     944                  'groupid' => new external_value(PARAM_INT, 'Subwiki\'s group ID. Used if subwiki does not exists.', VALUE_DEFAULT,
     945                      null)
     946              )
     947          );
     948      }
     949  
     950      /**
     951       * Creates a new page.
     952       *
     953       * @param string $title New page title.
     954       * @param string $content Page contents.
     955       * @param int $contentformat Page contents format. If an invalid format is provided, default wiki format is used.
     956       * @param int $subwikiid The Subwiki ID where to store the page.
     957       * @param int $wikiid Page\'s wiki ID. Used if subwiki does not exists.
     958       * @param int $userid Subwiki\'s user ID. Used if subwiki does not exists.
     959       * @param int $groupid Subwiki\'s group ID. Used if subwiki does not exists.
     960       * @return array of warnings and page data.
     961       * @since Moodle 3.1
     962       */
     963      public static function new_page($title, $content, $contentformat = null, $subwikiid = null, $wikiid = null, $userid = null,
     964          $groupid = null) {
     965          global $USER;
     966  
     967          $params = self::validate_parameters(self::new_page_parameters(),
     968                                              array(
     969                                                  'title' => $title,
     970                                                  'content' => $content,
     971                                                  'contentformat' => $contentformat,
     972                                                  'subwikiid' => $subwikiid,
     973                                                  'wikiid' => $wikiid,
     974                                                  'userid' => $userid,
     975                                                  'groupid' => $groupid
     976                                              )
     977              );
     978  
     979          $warnings = array();
     980  
     981          // Get wiki and subwiki instances.
     982          if (!empty($params['subwikiid'])) {
     983              if (!$subwiki = wiki_get_subwiki($params['subwikiid'])) {
     984                  throw new moodle_exception('incorrectsubwikiid', 'wiki');
     985              }
     986  
     987              if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
     988                  throw new moodle_exception('incorrectwikiid', 'wiki');
     989              }
     990  
     991              // Permission validation.
     992              $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
     993              $context = context_module::instance($cm->id);
     994              self::validate_context($context);
     995  
     996          } else {
     997              if (!$wiki = wiki_get_wiki($params['wikiid'])) {
     998                  throw new moodle_exception('incorrectwikiid', 'wiki');
     999              }
    1000  
    1001              // Permission validation.
    1002              $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
    1003              $context = context_module::instance($cm->id);
    1004              self::validate_context($context);
    1005  
    1006              // Determine groupid and userid to use.
    1007              list($groupid, $userid) = self::determine_group_and_user($cm, $wiki, $params['groupid'], $params['userid']);
    1008  
    1009              // Get subwiki and validate it.
    1010              $subwiki = wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid);
    1011  
    1012              if ($subwiki === false) {
    1013                  // User cannot view page.
    1014                  throw new moodle_exception('cannoteditpage', 'wiki');
    1015              } else if ($subwiki->id < 0) {
    1016                  // Subwiki needed to check edit permissions.
    1017                  if (!wiki_user_can_edit($subwiki)) {
    1018                      throw new moodle_exception('cannoteditpage', 'wiki');
    1019                  }
    1020  
    1021                  // Subwiki does not exists and it can be created.
    1022                  $swid = wiki_add_subwiki($wiki->id, $groupid, $userid);
    1023                  if (!$subwiki = wiki_get_subwiki($swid)) {
    1024                      throw new moodle_exception('incorrectsubwikiid', 'wiki');
    1025                  }
    1026              }
    1027          }
    1028  
    1029          // Subwiki needed to check edit permissions.
    1030          if (!wiki_user_can_edit($subwiki)) {
    1031              throw new moodle_exception('cannoteditpage', 'wiki');
    1032          }
    1033  
    1034          if ($page = wiki_get_page_by_title($subwiki->id, $params['title'])) {
    1035              throw new moodle_exception('pageexists', 'wiki');
    1036          }
    1037  
    1038          // Ignore invalid formats and use default instead.
    1039          if (!$params['contentformat'] || $wiki->forceformat) {
    1040              $params['contentformat'] = $wiki->defaultformat;
    1041          } else {
    1042              $formats = wiki_get_formats();
    1043              if (!in_array($params['contentformat'], $formats)) {
    1044                  $params['contentformat'] = $wiki->defaultformat;
    1045              }
    1046          }
    1047  
    1048          $newpageid = wiki_create_page($subwiki->id, $params['title'], $params['contentformat'], $USER->id);
    1049  
    1050          if (!$page = wiki_get_page($newpageid)) {
    1051              throw new moodle_exception('incorrectpageid', 'wiki');
    1052          }
    1053  
    1054          // Save content.
    1055          $save = wiki_save_page($page, $params['content'], $USER->id);
    1056  
    1057          if (!$save) {
    1058              throw new moodle_exception('savingerror', 'wiki');
    1059          }
    1060  
    1061          $result = array();
    1062          $result['pageid'] = $page->id;
    1063          $result['warnings'] = $warnings;
    1064          return $result;
    1065      }
    1066  
    1067      /**
    1068       * Describes the new_page return value.
    1069       *
    1070       * @return external_single_structure
    1071       * @since Moodle 3.1
    1072       */
    1073      public static function new_page_returns() {
    1074          return new external_single_structure(
    1075              array(
    1076                  'pageid' => new external_value(PARAM_INT, 'New page id.'),
    1077                  'warnings' => new external_warnings()
    1078              )
    1079          );
    1080      }
    1081  
    1082      /**
    1083       * Describes the parameters for edit_page.
    1084       *
    1085       * @return external_function_parameters
    1086       * @since Moodle 3.1
    1087       */
    1088      public static function edit_page_parameters() {
    1089          return new external_function_parameters (
    1090              array(
    1091                  'pageid' => new external_value(PARAM_INT, 'Page ID.'),
    1092                  'content' => new external_value(PARAM_RAW, 'Page contents.'),
    1093                  'section' => new external_value(PARAM_RAW, 'Section page title.', VALUE_DEFAULT, null)
    1094              )
    1095          );
    1096      }
    1097  
    1098      /**
    1099       * Edit a page contents.
    1100       *
    1101       * @param int $pageid The page ID.
    1102       * @param string $content Page contents.
    1103       * @param int $section Section to be edited.
    1104       * @return array of warnings and page data.
    1105       * @since Moodle 3.1
    1106       */
    1107      public static function edit_page($pageid, $content, $section = null) {
    1108          global $USER;
    1109  
    1110          $params = self::validate_parameters(self::edit_page_parameters(),
    1111                                              array(
    1112                                                  'pageid' => $pageid,
    1113                                                  'content' => $content,
    1114                                                  'section' => $section
    1115                                              )
    1116              );
    1117          $warnings = array();
    1118  
    1119          // Get wiki page.
    1120          if (!$page = wiki_get_page($params['pageid'])) {
    1121              throw new moodle_exception('incorrectpageid', 'wiki');
    1122          }
    1123  
    1124          // Get wiki instance.
    1125          if (!$wiki = wiki_get_wiki_from_pageid($params['pageid'])) {
    1126              throw new moodle_exception('incorrectwikiid', 'wiki');
    1127          }
    1128  
    1129          // Get subwiki instance.
    1130          if (!$subwiki = wiki_get_subwiki($page->subwikiid)) {
    1131              throw new moodle_exception('incorrectsubwikiid', 'wiki');
    1132          }
    1133  
    1134          // Permission validation.
    1135          $cm = get_coursemodule_from_instance('wiki', $wiki->id, $wiki->course);
    1136          $context = context_module::instance($cm->id);
    1137          self::validate_context($context);
    1138  
    1139          if (!wiki_user_can_edit($subwiki)) {
    1140              throw new moodle_exception('cannoteditpage', 'wiki');
    1141          }
    1142  
    1143          if (wiki_is_page_section_locked($page->id, $USER->id, $params['section'])) {
    1144              throw new moodle_exception('pageislocked', 'wiki');
    1145          }
    1146  
    1147          // Save content.
    1148          if (!is_null($params['section'])) {
    1149              $version = wiki_get_current_version($page->id);
    1150              $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $params['section'], false);
    1151              if (!$content) {
    1152                  throw new moodle_exception('invalidsection', 'wiki');
    1153              }
    1154  
    1155              $save = wiki_save_section($page, $params['section'], $params['content'], $USER->id);
    1156          } else {
    1157              $save = wiki_save_page($page, $params['content'], $USER->id);
    1158          }
    1159  
    1160          wiki_delete_locks($page->id, $USER->id, $params['section']);
    1161  
    1162          if (!$save) {
    1163              throw new moodle_exception('savingerror', 'wiki');
    1164          }
    1165  
    1166          $result = array();
    1167          $result['pageid'] = $page->id;
    1168          $result['warnings'] = $warnings;
    1169          return $result;
    1170      }
    1171  
    1172      /**
    1173       * Describes the edit_page return value.
    1174       *
    1175       * @return external_single_structure
    1176       * @since Moodle 3.1
    1177       */
    1178      public static function edit_page_returns() {
    1179          return new external_single_structure(
    1180              array(
    1181                  'pageid' => new external_value(PARAM_INT, 'Edited page id.'),
    1182                  'warnings' => new external_warnings()
    1183              )
    1184          );
    1185      }
    1186  
    1187  }