[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/wiki/ -> locallib.php (source)

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * This contains functions and classes that will be used by scripts in wiki module
  20   *
  21   * @package mod_wiki
  22   * @copyright 2009 Marc Alier, Jordi Piguillem marc.alier@upc.edu
  23   * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu
  24   *
  25   * @author Jordi Piguillem
  26   * @author Marc Alier
  27   * @author David Jimenez
  28   * @author Josep Arus
  29   * @author Daniel Serrano
  30   * @author Kenneth Riba
  31   *
  32   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  
  35  require_once($CFG->dirroot . '/mod/wiki/lib.php');
  36  require_once($CFG->dirroot . '/mod/wiki/parser/parser.php');
  37  require_once($CFG->libdir . '/filelib.php');
  38  
  39  define('WIKI_REFRESH_CACHE_TIME', 30); // @TODO: To be deleted.
  40  define('FORMAT_CREOLE', '37');
  41  define('FORMAT_NWIKI', '38');
  42  define('NO_VALID_RATE', '-999');
  43  define('IMPROVEMENT', '+');
  44  define('EQUAL', '=');
  45  define('WORST', '-');
  46  
  47  define('LOCK_TIMEOUT', 30);
  48  
  49  /**
  50   * Get a wiki instance
  51   * @param int $wikiid the instance id of wiki
  52   */
  53  function wiki_get_wiki($wikiid) {
  54      global $DB;
  55  
  56      return $DB->get_record('wiki', array('id' => $wikiid));
  57  }
  58  
  59  /**
  60   * Get sub wiki instances with same wiki id
  61   * @param int $wikiid
  62   */
  63  function wiki_get_subwikis($wikiid) {
  64      global $DB;
  65      return $DB->get_records('wiki_subwikis', array('wikiid' => $wikiid));
  66  }
  67  
  68  /**
  69   * Get a sub wiki instance by wiki id and group id
  70   * @param int $wikiid
  71   * @param int $groupid
  72   * @return object
  73   */
  74  function wiki_get_subwiki_by_group($wikiid, $groupid, $userid = 0) {
  75      global $DB;
  76      return $DB->get_record('wiki_subwikis', array('wikiid' => $wikiid, 'groupid' => $groupid, 'userid' => $userid));
  77  }
  78  
  79  /**
  80   * Get a sub wiki instace by instance id
  81   * @param int $subwikiid
  82   * @return object
  83   */
  84  function wiki_get_subwiki($subwikiid) {
  85      global $DB;
  86      return $DB->get_record('wiki_subwikis', array('id' => $subwikiid));
  87  
  88  }
  89  
  90  /**
  91   * Add a new sub wiki instance
  92   * @param int $wikiid
  93   * @param int $groupid
  94   * @return int $insertid
  95   */
  96  function wiki_add_subwiki($wikiid, $groupid, $userid = 0) {
  97      global $DB;
  98  
  99      $record = new StdClass();
 100      $record->wikiid = $wikiid;
 101      $record->groupid = $groupid;
 102      $record->userid = $userid;
 103  
 104      $insertid = $DB->insert_record('wiki_subwikis', $record);
 105      return $insertid;
 106  }
 107  
 108  /**
 109   * Get a wiki instance by pageid
 110   * @param int $pageid
 111   * @return object
 112   */
 113  function wiki_get_wiki_from_pageid($pageid) {
 114      global $DB;
 115  
 116      $sql = "SELECT w.*
 117              FROM {wiki} w, {wiki_subwikis} s, {wiki_pages} p
 118              WHERE p.id = ? AND
 119              p.subwikiid = s.id AND
 120              s.wikiid = w.id";
 121  
 122      return $DB->get_record_sql($sql, array($pageid));
 123  }
 124  
 125  /**
 126   * Get a wiki page by pageid
 127   * @param int $pageid
 128   * @return object
 129   */
 130  function wiki_get_page($pageid) {
 131      global $DB;
 132      return $DB->get_record('wiki_pages', array('id' => $pageid));
 133  }
 134  
 135  /**
 136   * Get latest version of wiki page
 137   * @param int $pageid
 138   * @return object
 139   */
 140  function wiki_get_current_version($pageid) {
 141      global $DB;
 142  
 143      // @TODO: Fix this query
 144      $sql = "SELECT *
 145              FROM {wiki_versions}
 146              WHERE pageid = ?
 147              ORDER BY version DESC";
 148      $records = $DB->get_records_sql($sql, array($pageid), 0, 1);
 149      return array_pop($records);
 150  
 151  }
 152  
 153  /**
 154   * Alias of wiki_get_current_version
 155   * @TODO, does the exactly same thing as wiki_get_current_version, should be removed
 156   * @param int $pageid
 157   * @return object
 158   */
 159  function wiki_get_last_version($pageid) {
 160      return wiki_get_current_version($pageid);
 161  }
 162  
 163  /**
 164   * Get page section
 165   * @param int $pageid
 166   * @param string $section
 167   */
 168  function wiki_get_section_page($page, $section) {
 169  
 170      $version = wiki_get_current_version($page->id);
 171      return wiki_parser_proxy::get_section($version->content, $version->contentformat, $section);
 172  }
 173  
 174  /**
 175   * Get a wiki page by page title
 176   * @param int $swid, sub wiki id
 177   * @param string $title
 178   * @return object
 179   */
 180  function wiki_get_page_by_title($swid, $title) {
 181      global $DB;
 182      return $DB->get_record('wiki_pages', array('subwikiid' => $swid, 'title' => $title));
 183  }
 184  
 185  /**
 186   * Get a version record by record id
 187   * @param int $versionid, the version id
 188   * @return object
 189   */
 190  function wiki_get_version($versionid) {
 191      global $DB;
 192      return $DB->get_record('wiki_versions', array('id' => $versionid));
 193  }
 194  
 195  /**
 196   * Get first page of wiki instace
 197   * @param int $subwikiid
 198   * @param int $module, wiki instance object
 199   */
 200  function wiki_get_first_page($subwikid, $module = null) {
 201      global $DB, $USER;
 202  
 203      $sql = "SELECT p.*
 204              FROM {wiki} w, {wiki_subwikis} s, {wiki_pages} p
 205              WHERE s.id = ? AND
 206              s.wikiid = w.id AND
 207              w.firstpagetitle = p.title AND
 208              p.subwikiid = s.id";
 209      return $DB->get_record_sql($sql, array($subwikid));
 210  }
 211  
 212  function wiki_save_section($wikipage, $sectiontitle, $sectioncontent, $userid) {
 213  
 214      $wiki = wiki_get_wiki_from_pageid($wikipage->id);
 215      $cm = get_coursemodule_from_instance('wiki', $wiki->id);
 216      $context = context_module::instance($cm->id);
 217  
 218      if (has_capability('mod/wiki:editpage', $context)) {
 219          $version = wiki_get_current_version($wikipage->id);
 220          $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $sectiontitle, true);
 221  
 222          $newcontent = $content[0] . $sectioncontent . $content[2];
 223  
 224          return wiki_save_page($wikipage, $newcontent, $userid);
 225      } else {
 226          return false;
 227      }
 228  }
 229  
 230  /**
 231   * Save page content
 232   * @param object $wikipage
 233   * @param string $newcontent
 234   * @param int $userid
 235   */
 236  function wiki_save_page($wikipage, $newcontent, $userid) {
 237      global $DB;
 238  
 239      $wiki = wiki_get_wiki_from_pageid($wikipage->id);
 240      $cm = get_coursemodule_from_instance('wiki', $wiki->id);
 241      $context = context_module::instance($cm->id);
 242  
 243      if (has_capability('mod/wiki:editpage', $context)) {
 244          $version = wiki_get_current_version($wikipage->id);
 245  
 246          $version->content = $newcontent;
 247          $version->userid = $userid;
 248          $version->version++;
 249          $version->timecreated = time();
 250          $version->id = $DB->insert_record('wiki_versions', $version);
 251  
 252          $wikipage->timemodified = $version->timecreated;
 253          $wikipage->userid = $userid;
 254          $return = wiki_refresh_cachedcontent($wikipage, $newcontent);
 255          $event = \mod_wiki\event\page_updated::create(
 256                  array(
 257                      'context' => $context,
 258                      'objectid' => $wikipage->id,
 259                      'relateduserid' => $userid,
 260                      'other' => array(
 261                          'newcontent' => $newcontent
 262                          )
 263                      ));
 264          $event->add_record_snapshot('wiki', $wiki);
 265          $event->add_record_snapshot('wiki_pages', $wikipage);
 266          $event->add_record_snapshot('wiki_versions', $version);
 267          $event->trigger();
 268          return $return;
 269      } else {
 270          return false;
 271      }
 272  }
 273  
 274  function wiki_refresh_cachedcontent($page, $newcontent = null) {
 275      global $DB;
 276  
 277      $version = wiki_get_current_version($page->id);
 278      if (empty($version)) {
 279          return null;
 280      }
 281      if (!isset($newcontent)) {
 282          $newcontent = $version->content;
 283      }
 284  
 285      $options = array('swid' => $page->subwikiid, 'pageid' => $page->id);
 286      $parseroutput = wiki_parse_content($version->contentformat, $newcontent, $options);
 287      $page->cachedcontent = $parseroutput['toc'] . $parseroutput['parsed_text'];
 288      $page->timerendered = time();
 289      $DB->update_record('wiki_pages', $page);
 290  
 291      wiki_refresh_page_links($page, $parseroutput['link_count']);
 292  
 293      return array('page' => $page, 'sections' => $parseroutput['repeated_sections'], 'version' => $version->version);
 294  }
 295  
 296  /**
 297   * Restore a page with specified version.
 298   *
 299   * @param stdClass $wikipage wiki page record
 300   * @param stdClass $version wiki page version to restore
 301   * @param context_module $context context of wiki module
 302   * @return stdClass restored page
 303   */
 304  function wiki_restore_page($wikipage, $version, $context) {
 305      $return = wiki_save_page($wikipage, $version->content, $version->userid);
 306      $event = \mod_wiki\event\page_version_restored::create(
 307              array(
 308                  'context' => $context,
 309                  'objectid' => $version->id,
 310                  'other' => array(
 311                      'pageid' => $wikipage->id
 312                      )
 313                  ));
 314      $event->add_record_snapshot('wiki_versions', $version);
 315      $event->trigger();
 316      return $return['page'];
 317  }
 318  
 319  function wiki_refresh_page_links($page, $links) {
 320      global $DB;
 321  
 322      $DB->delete_records('wiki_links', array('frompageid' => $page->id));
 323      foreach ($links as $linkname => $linkinfo) {
 324  
 325          $newlink = new stdClass();
 326          $newlink->subwikiid = $page->subwikiid;
 327          $newlink->frompageid = $page->id;
 328  
 329          if ($linkinfo['new']) {
 330              $newlink->tomissingpage = $linkname;
 331          } else {
 332              $newlink->topageid = $linkinfo['pageid'];
 333          }
 334  
 335          try {
 336              $DB->insert_record('wiki_links', $newlink);
 337          } catch (dml_exception $e) {
 338              debugging($e->getMessage());
 339          }
 340  
 341      }
 342  }
 343  
 344  /**
 345   * Create a new wiki page, if the page exists, return existing pageid
 346   * @param int $swid
 347   * @param string $title
 348   * @param string $format
 349   * @param int $userid
 350   */
 351  function wiki_create_page($swid, $title, $format, $userid) {
 352      global $DB;
 353      $subwiki = wiki_get_subwiki($swid);
 354      $cm = get_coursemodule_from_instance('wiki', $subwiki->wikiid);
 355      $context = context_module::instance($cm->id);
 356      require_capability('mod/wiki:editpage', $context);
 357      // if page exists
 358      if ($page = wiki_get_page_by_title($swid, $title)) {
 359          return $page->id;
 360      }
 361  
 362      // Creating a new empty version
 363      $version = new stdClass();
 364      $version->content = '';
 365      $version->contentformat = $format;
 366      $version->version = 0;
 367      $version->timecreated = time();
 368      $version->userid = $userid;
 369  
 370      $versionid = null;
 371      $versionid = $DB->insert_record('wiki_versions', $version);
 372  
 373      // Createing a new empty page
 374      $page = new stdClass();
 375      $page->subwikiid = $swid;
 376      $page->title = $title;
 377      $page->cachedcontent = '';
 378      $page->timecreated = $version->timecreated;
 379      $page->timemodified = $version->timecreated;
 380      $page->timerendered = $version->timecreated;
 381      $page->userid = $userid;
 382      $page->pageviews = 0;
 383      $page->readonly = 0;
 384  
 385      $pageid = $DB->insert_record('wiki_pages', $page);
 386  
 387      // Setting the pageid
 388      $version->id = $versionid;
 389      $version->pageid = $pageid;
 390      $DB->update_record('wiki_versions', $version);
 391  
 392      $event = \mod_wiki\event\page_created::create(
 393              array(
 394                  'context' => $context,
 395                  'objectid' => $pageid
 396                  )
 397              );
 398      $event->trigger();
 399  
 400      wiki_make_cache_expire($page->title);
 401      return $pageid;
 402  }
 403  
 404  function wiki_make_cache_expire($pagename) {
 405      global $DB;
 406  
 407      $sql = "UPDATE {wiki_pages}
 408              SET timerendered = 0
 409              WHERE id IN ( SELECT l.frompageid
 410                  FROM {wiki_links} l
 411                  WHERE l.tomissingpage = ?
 412              )";
 413      $DB->execute ($sql, array($pagename));
 414  }
 415  
 416  /**
 417   * Get a specific version of page
 418   * @param int $pageid
 419   * @param int $version
 420   */
 421  function wiki_get_wiki_page_version($pageid, $version) {
 422      global $DB;
 423      return $DB->get_record('wiki_versions', array('pageid' => $pageid, 'version' => $version));
 424  }
 425  
 426  /**
 427   * Get version list
 428   * @param int $pageid
 429   * @param int $limitfrom
 430   * @param int $limitnum
 431   */
 432  function wiki_get_wiki_page_versions($pageid, $limitfrom, $limitnum) {
 433      global $DB;
 434      return $DB->get_records('wiki_versions', array('pageid' => $pageid), 'version DESC', '*', $limitfrom, $limitnum);
 435  }
 436  
 437  /**
 438   * Count the number of page version
 439   * @param int $pageid
 440   */
 441  function wiki_count_wiki_page_versions($pageid) {
 442      global $DB;
 443      return $DB->count_records('wiki_versions', array('pageid' => $pageid));
 444  }
 445  
 446  /**
 447   * Get linked from page
 448   * @param int $pageid
 449   */
 450  function wiki_get_linked_to_pages($pageid) {
 451      global $DB;
 452      return $DB->get_records('wiki_links', array('frompageid' => $pageid));
 453  }
 454  
 455  /**
 456   * Get linked from page
 457   * @param int $pageid
 458   */
 459  function wiki_get_linked_from_pages($pageid) {
 460      global $DB;
 461      return $DB->get_records('wiki_links', array('topageid' => $pageid));
 462  }
 463  
 464  /**
 465   * Get pages which user have been edited
 466   * @param int $swid
 467   * @param int $userid
 468   */
 469  function wiki_get_contributions($swid, $userid) {
 470      global $DB;
 471  
 472      $sql = "SELECT v.*
 473              FROM {wiki_versions} v, {wiki_pages} p
 474              WHERE p.subwikiid = ? AND
 475              v.pageid = p.id AND
 476              v.userid = ?";
 477  
 478      return $DB->get_records_sql($sql, array($swid, $userid));
 479  }
 480  
 481  /**
 482   * Get missing or empty pages in wiki
 483   * @param int $swid sub wiki id
 484   */
 485  function wiki_get_missing_or_empty_pages($swid) {
 486      global $DB;
 487  
 488      $sql = "SELECT DISTINCT p.title, p.id, p.subwikiid
 489              FROM {wiki} w, {wiki_subwikis} s, {wiki_pages} p
 490              WHERE s.wikiid = w.id and
 491              s.id = ? and
 492              w.firstpagetitle != p.title and
 493              p.subwikiid = ? and
 494              1 =  (SELECT count(*)
 495                  FROM {wiki_versions} v
 496                  WHERE v.pageid = p.id)
 497              UNION
 498              SELECT DISTINCT l.tomissingpage as title, 0 as id, l.subwikiid
 499              FROM {wiki_links} l
 500              WHERE l.subwikiid = ? and
 501              l.topageid = 0";
 502  
 503      return $DB->get_records_sql($sql, array($swid, $swid, $swid));
 504  }
 505  
 506  /**
 507   * Get pages list in wiki
 508   * @param int $swid sub wiki id
 509   * @param string $sort How to sort the pages. By default, title ASC.
 510   */
 511  function wiki_get_page_list($swid, $sort = 'title ASC') {
 512      global $DB;
 513      $records = $DB->get_records('wiki_pages', array('subwikiid' => $swid), $sort);
 514      return $records;
 515  }
 516  
 517  /**
 518   * Return a list of orphaned wikis for one specific subwiki
 519   * @global object
 520   * @param int $swid sub wiki id
 521   */
 522  function wiki_get_orphaned_pages($swid) {
 523      global $DB;
 524  
 525      $sql = "SELECT p.id, p.title
 526              FROM {wiki_pages} p, {wiki} w , {wiki_subwikis} s
 527              WHERE p.subwikiid = ?
 528              AND s.id = ?
 529              AND w.id = s.wikiid
 530              AND p.title != w.firstpagetitle
 531              AND p.id NOT IN (SELECT topageid FROM {wiki_links} WHERE subwikiid = ?)";
 532  
 533      return $DB->get_records_sql($sql, array($swid, $swid, $swid));
 534  }
 535  
 536  /**
 537   * Search wiki title
 538   * @param int $swid sub wiki id
 539   * @param string $search
 540   */
 541  function wiki_search_title($swid, $search) {
 542      global $DB;
 543  
 544      return $DB->get_records_select('wiki_pages', "subwikiid = ? AND title LIKE ?", array($swid, '%'.$search.'%'));
 545  }
 546  
 547  /**
 548   * Search wiki content
 549   * @param int $swid sub wiki id
 550   * @param string $search
 551   */
 552  function wiki_search_content($swid, $search) {
 553      global $DB;
 554  
 555      return $DB->get_records_select('wiki_pages', "subwikiid = ? AND cachedcontent LIKE ?", array($swid, '%'.$search.'%'));
 556  }
 557  
 558  /**
 559   * Search wiki title and content
 560   * @param int $swid sub wiki id
 561   * @param string $search
 562   */
 563  function wiki_search_all($swid, $search) {
 564      global $DB;
 565  
 566      return $DB->get_records_select('wiki_pages', "subwikiid = ? AND (cachedcontent LIKE ? OR title LIKE ?)", array($swid, '%'.$search.'%', '%'.$search.'%'));
 567  }
 568  
 569  /**
 570   * Get user data
 571   */
 572  function wiki_get_user_info($userid) {
 573      global $DB;
 574      return $DB->get_record('user', array('id' => $userid));
 575  }
 576  
 577  /**
 578   * Increase page view nubmer
 579   * @param int $page, database record
 580   */
 581  function wiki_increment_pageviews($page) {
 582      global $DB;
 583  
 584      $page->pageviews++;
 585      $DB->update_record('wiki_pages', $page);
 586  }
 587  
 588  //----------------------------------------------------------
 589  //----------------------------------------------------------
 590  
 591  /**
 592   * Text format supported by wiki module
 593   */
 594  function wiki_get_formats() {
 595      return array('html', 'creole', 'nwiki');
 596  }
 597  
 598  /**
 599   * Parses a string with the wiki markup language in $markup.
 600   *
 601   * @return Array or false when something wrong has happened.
 602   *
 603   * Returned array contains the following fields:
 604   *     'parsed_text' => String. Contains the parsed wiki content.
 605   *     'unparsed_text' => String. Constains the original wiki content.
 606   *     'link_count' => Array of array('destination' => ..., 'new' => "is new?"). Contains the internal wiki links found in the wiki content.
 607   *      'deleted_sections' => the list of deleted sections.
 608   *              '' =>
 609   *
 610   * @author Josep Arús Pous
 611   **/
 612  function wiki_parse_content($markup, $pagecontent, $options = array()) {
 613      global $PAGE;
 614  
 615      $subwiki = wiki_get_subwiki($options['swid']);
 616      $cm = get_coursemodule_from_instance("wiki", $subwiki->wikiid);
 617      $context = context_module::instance($cm->id);
 618  
 619      $parser_options = array(
 620          'link_callback' => '/mod/wiki/locallib.php:wiki_parser_link',
 621          'link_callback_args' => array('swid' => $options['swid']),
 622          'table_callback' => '/mod/wiki/locallib.php:wiki_parser_table',
 623          'real_path_callback' => '/mod/wiki/locallib.php:wiki_parser_real_path',
 624          'real_path_callback_args' => array(
 625              'context' => $context,
 626              'component' => 'mod_wiki',
 627              'filearea' => 'attachments',
 628              'subwikiid'=> $subwiki->id,
 629              'pageid' => $options['pageid']
 630          ),
 631          'pageid' => $options['pageid'],
 632          'pretty_print' => (isset($options['pretty_print']) && $options['pretty_print']),
 633          'printable' => (isset($options['printable']) && $options['printable'])
 634      );
 635  
 636      return wiki_parser_proxy::parse($pagecontent, $markup, $parser_options);
 637  }
 638  
 639  /**
 640   * This function is the parser callback to parse wiki links.
 641   *
 642   * It returns the necesary information to print a link.
 643   *
 644   * NOTE: Empty pages and non-existent pages must be print in red color.
 645   *
 646   * !!!!!! IMPORTANT !!!!!!
 647   * It is critical that you call format_string on the content before it is used.
 648   *
 649   * @param string|page_wiki $link name of a page
 650   * @param array $options
 651   * @return array Array('content' => string, 'url' => string, 'new' => bool, 'link_info' => array)
 652   *
 653   * @TODO Doc return and options
 654   */
 655  function wiki_parser_link($link, $options = null) {
 656      global $CFG;
 657  
 658      if (is_object($link)) {
 659          $parsedlink = array('content' => $link->title, 'url' => $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $link->id, 'new' => false, 'link_info' => array('link' => $link->title, 'pageid' => $link->id, 'new' => false));
 660  
 661          $version = wiki_get_current_version($link->id);
 662          if ($version->version == 0) {
 663              $parsedlink['new'] = true;
 664          }
 665          return $parsedlink;
 666      } else {
 667          $swid = $options['swid'];
 668  
 669          if ($page = wiki_get_page_by_title($swid, $link)) {
 670              $parsedlink = array('content' => $link, 'url' => $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $page->id, 'new' => false, 'link_info' => array('link' => $link, 'pageid' => $page->id, 'new' => false));
 671  
 672              $version = wiki_get_current_version($page->id);
 673              if ($version->version == 0) {
 674                  $parsedlink['new'] = true;
 675              }
 676  
 677              return $parsedlink;
 678  
 679          } else {
 680              return array('content' => $link, 'url' => $CFG->wwwroot . '/mod/wiki/create.php?swid=' . $swid . '&amp;title=' . urlencode($link) . '&amp;action=new', 'new' => true, 'link_info' => array('link' => $link, 'new' => true, 'pageid' => 0));
 681          }
 682      }
 683  }
 684  
 685  /**
 686   * Returns the table fully parsed (HTML)
 687   *
 688   * @return HTML for the table $table
 689   * @author Josep Arús Pous
 690   *
 691   **/
 692  function wiki_parser_table($table) {
 693      global $OUTPUT;
 694  
 695      $htmltable = new html_table();
 696  
 697      $headers = $table[0];
 698      $htmltable->head = array();
 699      foreach ($headers as $h) {
 700          $htmltable->head[] = $h[1];
 701      }
 702  
 703      array_shift($table);
 704      $htmltable->data = array();
 705      foreach ($table as $row) {
 706          $row_data = array();
 707          foreach ($row as $r) {
 708              $row_data[] = $r[1];
 709          }
 710          $htmltable->data[] = $row_data;
 711      }
 712  
 713      return html_writer::table($htmltable);
 714  }
 715  
 716  /**
 717   * Returns an absolute path link, unless there is no such link.
 718   *
 719   * @param string $url Link's URL or filename
 720   * @param stdClass $context filearea params
 721   * @param string $component The component the file is associated with
 722   * @param string $filearea The filearea the file is stored in
 723   * @param int $swid Sub wiki id
 724   *
 725   * @return string URL for files full path
 726   */
 727  
 728  function wiki_parser_real_path($url, $context, $component, $filearea, $swid) {
 729      global $CFG;
 730  
 731      if (preg_match("/^(?:http|ftp)s?\:\/\//", $url)) {
 732          return $url;
 733      } else {
 734  
 735          $file = 'pluginfile.php';
 736          if (!$CFG->slasharguments) {
 737              $file = $file . '?file=';
 738          }
 739          $baseurl = "$CFG->wwwroot/$file/{$context->id}/$component/$filearea/$swid/";
 740          // it is a file in current file area
 741          return $baseurl . $url;
 742      }
 743  }
 744  
 745  /**
 746   * Returns the token used by a wiki language to represent a given tag or "object" (bold -> **)
 747   *
 748   * @return A string when it has only one token at the beginning (f. ex. lists). An array composed by 2 strings when it has 2 tokens, one at the beginning and one at the end (f. ex. italics). Returns false otherwise.
 749   * @author Josep Arús Pous
 750   **/
 751  function wiki_parser_get_token($markup, $name) {
 752  
 753      return wiki_parser_proxy::get_token($name, $markup);
 754  }
 755  
 756  /**
 757   * Checks if current user can view a subwiki
 758   *
 759   * @param stdClass $subwiki usually record from {wiki_subwikis}. Must contain fields 'wikiid', 'groupid', 'userid'.
 760   *     If it also contains fields 'course' and 'groupmode' from table {wiki} it will save extra DB query.
 761   * @param stdClass $wiki optional wiki object if known
 762   * @return bool
 763   */
 764  function wiki_user_can_view($subwiki, $wiki = null) {
 765      global $USER;
 766  
 767      if (empty($wiki) || $wiki->id != $subwiki->wikiid) {
 768          $wiki = wiki_get_wiki($subwiki->wikiid);
 769      }
 770      $modinfo = get_fast_modinfo($wiki->course);
 771      if (!isset($modinfo->instances['wiki'][$subwiki->wikiid])) {
 772          // Module does not exist.
 773          return false;
 774      }
 775      $cm = $modinfo->instances['wiki'][$subwiki->wikiid];
 776      if (!$cm->uservisible) {
 777          // The whole module is not visible to the current user.
 778          return false;
 779      }
 780      $context = context_module::instance($cm->id);
 781  
 782      // Working depending on activity groupmode
 783      switch (groups_get_activity_groupmode($cm)) {
 784      case NOGROUPS:
 785  
 786          if ($wiki->wikimode == 'collaborative') {
 787              // Collaborative Mode:
 788              // There is one wiki for all the class.
 789              //
 790              // Only view capbility needed
 791              return has_capability('mod/wiki:viewpage', $context);
 792          } else if ($wiki->wikimode == 'individual') {
 793              // Individual Mode:
 794              // Each person owns a wiki.
 795              if ($subwiki->userid == $USER->id) {
 796                  // Only the owner of the wiki can view it
 797                  return has_capability('mod/wiki:viewpage', $context);
 798              } else { // User has special capabilities
 799                  // User must have:
 800                  //      mod/wiki:viewpage capability
 801                  // and
 802                  //      mod/wiki:managewiki capability
 803                  $view = has_capability('mod/wiki:viewpage', $context);
 804                  $manage = has_capability('mod/wiki:managewiki', $context);
 805  
 806                  return $view && $manage;
 807              }
 808          } else {
 809              //Error
 810              return false;
 811          }
 812      case SEPARATEGROUPS:
 813          // Collaborative and Individual Mode
 814          //
 815          // Collaborative Mode:
 816          //      There is one wiki per group.
 817          // Individual Mode:
 818          //      Each person owns a wiki.
 819          if ($wiki->wikimode == 'collaborative' || $wiki->wikimode == 'individual') {
 820              // Only members of subwiki group could view that wiki
 821              if (in_array($subwiki->groupid, $modinfo->get_groups($cm->groupingid))) {
 822                  // Only view capability needed
 823                  return has_capability('mod/wiki:viewpage', $context);
 824  
 825              } else { // User is not part of that group
 826                  // User must have:
 827                  //      mod/wiki:managewiki capability
 828                  // or
 829                  //      moodle/site:accessallgroups capability
 830                  // and
 831                  //      mod/wiki:viewpage capability
 832                  $view = has_capability('mod/wiki:viewpage', $context);
 833                  $manage = has_capability('mod/wiki:managewiki', $context);
 834                  $access = has_capability('moodle/site:accessallgroups', $context);
 835                  return ($manage || $access) && $view;
 836              }
 837          } else {
 838              //Error
 839              return false;
 840          }
 841      case VISIBLEGROUPS:
 842          // Collaborative and Individual Mode
 843          //
 844          // Collaborative Mode:
 845          //      There is one wiki per group.
 846          // Individual Mode:
 847          //      Each person owns a wiki.
 848          if ($wiki->wikimode == 'collaborative' || $wiki->wikimode == 'individual') {
 849              // Everybody can read all wikis
 850              //
 851              // Only view capability needed
 852              return has_capability('mod/wiki:viewpage', $context);
 853          } else {
 854              //Error
 855              return false;
 856          }
 857      default: // Error
 858          return false;
 859      }
 860  }
 861  
 862  /**
 863   * Checks if current user can edit a subwiki
 864   *
 865   * @param $subwiki
 866   */
 867  function wiki_user_can_edit($subwiki) {
 868      global $USER;
 869  
 870      $wiki = wiki_get_wiki($subwiki->wikiid);
 871      $cm = get_coursemodule_from_instance('wiki', $wiki->id);
 872      $context = context_module::instance($cm->id);
 873  
 874      // Working depending on activity groupmode
 875      switch (groups_get_activity_groupmode($cm)) {
 876      case NOGROUPS:
 877  
 878          if ($wiki->wikimode == 'collaborative') {
 879              // Collaborative Mode:
 880              // There is a wiki for all the class.
 881              //
 882              // Only edit capbility needed
 883              return has_capability('mod/wiki:editpage', $context);
 884          } else if ($wiki->wikimode == 'individual') {
 885              // Individual Mode
 886              // There is a wiki per user
 887  
 888              // Only the owner of that wiki can edit it
 889              if ($subwiki->userid == $USER->id) {
 890                  return has_capability('mod/wiki:editpage', $context);
 891              } else { // Current user is not the owner of that wiki.
 892  
 893                  // User must have:
 894                  //      mod/wiki:editpage capability
 895                  // and
 896                  //      mod/wiki:managewiki capability
 897                  $edit = has_capability('mod/wiki:editpage', $context);
 898                  $manage = has_capability('mod/wiki:managewiki', $context);
 899  
 900                  return $edit && $manage;
 901              }
 902          } else {
 903              //Error
 904              return false;
 905          }
 906      case SEPARATEGROUPS:
 907          if ($wiki->wikimode == 'collaborative') {
 908              // Collaborative Mode:
 909              // There is one wiki per group.
 910              //
 911              // Only members of subwiki group could edit that wiki
 912              if (groups_is_member($subwiki->groupid)) {
 913                  // Only edit capability needed
 914                  return has_capability('mod/wiki:editpage', $context);
 915              } else { // User is not part of that group
 916                  // User must have:
 917                  //      mod/wiki:managewiki capability
 918                  // and
 919                  //      moodle/site:accessallgroups capability
 920                  // and
 921                  //      mod/wiki:editpage capability
 922                  $manage = has_capability('mod/wiki:managewiki', $context);
 923                  $access = has_capability('moodle/site:accessallgroups', $context);
 924                  $edit = has_capability('mod/wiki:editpage', $context);
 925                  return $manage && $access && $edit;
 926              }
 927          } else if ($wiki->wikimode == 'individual') {
 928              // Individual Mode:
 929              // Each person owns a wiki.
 930              //
 931              // Only the owner of that wiki can edit it
 932              if ($subwiki->userid == $USER->id) {
 933                  return has_capability('mod/wiki:editpage', $context);
 934              } else { // Current user is not the owner of that wiki.
 935                  // User must have:
 936                  //      mod/wiki:managewiki capability
 937                  // and
 938                  //      moodle/site:accessallgroups capability
 939                  // and
 940                  //      mod/wiki:editpage capability
 941                  $manage = has_capability('mod/wiki:managewiki', $context);
 942                  $access = has_capability('moodle/site:accessallgroups', $context);
 943                  $edit = has_capability('mod/wiki:editpage', $context);
 944                  return $manage && $access && $edit;
 945              }
 946          } else {
 947              //Error
 948              return false;
 949          }
 950      case VISIBLEGROUPS:
 951          if ($wiki->wikimode == 'collaborative') {
 952              // Collaborative Mode:
 953              // There is one wiki per group.
 954              //
 955              // Only members of subwiki group could edit that wiki
 956              if (groups_is_member($subwiki->groupid)) {
 957                  // Only edit capability needed
 958                  return has_capability('mod/wiki:editpage', $context);
 959              } else { // User is not part of that group
 960                  // User must have:
 961                  //      mod/wiki:managewiki capability
 962                  // and
 963                  //      mod/wiki:editpage capability
 964                  $manage = has_capability('mod/wiki:managewiki', $context);
 965                  $edit = has_capability('mod/wiki:editpage', $context);
 966                  return $manage && $edit;
 967              }
 968          } else if ($wiki->wikimode == 'individual') {
 969              // Individual Mode:
 970              // Each person owns a wiki.
 971              //
 972              // Only the owner of that wiki can edit it
 973              if ($subwiki->userid == $USER->id) {
 974                  return has_capability('mod/wiki:editpage', $context);
 975              } else { // Current user is not the owner of that wiki.
 976                  // User must have:
 977                  //      mod/wiki:managewiki capability
 978                  // and
 979                  //      mod/wiki:editpage capability
 980                  $manage = has_capability('mod/wiki:managewiki', $context);
 981                  $edit = has_capability('mod/wiki:editpage', $context);
 982                  return $manage && $edit;
 983              }
 984          } else {
 985              //Error
 986              return false;
 987          }
 988      default: // Error
 989          return false;
 990      }
 991  }
 992  
 993  //----------------
 994  // Locks
 995  //----------------
 996  
 997  /**
 998   * Checks if a page-section is locked.
 999   *
1000   * @return true if the combination of section and page is locked, FALSE otherwise.
1001   */
1002  function wiki_is_page_section_locked($pageid, $userid, $section = null) {
1003      global $DB;
1004  
1005      $sql = "pageid = ? AND lockedat > ? AND userid != ?";
1006      $params = array($pageid, time(), $userid);
1007  
1008      if (!empty($section)) {
1009          $sql .= " AND (sectionname = ? OR sectionname IS null)";
1010          $params[] = $section;
1011      }
1012  
1013      return $DB->record_exists_select('wiki_locks', $sql, $params);
1014  }
1015  
1016  /**
1017   * Inserts or updates a wiki_locks record.
1018   */
1019  function wiki_set_lock($pageid, $userid, $section = null, $insert = false) {
1020      global $DB;
1021  
1022      if (wiki_is_page_section_locked($pageid, $userid, $section)) {
1023          return false;
1024      }
1025  
1026      $params = array('pageid' => $pageid, 'userid' => $userid, 'sectionname' => $section);
1027  
1028      $lock = $DB->get_record('wiki_locks', $params);
1029  
1030      if (!empty($lock)) {
1031          $DB->update_record('wiki_locks', array('id' => $lock->id, 'lockedat' => time() + LOCK_TIMEOUT));
1032      } else if ($insert) {
1033          $DB->insert_record('wiki_locks', array('pageid' => $pageid, 'sectionname' => $section, 'userid' => $userid, 'lockedat' => time() + 30));
1034      }
1035  
1036      return true;
1037  }
1038  
1039  /**
1040   * Deletes wiki_locks that are not in use. (F.Ex. after submitting the changes). If no userid is present, it deletes ALL the wiki_locks of a specific page.
1041   *
1042   * @param int $pageid page id.
1043   * @param int $userid id of user for which lock is deleted.
1044   * @param string $section section to be deleted.
1045   * @param bool $delete_from_db deleted from db.
1046   * @param bool $delete_section_and_page delete section and page version.
1047   */
1048  function wiki_delete_locks($pageid, $userid = null, $section = null, $delete_from_db = true, $delete_section_and_page = false) {
1049      global $DB;
1050  
1051      $wiki = wiki_get_wiki_from_pageid($pageid);
1052      $cm = get_coursemodule_from_instance('wiki', $wiki->id);
1053      $context = context_module::instance($cm->id);
1054  
1055      $params = array('pageid' => $pageid);
1056  
1057      if (!empty($userid)) {
1058          $params['userid'] = $userid;
1059      }
1060  
1061      if (!empty($section)) {
1062          $params['sectionname'] = $section;
1063      }
1064  
1065      if ($delete_from_db) {
1066          $DB->delete_records('wiki_locks', $params);
1067          if ($delete_section_and_page && !empty($section)) {
1068              $params['sectionname'] = null;
1069              $DB->delete_records('wiki_locks', $params);
1070          }
1071          $event = \mod_wiki\event\page_locks_deleted::create(
1072          array(
1073              'context' => $context,
1074              'objectid' => $pageid,
1075              'relateduserid' => $userid,
1076              'other' => array(
1077                  'section' => $section
1078                  )
1079              ));
1080          // No need to add snapshot, as important data is section, userid and pageid, which is part of event.
1081          $event->trigger();
1082      } else {
1083          $DB->set_field('wiki_locks', 'lockedat', time(), $params);
1084      }
1085  }
1086  
1087  /**
1088   * Deletes wiki_locks that expired 1 hour ago.
1089   */
1090  function wiki_delete_old_locks() {
1091      global $DB;
1092  
1093      $DB->delete_records_select('wiki_locks', "lockedat < ?", array(time() - 3600));
1094  }
1095  
1096  /**
1097   * Deletes wiki_links. It can be sepecific link or links attached in subwiki
1098   *
1099   * @global mixed $DB database object
1100   * @param int $linkid id of the link to be deleted
1101   * @param int $topageid links to the specific page
1102   * @param int $frompageid links from specific page
1103   * @param int $subwikiid links to subwiki
1104   */
1105  function wiki_delete_links($linkid = null, $topageid = null, $frompageid = null, $subwikiid = null) {
1106      global $DB;
1107      $params = array();
1108  
1109      // if link id is givien then don't check for anything else
1110      if (!empty($linkid)) {
1111          $params['id'] = $linkid;
1112      } else {
1113          if (!empty($topageid)) {
1114              $params['topageid'] = $topageid;
1115          }
1116          if (!empty($frompageid)) {
1117              $params['frompageid'] = $frompageid;
1118          }
1119          if (!empty($subwikiid)) {
1120              $params['subwikiid'] = $subwikiid;
1121          }
1122      }
1123  
1124      //Delete links if any params are passed, else nothing to delete.
1125      if (!empty($params)) {
1126          $DB->delete_records('wiki_links', $params);
1127      }
1128  }
1129  
1130  /**
1131   * Delete wiki synonyms related to subwikiid or page
1132   *
1133   * @param int $subwikiid id of sunbwiki
1134   * @param int $pageid id of page
1135   */
1136  function wiki_delete_synonym($subwikiid, $pageid = null) {
1137      global $DB;
1138  
1139      $params = array('subwikiid' => $subwikiid);
1140      if (!is_null($pageid)) {
1141          $params['pageid'] = $pageid;
1142      }
1143      $DB->delete_records('wiki_synonyms', $params, IGNORE_MISSING);
1144  }
1145  
1146  /**
1147   * Delete pages and all related data
1148   *
1149   * @param mixed $context context in which page needs to be deleted.
1150   * @param mixed $pageids id's of pages to be deleted
1151   * @param int $subwikiid id of the subwiki for which all pages should be deleted
1152   */
1153  function wiki_delete_pages($context, $pageids = null, $subwikiid = null) {
1154      global $DB, $CFG;
1155  
1156      if (!empty($pageids) && is_int($pageids)) {
1157         $pageids = array($pageids);
1158      } else if (!empty($subwikiid)) {
1159          $pageids = wiki_get_page_list($subwikiid);
1160      }
1161  
1162      //If there is no pageid then return as we can't delete anything.
1163      if (empty($pageids)) {
1164          return;
1165      }
1166  
1167      /// Delete page and all it's relevent data
1168      foreach ($pageids as $pageid) {
1169          if (is_object($pageid)) {
1170              $pageid = $pageid->id;
1171          }
1172  
1173          //Delete page comments
1174          $comments = wiki_get_comments($context->id, $pageid);
1175          foreach ($comments as $commentid => $commentvalue) {
1176              wiki_delete_comment($commentid, $context, $pageid);
1177          }
1178  
1179          //Delete page tags
1180          core_tag_tag::remove_all_item_tags('mod_wiki', 'wiki_pages', $pageid);
1181  
1182          //Delete Synonym
1183          wiki_delete_synonym($subwikiid, $pageid);
1184  
1185          //Delete all page versions
1186          wiki_delete_page_versions(array($pageid=>array(0)), $context);
1187  
1188          //Delete all page locks
1189          wiki_delete_locks($pageid);
1190  
1191          //Delete all page links
1192          wiki_delete_links(null, $pageid);
1193  
1194          $params = array('id' => $pageid);
1195  
1196          // Get page before deleting.
1197          $page = $DB->get_record('wiki_pages', $params);
1198  
1199          //Delete page
1200          $DB->delete_records('wiki_pages', $params);
1201  
1202          // Trigger page_deleted event.
1203          $event = \mod_wiki\event\page_deleted::create(
1204                  array(
1205                      'context' => $context,
1206                      'objectid' => $pageid,
1207                      'other' => array('subwikiid' => $subwikiid)
1208                      ));
1209          $event->add_record_snapshot('wiki_pages', $page);
1210          $event->trigger();
1211      }
1212  }
1213  
1214  /**
1215   * Delete specificed versions of a page or versions created by users
1216   * if version is 0 then it will remove all versions of the page
1217   *
1218   * @param array $deleteversions delete versions for a page
1219   * @param context_module $context module context
1220   */
1221  function wiki_delete_page_versions($deleteversions, $context = null) {
1222      global $DB;
1223  
1224      /// delete page-versions
1225      foreach ($deleteversions as $id => $versions) {
1226          $params = array('pageid' => $id);
1227          if (is_null($context)) {
1228              $wiki = wiki_get_wiki_from_pageid($id);
1229              $cm = get_coursemodule_from_instance('wiki', $wiki->id);
1230              $context = context_module::instance($cm->id);
1231          }
1232          // Delete all versions, if version specified is 0.
1233          if (in_array(0, $versions)) {
1234              $oldversions = $DB->get_records('wiki_versions', $params);
1235              $DB->delete_records('wiki_versions', $params, IGNORE_MISSING);
1236          } else {
1237              list($insql, $param) = $DB->get_in_or_equal($versions);
1238              $insql .= ' AND pageid = ?';
1239              array_push($param, $params['pageid']);
1240              $oldversions = $DB->get_recordset_select('wiki_versions', 'version ' . $insql, $param);
1241              $DB->delete_records_select('wiki_versions', 'version ' . $insql, $param);
1242          }
1243          foreach ($oldversions as $version) {
1244              // Trigger page version deleted event.
1245              $event = \mod_wiki\event\page_version_deleted::create(
1246                      array(
1247                          'context' => $context,
1248                          'objectid' => $version->id,
1249                          'other' => array(
1250                              'pageid' => $id
1251                          )
1252                      ));
1253              $event->add_record_snapshot('wiki_versions', $version);
1254              $event->trigger();
1255          }
1256      }
1257  }
1258  
1259  function wiki_get_comment($commentid){
1260      global $DB;
1261      return $DB->get_record('comments', array('id' => $commentid));
1262  }
1263  
1264  /**
1265   * Returns all comments by context and pageid
1266   *
1267   * @param int $contextid Current context id
1268   * @param int $pageid Current pageid
1269   **/
1270  function wiki_get_comments($contextid, $pageid) {
1271      global $DB;
1272  
1273      return $DB->get_records('comments', array('contextid' => $contextid, 'itemid' => $pageid, 'commentarea' => 'wiki_page'), 'timecreated ASC');
1274  }
1275  
1276  /**
1277   * Add comments ro database
1278   *
1279   * @param object $context. Current context
1280   * @param int $pageid. Current pageid
1281   * @param string $content. Content of the comment
1282   * @param string editor. Version of editor we are using.
1283   **/
1284  function wiki_add_comment($context, $pageid, $content, $editor) {
1285      global $CFG;
1286      require_once($CFG->dirroot . '/comment/lib.php');
1287  
1288      list($context, $course, $cm) = get_context_info_array($context->id);
1289      $cmt = new stdclass();
1290      $cmt->context = $context;
1291      $cmt->itemid = $pageid;
1292      $cmt->area = 'wiki_page';
1293      $cmt->course = $course;
1294      $cmt->component = 'mod_wiki';
1295  
1296      $manager = new comment($cmt);
1297  
1298      if ($editor == 'creole') {
1299          $manager->add($content, FORMAT_CREOLE);
1300      } else if ($editor == 'html') {
1301          $manager->add($content, FORMAT_HTML);
1302      } else if ($editor == 'nwiki') {
1303          $manager->add($content, FORMAT_NWIKI);
1304      }
1305  
1306  }
1307  
1308  /**
1309   * Delete comments from database
1310   *
1311   * @param $idcomment. Id of comment which will be deleted
1312   * @param $context. Current context
1313   * @param $pageid. Current pageid
1314   **/
1315  function wiki_delete_comment($idcomment, $context, $pageid) {
1316      global $CFG;
1317      require_once($CFG->dirroot . '/comment/lib.php');
1318  
1319      list($context, $course, $cm) = get_context_info_array($context->id);
1320      $cmt = new stdClass();
1321      $cmt->context = $context;
1322      $cmt->itemid = $pageid;
1323      $cmt->area = 'wiki_page';
1324      $cmt->course = $course;
1325      $cmt->component = 'mod_wiki';
1326  
1327      $manager = new comment($cmt);
1328      $manager->delete($idcomment);
1329  
1330  }
1331  
1332  /**
1333   * Delete al comments from wiki
1334   *
1335   **/
1336  function wiki_delete_comments_wiki() {
1337      global $PAGE, $DB;
1338  
1339      $cm = $PAGE->cm;
1340      $context = context_module::instance($cm->id);
1341  
1342      $table = 'comments';
1343      $select = 'contextid = ?';
1344  
1345      $DB->delete_records_select($table, $select, array($context->id));
1346  
1347  }
1348  
1349  function wiki_add_progress($pageid, $oldversionid, $versionid, $progress) {
1350      global $DB;
1351      for ($v = $oldversionid + 1; $v <= $versionid; $v++) {
1352          $user = wiki_get_wiki_page_id($pageid, $v);
1353  
1354          $DB->insert_record('wiki_progress', array('userid' => $user->userid, 'pageid' => $pageid, 'versionid' => $v, 'progress' => $progress));
1355      }
1356  }
1357  
1358  function wiki_get_wiki_page_id($pageid, $id) {
1359      global $DB;
1360      return $DB->get_record('wiki_versions', array('pageid' => $pageid, 'id' => $id));
1361  }
1362  
1363  function wiki_print_page_content($page, $context, $subwikiid) {
1364      global $OUTPUT, $CFG;
1365  
1366      if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1367          $content = wiki_refresh_cachedcontent($page);
1368          $page = $content['page'];
1369      }
1370  
1371      if (isset($content)) {
1372          $box = '';
1373          foreach ($content['sections'] as $s) {
1374              $box .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
1375          }
1376  
1377          if (!empty($box)) {
1378              echo $OUTPUT->box($box);
1379          }
1380      }
1381      $html = file_rewrite_pluginfile_urls($page->cachedcontent, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $subwikiid);
1382      $html = format_text($html, FORMAT_MOODLE, array('overflowdiv'=>true, 'allowid'=>true));
1383      echo $OUTPUT->box($html);
1384  
1385      echo $OUTPUT->tag_list(core_tag_tag::get_item_tags('mod_wiki', 'wiki_pages', $page->id),
1386              null, 'wiki-tags');
1387  
1388      wiki_increment_pageviews($page);
1389  }
1390  
1391  /**
1392   * This function trims any given text and returns it with some dots at the end
1393   *
1394   * @param string $text
1395   * @param string $limit
1396   *
1397   * @return string
1398   */
1399  function wiki_trim_string($text, $limit = 25) {
1400  
1401      if (core_text::strlen($text) > $limit) {
1402          $text = core_text::substr($text, 0, $limit) . '...';
1403      }
1404  
1405      return $text;
1406  }
1407  
1408  /**
1409   * Prints default edit form fields and buttons
1410   *
1411   * @param string $format Edit form format (html, creole...)
1412   * @param integer $version Version number. A negative number means no versioning.
1413   */
1414  
1415  function wiki_print_edit_form_default_fields($format, $pageid, $version = -1, $upload = false, $deleteuploads = array()) {
1416      global $CFG, $PAGE, $OUTPUT;
1417  
1418      echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
1419  
1420      if ($version >= 0) {
1421          echo '<input type="hidden" name="version" value="' . $version . '" />';
1422      }
1423  
1424      echo '<input type="hidden" name="format" value="' . $format . '"/>';
1425  
1426      //attachments
1427      require_once($CFG->dirroot . '/lib/form/filemanager.php');
1428  
1429      $filemanager = new MoodleQuickForm_filemanager('attachments', get_string('wikiattachments', 'wiki'), array('id' => 'attachments'), array('subdirs' => false, 'maxfiles' => 99, 'maxbytes' => $CFG->maxbytes));
1430  
1431      $value = file_get_submitted_draft_itemid('attachments');
1432      if (!empty($value) && !$upload) {
1433          $filemanager->setValue($value);
1434      }
1435  
1436      echo "<fieldset class=\"wiki-upload-section clearfix\"><legend class=\"ftoggler\">" . get_string("uploadtitle", 'wiki') . "</legend>";
1437  
1438      echo $OUTPUT->container_start('mdl-align wiki-form-center aaaaa');
1439      print $filemanager->toHtml();
1440      echo $OUTPUT->container_end();
1441  
1442      $cm = $PAGE->cm;
1443      $context = context_module::instance($cm->id);
1444  
1445      echo $OUTPUT->container_start('mdl-align wiki-form-center wiki-upload-table');
1446      wiki_print_upload_table($context, 'wiki_upload', $pageid, $deleteuploads);
1447      echo $OUTPUT->container_end();
1448  
1449      echo "</fieldset>";
1450  
1451      echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('save', 'wiki') . '"/>';
1452      echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('upload', 'wiki') . '"/>';
1453      echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('preview') . '"/>';
1454      echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('cancel') . '" />';
1455  }
1456  
1457  /**
1458   * Prints a table with the files attached to a wiki page
1459   * @param object $context
1460   * @param string $filearea
1461   * @param int $fileitemid
1462   * @param array deleteuploads
1463   */
1464  function wiki_print_upload_table($context, $filearea, $fileitemid, $deleteuploads = array()) {
1465      global $CFG, $OUTPUT;
1466  
1467      $htmltable = new html_table();
1468  
1469      $htmltable->head = array(get_string('deleteupload', 'wiki'), get_string('uploadname', 'wiki'), get_string('uploadactions', 'wiki'));
1470  
1471      $fs = get_file_storage();
1472      $files = $fs->get_area_files($context->id, 'mod_wiki', $filearea, $fileitemid); //TODO: this is weird (skodak)
1473  
1474      foreach ($files as $file) {
1475          if (!$file->is_directory()) {
1476              $checkbox = '<input type="checkbox" name="deleteupload[]", value="' . $file->get_pathnamehash() . '"';
1477  
1478              if (in_array($file->get_pathnamehash(), $deleteuploads)) {
1479                  $checkbox .= ' checked="checked"';
1480              }
1481  
1482              $checkbox .= " />";
1483  
1484              $htmltable->data[] = array($checkbox, '<a href="' . file_encode_url($CFG->wwwroot . '/pluginfile.php', '/' . $context->id . '/wiki_upload/' . $fileitemid . '/' . $file->get_filename()) . '">' . $file->get_filename() . '</a>', "");
1485          }
1486      }
1487  
1488      print '<h3 class="upload-table-title">' . get_string('uploadfiletitle', 'wiki') . "</h3>";
1489      print html_writer::table($htmltable);
1490  }
1491  
1492  /**
1493   * Generate wiki's page tree
1494   *
1495   * @param page_wiki $page. A wiki page object
1496   * @param navigation_node $node. Starting navigation_node
1497   * @param array $keys. An array to store keys
1498   * @return an array with all tree nodes
1499   */
1500  function wiki_build_tree($page, $node, &$keys) {
1501      $content = array();
1502      static $icon = null;
1503      if ($icon === null) {
1504          // Substitute the default navigation icon with empty image.
1505          $icon = new pix_icon('spacer', '');
1506      }
1507      $pages = wiki_get_linked_pages($page->id);
1508      foreach ($pages as $p) {
1509          $key = $page->id . ':' . $p->id;
1510          if (in_array($key, $keys)) {
1511              break;
1512          }
1513          array_push($keys, $key);
1514          $l = wiki_parser_link($p);
1515          $link = new moodle_url('/mod/wiki/view.php', array('pageid' => $p->id));
1516          // navigation_node::get_content will format the title for us
1517          $nodeaux = $node->add($p->title, $link, null, null, null, $icon);
1518          if ($l['new']) {
1519              $nodeaux->add_class('wiki_newentry');
1520          }
1521          wiki_build_tree($p, $nodeaux, $keys);
1522      }
1523      $content[] = $node;
1524      return $content;
1525  }
1526  
1527  /**
1528   * Get linked pages from page
1529   * @param int $pageid
1530   */
1531  function wiki_get_linked_pages($pageid) {
1532      global $DB;
1533  
1534      $sql = "SELECT p.id, p.title
1535              FROM {wiki_pages} p
1536              JOIN {wiki_links} l ON l.topageid = p.id
1537              WHERE l.frompageid = ?
1538              ORDER BY p.title ASC";
1539      return $DB->get_records_sql($sql, array($pageid));
1540  }
1541  
1542  /**
1543   * Get updated pages from wiki
1544   * @param int $pageid
1545   */
1546  function wiki_get_updated_pages_by_subwiki($swid) {
1547      global $DB, $USER;
1548  
1549      $sql = "SELECT *
1550              FROM {wiki_pages}
1551              WHERE subwikiid = ? AND timemodified > ?
1552              ORDER BY timemodified DESC";
1553      return $DB->get_records_sql($sql, array($swid, $USER->lastlogin));
1554  }
1555  
1556  /**
1557   * Check if the user can create pages in a certain wiki.
1558   * @param context $context Wiki's context.
1559   * @param integer|stdClass $user A user id or object. By default (null) checks the permissions of the current user.
1560   * @return bool True if user can create pages, false otherwise.
1561   * @since Moodle 3.1
1562   */
1563  function wiki_can_create_pages($context, $user = null) {
1564      return has_capability('mod/wiki:createpage', $context, $user);
1565  }
1566  
1567  /**
1568   * Get a sub wiki instance by wiki id, group id and user id.
1569   * If the wiki doesn't exist in DB it will return an isntance with id -1.
1570   *
1571   * @param int $wikiid  Wiki ID.
1572   * @param int $groupid Group ID.
1573   * @param int $userid  User ID.
1574   * @return object      Subwiki instance.
1575   * @since Moodle 3.1
1576   */
1577  function wiki_get_possible_subwiki_by_group($wikiid, $groupid, $userid = 0) {
1578      if (!$subwiki = wiki_get_subwiki_by_group($wikiid, $groupid, $userid)) {
1579          $subwiki = new stdClass();
1580          $subwiki->id = -1;
1581          $subwiki->wikiid = $wikiid;
1582          $subwiki->groupid = $groupid;
1583          $subwiki->userid = $userid;
1584      }
1585      return $subwiki;
1586  }
1587  
1588  /**
1589   * Get all the possible subwikis visible to the user in a wiki.
1590   * It will return all the subwikis that can be created in a wiki, even if they don't exist in DB yet.
1591   *
1592   * @param  stdClass $wiki          Wiki to get the subwikis from.
1593   * @param  cm_info|stdClass $cm    Optional. The course module object.
1594   * @param  context_module $context Optional. Context of wiki module.
1595   * @return array                   List of subwikis.
1596   * @since Moodle 3.1
1597   */
1598  function wiki_get_visible_subwikis($wiki, $cm = null, $context = null) {
1599      global $USER;
1600  
1601      $subwikis = array();
1602  
1603      if (empty($wiki) or !is_object($wiki)) {
1604          // Wiki not valid.
1605          return $subwikis;
1606      }
1607  
1608      if (empty($cm)) {
1609          $cm = get_coursemodule_from_instance('wiki', $wiki->id);
1610      }
1611      if (empty($context)) {
1612          $context = context_module::instance($cm->id);
1613      }
1614  
1615      if (!has_capability('mod/wiki:viewpage', $context)) {
1616          return $subwikis;
1617      }
1618  
1619      $manage = has_capability('mod/wiki:managewiki', $context);
1620  
1621      if (!$groupmode = groups_get_activity_groupmode($cm)) {
1622          // No groups.
1623          if ($wiki->wikimode == 'collaborative') {
1624              // Only 1 subwiki.
1625              $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, 0, 0);
1626          } else if ($wiki->wikimode == 'individual') {
1627              // There's 1 subwiki per user.
1628              if ($manage) {
1629                  // User can view all subwikis.
1630                  $users = get_enrolled_users($context);
1631                  foreach ($users as $user) {
1632                      $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, 0, $user->id);
1633                  }
1634              } else {
1635                  // User can only see his subwiki.
1636                  $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, 0, $USER->id);
1637              }
1638          }
1639      } else {
1640          if ($wiki->wikimode == 'collaborative') {
1641              // 1 subwiki per group.
1642              $aag = has_capability('moodle/site:accessallgroups', $context);
1643              if ($aag || $groupmode == VISIBLEGROUPS) {
1644                  // User can see all groups.
1645                  $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid);
1646                  $allparticipants = new stdClass();
1647                  $allparticipants->id = 0;
1648                  array_unshift($allowedgroups, $allparticipants); // Add all participants.
1649              } else {
1650                  // User can only see the groups he belongs to.
1651                  $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid);
1652              }
1653  
1654              foreach ($allowedgroups as $group) {
1655                  $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, $group->id, 0);
1656              }
1657          } else if ($wiki->wikimode == 'individual') {
1658              // 1 subwiki per user and group.
1659  
1660              if ($manage || $groupmode == VISIBLEGROUPS) {
1661                  // User can view all subwikis.
1662                  $users = get_enrolled_users($context);
1663                  foreach ($users as $user) {
1664                      // Get all the groups this user belongs to.
1665                      $groups = groups_get_all_groups($cm->course, $user->id);
1666                      if (!empty($groups)) {
1667                          foreach ($groups as $group) {
1668                              $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, $group->id, $user->id);
1669                          }
1670                      } else {
1671                          // User doesn't belong to any group, add it to group 0.
1672                          $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, 0, $user->id);
1673                      }
1674                  }
1675              } else {
1676                  // The user can only see the subwikis of the groups he belongs.
1677                  $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid);
1678                  foreach ($allowedgroups as $group) {
1679                      $users = groups_get_members($group->id);
1680                      foreach ($users as $user) {
1681                          $subwikis[] = wiki_get_possible_subwiki_by_group($wiki->id, $group->id, $user->id);
1682                      }
1683                  }
1684              }
1685          }
1686      }
1687  
1688      return $subwikis;
1689  }
1690  
1691  /**
1692   * Utility function for getting a subwiki by group and user, validating that the user can view it.
1693   * If the subwiki doesn't exists in DB yet it'll have id -1.
1694   *
1695   * @param stdClass $wiki The wiki.
1696   * @param int $groupid Group ID. 0 means the subwiki doesn't use groups.
1697   * @param int $userid User ID. 0 means the subwiki doesn't use users.
1698   * @return stdClass Subwiki. If it doesn't exists in DB yet it'll have id -1. If the user can't view the
1699   *                  subwiki this function will return false.
1700   * @since  Moodle 3.1
1701   * @throws moodle_exception
1702   */
1703  function wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $userid) {
1704      global $USER, $DB;
1705  
1706      // Get subwiki based on group and user.
1707      if (!$subwiki = wiki_get_subwiki_by_group($wiki->id, $groupid, $userid)) {
1708  
1709          // The subwiki doesn't exist.
1710          // Validate if user is valid.
1711          if ($userid != 0) {
1712              $user = core_user::get_user($userid, '*', MUST_EXIST);
1713              core_user::require_active_user($user);
1714          }
1715  
1716          // Validate that groupid is valid.
1717          if ($groupid != 0 && !groups_group_exists($groupid)) {
1718              throw new moodle_exception('cannotfindgroup', 'error');
1719          }
1720  
1721          // Valid data but subwiki not found. We'll simulate a subwiki object to check if the user would be able to see it
1722          // if it existed. If he's able to see it then we'll return an empty array because the subwiki has no pages.
1723          $subwiki = new stdClass();
1724          $subwiki->id = -1;
1725          $subwiki->wikiid = $wiki->id;
1726          $subwiki->userid = $userid;
1727          $subwiki->groupid = $groupid;
1728      }
1729  
1730      // Check that the user can view the subwiki. This function checks capabilities.
1731      if (!wiki_user_can_view($subwiki, $wiki)) {
1732          return false;
1733      }
1734  
1735      return $subwiki;
1736  }
1737  
1738  /**
1739   * Returns wiki pages tagged with a specified tag.
1740   *
1741   * This is a callback used by the tag area mod_wiki/wiki_pages to search for wiki pages
1742   * tagged with a specific tag.
1743   *
1744   * @param core_tag_tag $tag
1745   * @param bool $exclusivemode if set to true it means that no other entities tagged with this tag
1746   *             are displayed on the page and the per-page limit may be bigger
1747   * @param int $fromctx context id where the link was displayed, may be used by callbacks
1748   *            to display items in the same context first
1749   * @param int $ctx context id where to search for records
1750   * @param bool $rec search in subcontexts as well
1751   * @param int $page 0-based number of page being displayed
1752   * @return \core_tag\output\tagindex
1753   */
1754  function mod_wiki_get_tagged_pages($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0) {
1755      global $OUTPUT;
1756      $perpage = $exclusivemode ? 20 : 5;
1757  
1758      // Build the SQL query.
1759      $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
1760      $query = "SELECT wp.id, wp.title, ws.userid, ws.wikiid, ws.id AS subwikiid, ws.groupid, w.wikimode,
1761                      cm.id AS cmid, c.id AS courseid, c.shortname, c.fullname, $ctxselect
1762                  FROM {wiki_pages} wp
1763                  JOIN {wiki_subwikis} ws ON wp.subwikiid = ws.id
1764                  JOIN {wiki} w ON w.id = ws.wikiid
1765                  JOIN {modules} m ON m.name='wiki'
1766                  JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = w.id
1767                  JOIN {tag_instance} tt ON wp.id = tt.itemid
1768                  JOIN {course} c ON cm.course = c.id
1769                  JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :coursemodulecontextlevel
1770                 WHERE tt.itemtype = :itemtype AND tt.tagid = :tagid AND tt.component = :component
1771                   AND wp.id %ITEMFILTER% AND c.id %COURSEFILTER%";
1772  
1773      $params = array('itemtype' => 'wiki_pages', 'tagid' => $tag->id, 'component' => 'mod_wiki',
1774          'coursemodulecontextlevel' => CONTEXT_MODULE);
1775  
1776      if ($ctx) {
1777          $context = $ctx ? context::instance_by_id($ctx) : context_system::instance();
1778          $query .= $rec ? ' AND (ctx.id = :contextid OR ctx.path LIKE :path)' : ' AND ctx.id = :contextid';
1779          $params['contextid'] = $context->id;
1780          $params['path'] = $context->path.'/%';
1781      }
1782  
1783      $query .= " ORDER BY ";
1784      if ($fromctx) {
1785          // In order-clause specify that modules from inside "fromctx" context should be returned first.
1786          $fromcontext = context::instance_by_id($fromctx);
1787          $query .= ' (CASE WHEN ctx.id = :fromcontextid OR ctx.path LIKE :frompath THEN 0 ELSE 1 END),';
1788          $params['fromcontextid'] = $fromcontext->id;
1789          $params['frompath'] = $fromcontext->path.'/%';
1790      }
1791      $query .= ' c.sortorder, cm.id, wp.id';
1792  
1793      $totalpages = $page + 1;
1794  
1795      // Use core_tag_index_builder to build and filter the list of items.
1796      $builder = new core_tag_index_builder('mod_wiki', 'wiki_pages', $query, $params, $page * $perpage, $perpage + 1);
1797      while ($item = $builder->has_item_that_needs_access_check()) {
1798          context_helper::preload_from_record($item);
1799          $courseid = $item->courseid;
1800          if (!$builder->can_access_course($courseid)) {
1801              $builder->set_accessible($item, false);
1802              continue;
1803          }
1804          $modinfo = get_fast_modinfo($builder->get_course($courseid));
1805          // Set accessibility of this item and all other items in the same course.
1806          $builder->walk(function ($taggeditem) use ($courseid, $modinfo, $builder) {
1807              if ($taggeditem->courseid == $courseid) {
1808                  $accessible = false;
1809                  if (($cm = $modinfo->get_cm($taggeditem->cmid)) && $cm->uservisible) {
1810                      $subwiki = (object)array('id' => $taggeditem->subwikiid, 'groupid' => $taggeditem->groupid,
1811                          'userid' => $taggeditem->userid, 'wikiid' => $taggeditem->wikiid);
1812                      $wiki = (object)array('id' => $taggeditem->wikiid, 'wikimode' => $taggeditem->wikimode,
1813                          'course' => $cm->course);
1814                      $accessible = wiki_user_can_view($subwiki, $wiki);
1815                  }
1816                  $builder->set_accessible($taggeditem, $accessible);
1817              }
1818          });
1819      }
1820  
1821      $items = $builder->get_items();
1822      if (count($items) > $perpage) {
1823          $totalpages = $page + 2; // We don't need exact page count, just indicate that the next page exists.
1824          array_pop($items);
1825      }
1826  
1827      // Build the display contents.
1828      if ($items) {
1829          $tagfeed = new core_tag\output\tagfeed();
1830          foreach ($items as $item) {
1831              context_helper::preload_from_record($item);
1832              $modinfo = get_fast_modinfo($item->courseid);
1833              $cm = $modinfo->get_cm($item->cmid);
1834              $pageurl = new moodle_url('/mod/wiki/view.php', array('pageid' => $item->id));
1835              $pagename = format_string($item->title, true, array('context' => context_module::instance($item->cmid)));
1836              $pagename = html_writer::link($pageurl, $pagename);
1837              $courseurl = course_get_url($item->courseid, $cm->sectionnum);
1838              $cmname = html_writer::link($cm->url, $cm->get_formatted_name());
1839              $coursename = format_string($item->fullname, true, array('context' => context_course::instance($item->courseid)));
1840              $coursename = html_writer::link($courseurl, $coursename);
1841              $icon = html_writer::link($pageurl, html_writer::empty_tag('img', array('src' => $cm->get_icon_url())));
1842              $tagfeed->add($icon, $pagename, $cmname.'<br>'.$coursename);
1843          }
1844  
1845          $content = $OUTPUT->render_from_template('core_tag/tagfeed',
1846                  $tagfeed->export_for_template($OUTPUT));
1847  
1848          return new core_tag\output\tagindex($tag, 'mod_wiki', 'wiki_pages', $content,
1849                  $exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
1850      }
1851  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1