Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   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 file contains several classes uses to render the diferent pages
  20   * of the wiki module
  21   *
  22   * @package mod_wiki
  23   * @copyright 2009 Marc Alier, Jordi Piguillem marc.alier@upc.edu
  24   * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu
  25   *
  26   * @author Jordi Piguillem
  27   * @author Marc Alier
  28   * @author David Jimenez
  29   * @author Josep Arus
  30   * @author Daniel Serrano
  31   * @author Kenneth Riba
  32   *
  33   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  
  36  defined('MOODLE_INTERNAL') || die();
  37  
  38  require_once($CFG->dirroot . '/mod/wiki/edit_form.php');
  39  
  40  /**
  41   * Class page_wiki contains the common code between all pages
  42   *
  43   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  44   */
  45  abstract class page_wiki {
  46  
  47      /**
  48       * @var object Current subwiki
  49       */
  50      protected $subwiki;
  51  
  52      /**
  53       * @var int Current page
  54       */
  55      protected $page;
  56  
  57      /**
  58       * @var string Current page title
  59       */
  60      protected $title;
  61  
  62      /**
  63       * @var int Current group ID
  64       */
  65      protected $gid;
  66  
  67      /**
  68       * @var object module context object
  69       */
  70      protected $modcontext;
  71  
  72      /**
  73       * @var int Current user ID
  74       */
  75      protected $uid;
  76      /**
  77       * @var array The tabs set used in wiki module
  78       */
  79      protected $tabs = array('view' => 'view', 'edit' => 'edit', 'comments' => 'comments',
  80                              'history' => 'history', 'map' => 'map', 'files' => 'files',
  81                              'admin' => 'admin');
  82      /**
  83       * @var array tabs options
  84       */
  85      protected $tabs_options = array();
  86      /**
  87       * @var mod_wiki_renderer wiki renderer
  88       */
  89      protected $wikioutput;
  90      /**
  91       * @var stdClass course module.
  92       */
  93      protected $cm;
  94  
  95      /**
  96       * The page_wiki constructor.
  97       *
  98       * @param stdClass $wiki Current wiki
  99       * @param stdClass $subwiki Current subwiki.
 100       * @param stdClass $cm Current course_module.
 101       * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
 102       */
 103      public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
 104          global $PAGE, $CFG;
 105          $this->subwiki = $subwiki;
 106          $this->cm = $cm;
 107          $this->modcontext = context_module::instance($this->cm->id);
 108  
 109          // initialise wiki renderer
 110          $this->wikioutput = $PAGE->get_renderer('mod_wiki');
 111          $PAGE->set_cacheable(true);
 112          $PAGE->set_cm($cm);
 113          $PAGE->set_activity_record($wiki);
 114          if ($activesecondarytab) {
 115              $PAGE->set_secondary_active_tab($activesecondarytab);
 116          }
 117          $PAGE->add_body_class('limitedwidth');
 118          // the search box
 119          if (!empty($subwiki->id)) {
 120              $search = optional_param('searchstring', null, PARAM_TEXT);
 121              $PAGE->set_button(wiki_search_form($cm, $search, $subwiki));
 122          }
 123      }
 124  
 125      /**
 126       * This method prints the top of the page.
 127       */
 128      function print_header() {
 129          global $OUTPUT, $PAGE, $SESSION;
 130  
 131          $PAGE->set_heading($PAGE->course->fullname);
 132  
 133          $this->set_url();
 134          if (isset($SESSION->wikipreviousurl) && is_array($SESSION->wikipreviousurl)) {
 135              $this->process_session_url();
 136          }
 137          $this->set_session_url();
 138  
 139          $this->create_navbar();
 140  
 141          echo $OUTPUT->header();
 142  
 143          if (!empty($this->page)) {
 144              echo $this->action_bar($this->page->id, $PAGE->url);
 145          }
 146      }
 147  
 148      /**
 149       * This method returns the action bar.
 150       *
 151       * @param int $pageid The page id.
 152       * @param moodle_url $pageurl The page url.
 153       * @return string The HTML for the action bar.
 154       */
 155      protected function action_bar(int $pageid, moodle_url $pageurl): string {
 156          $actionbar = new \mod_wiki\output\action_bar($pageid, $pageurl);
 157          return $this->wikioutput->render_action_bar($actionbar);
 158      }
 159  
 160      /**
 161       * Protected method to print current page title.
 162       */
 163      protected function print_pagetitle() {
 164          global $OUTPUT;
 165          $html = '';
 166  
 167          $html .= $OUTPUT->container_start('wiki_headingtitle');
 168          $html .= $OUTPUT->heading(format_string($this->title), 3);
 169          $html .= $OUTPUT->container_end();
 170          echo $html;
 171      }
 172  
 173      /**
 174       * Setup page tabs, if options is empty, will set up active tab automatically
 175       * @param array $options, tabs options
 176       */
 177      protected function setup_tabs($options = array()) {
 178          global $CFG, $PAGE;
 179          $groupmode = groups_get_activity_groupmode($this->cm);
 180  
 181          if (empty($CFG->usecomments) || !has_capability('mod/wiki:viewcomment', $PAGE->context)){
 182              unset($this->tabs['comments']);
 183          }
 184  
 185          if (!has_capability('mod/wiki:editpage', $PAGE->context)){
 186              unset($this->tabs['edit']);
 187          }
 188  
 189          if ($groupmode and $groupmode == VISIBLEGROUPS) {
 190              $currentgroup = groups_get_activity_group($this->cm);
 191              $manage = has_capability('mod/wiki:managewiki', $this->modcontext);
 192              $edit = has_capability('mod/wiki:editpage', $PAGE->context);
 193              if (!$manage and !($edit and groups_is_member($currentgroup))) {
 194                  unset($this->tabs['edit']);
 195              }
 196          }
 197  
 198          if (empty($options)) {
 199              $this->tabs_options = array('activetab' => substr(get_class($this), 10));
 200          } else {
 201              $this->tabs_options = $options;
 202          }
 203  
 204      }
 205  
 206      /**
 207       * This method must be overwritten to print the page content.
 208       */
 209      function print_content() {
 210          throw new coding_exception('Page wiki class does not implement method print_content()');
 211      }
 212  
 213      /**
 214       * Method to set the current page
 215       *
 216       * @param object $page Current page
 217       */
 218      function set_page($page) {
 219          global $PAGE;
 220  
 221          $this->page = $page;
 222          $this->title = $page->title;
 223          // set_title calls format_string itself so no probs there
 224          $PAGE->set_title($this->title);
 225      }
 226  
 227      /**
 228       * Method to set the current page title.
 229       * This method must be called when the current page is not created yet.
 230       * @param string $title Current page title.
 231       */
 232      function set_title($title) {
 233          global $PAGE;
 234  
 235          $this->page = null;
 236          $this->title = $title;
 237          // set_title calls format_string itself so no probs there
 238          $PAGE->set_title($this->title);
 239      }
 240  
 241      /**
 242       * Method to set current group id
 243       * @param int $gid Current group id
 244       */
 245      function set_gid($gid) {
 246          $this->gid = $gid;
 247      }
 248  
 249      /**
 250       * Method to set current user id
 251       * @param int $uid Current user id
 252       */
 253      function set_uid($uid) {
 254          $this->uid = $uid;
 255      }
 256  
 257      /**
 258       * Method to set the URL of the page.
 259       * This method must be overwritten by every type of page.
 260       */
 261      protected function set_url() {
 262          throw new coding_exception('Page wiki class does not implement method set_url()');
 263      }
 264  
 265      /**
 266       * Protected method to create the common items of the navbar in every page type.
 267       */
 268      protected function create_navbar() {
 269          global $PAGE, $CFG;
 270  
 271          $PAGE->navbar->add(format_string($this->title), $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $this->page->id);
 272      }
 273  
 274      /**
 275       * This method print the footer of the page.
 276       */
 277      function print_footer() {
 278          global $OUTPUT;
 279          echo $OUTPUT->footer();
 280      }
 281  
 282      protected function process_session_url() {
 283          global $USER, $SESSION;
 284  
 285          //delete locks if edit
 286          $url = $SESSION->wikipreviousurl;
 287          switch ($url['page']) {
 288          case 'edit':
 289              wiki_delete_locks($url['params']['pageid'], $USER->id, $url['params']['section'], false);
 290              break;
 291          }
 292      }
 293  
 294      protected function set_session_url() {
 295          global $SESSION;
 296          unset($SESSION->wikipreviousurl);
 297      }
 298  
 299  }
 300  
 301  /**
 302   * View a wiki page
 303   *
 304   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 305   */
 306  class page_wiki_view extends page_wiki {
 307  
 308      function print_header() {
 309          global $PAGE;
 310  
 311          parent::print_header();
 312  
 313          $this->wikioutput->wiki_print_subwiki_selector($PAGE->activityrecord, $this->subwiki, $this->page, 'view');
 314  
 315          //echo $this->wikioutput->page_index();
 316  
 317          $this->print_pagetitle();
 318      }
 319  
 320      /**
 321       * This method returns the action bar.
 322       *
 323       * @param int $pageid The page id.
 324       * @param moodle_url $pageurl The page url.
 325       * @return string The HTML for the action bar.
 326       */
 327      protected function action_bar(int $pageid, moodle_url $pageurl): string {
 328          $actionbar = new \mod_wiki\output\action_bar($pageid, $pageurl, true);
 329          return $this->wikioutput->render_action_bar($actionbar);
 330      }
 331  
 332      function print_content() {
 333          global $PAGE, $CFG;
 334  
 335          if (wiki_user_can_view($this->subwiki)) {
 336  
 337              if (!empty($this->page)) {
 338                  wiki_print_page_content($this->page, $this->modcontext, $this->subwiki->id);
 339                  $wiki = $PAGE->activityrecord;
 340              } else {
 341                  print_string('nocontent', 'wiki');
 342                  // TODO: fix this part
 343                  $swid = 0;
 344                  if (!empty($this->subwiki)) {
 345                      $swid = $this->subwiki->id;
 346                  }
 347              }
 348          } else {
 349              echo get_string('cannotviewpage', 'wiki');
 350          }
 351      }
 352  
 353      function set_url() {
 354          global $PAGE, $CFG;
 355          $params = array();
 356  
 357          if (isset($this->cm->id)) {
 358              $params['id'] = $this->cm->id;
 359          } else if (!empty($this->page) and $this->page != null) {
 360              $params['pageid'] = $this->page->id;
 361          } else if (!empty($this->gid)) {
 362              $params['wid'] = $this->cm->instance;
 363              $params['group'] = $this->gid;
 364          } else if (!empty($this->title)) {
 365              $params['swid'] = $this->subwiki->id;
 366              $params['title'] = $this->title;
 367          } else {
 368              throw new \moodle_exception(get_string('invalidparameters', 'wiki'));
 369          }
 370          $PAGE->set_url(new moodle_url($CFG->wwwroot . '/mod/wiki/view.php', $params));
 371      }
 372  
 373      protected function create_navbar() {
 374          global $PAGE;
 375  
 376          $PAGE->navbar->add(format_string($this->title));
 377          $PAGE->navbar->add(get_string('view', 'wiki'));
 378      }
 379  }
 380  
 381  /**
 382   * Wiki page editing page
 383   *
 384   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 385   */
 386  class page_wiki_edit extends page_wiki {
 387  
 388      public static $attachmentoptions;
 389  
 390      protected $sectioncontent;
 391      /** @var string the section name needed to be edited */
 392      protected $section;
 393      protected $overridelock = false;
 394      protected $versionnumber = -1;
 395      protected $upload = false;
 396      protected $attachments = 0;
 397      protected $deleteuploads = array();
 398      protected $format;
 399  
 400      /**
 401       * The page_wiki_edit constructor.
 402       *
 403       * @param stdClass $wiki Current wiki
 404       * @param stdClass $subwiki Current subwiki.
 405       * @param stdClass $cm Current course_module.
 406       * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
 407       */
 408      public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
 409          global $CFG, $PAGE;
 410          parent::__construct($wiki, $subwiki, $cm, $activesecondarytab);
 411          $showfilemanager = false;
 412          if (has_capability('mod/wiki:managefiles', context_module::instance($cm->id))) {
 413              $showfilemanager = true;
 414          }
 415          self::$attachmentoptions = array('subdirs' => false, 'maxfiles' => - 1, 'maxbytes' => $CFG->maxbytes,
 416                  'accepted_types' => '*', 'enable_filemanagement' => $showfilemanager);
 417          $PAGE->requires->js_init_call('M.mod_wiki.renew_lock', null, true);
 418      }
 419  
 420      protected function print_pagetitle() {
 421          global $OUTPUT;
 422  
 423          $title = $this->title;
 424          if (isset($this->section)) {
 425              $title .= ' : ' . $this->section;
 426          }
 427          echo $OUTPUT->container_start('wiki_clear wiki_headingtitle');
 428          echo $OUTPUT->heading(format_string($title), 3);
 429          echo $OUTPUT->container_end();
 430      }
 431  
 432      function print_header() {
 433          global $OUTPUT, $PAGE;
 434          $PAGE->requires->data_for_js('wiki', array('renew_lock_timeout' => LOCK_TIMEOUT - 5, 'pageid' => $this->page->id, 'section' => $this->section));
 435  
 436          parent::print_header();
 437  
 438          $this->print_pagetitle();
 439  
 440          print '<noscript>' . $OUTPUT->box(get_string('javascriptdisabledlocks', 'wiki'), 'errorbox') . '</noscript>';
 441      }
 442  
 443      function print_content() {
 444          global $PAGE;
 445  
 446          if (wiki_user_can_edit($this->subwiki)) {
 447              $this->print_edit();
 448          } else {
 449              echo get_string('cannoteditpage', 'wiki');
 450          }
 451      }
 452  
 453      protected function set_url() {
 454          global $PAGE, $CFG;
 455  
 456          $params = array('pageid' => $this->page->id);
 457  
 458          if (isset($this->section)) {
 459              $params['section'] = $this->section;
 460          }
 461  
 462          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/edit.php', $params);
 463      }
 464  
 465      protected function set_session_url() {
 466          global $SESSION;
 467  
 468          $SESSION->wikipreviousurl = array('page' => 'edit', 'params' => array('pageid' => $this->page->id, 'section' => $this->section));
 469      }
 470  
 471      protected function process_session_url() {
 472      }
 473  
 474      function set_section($sectioncontent, $section) {
 475          $this->sectioncontent = $sectioncontent;
 476          $this->section = $section;
 477      }
 478  
 479      public function set_versionnumber($versionnumber) {
 480          $this->versionnumber = $versionnumber;
 481      }
 482  
 483      public function set_overridelock($override) {
 484          $this->overridelock = $override;
 485      }
 486  
 487      function set_format($format) {
 488          $this->format = $format;
 489      }
 490  
 491      public function set_upload($upload) {
 492          $this->upload = $upload;
 493      }
 494  
 495      public function set_attachments($attachments) {
 496          $this->attachments = $attachments;
 497      }
 498  
 499      public function set_deleteuploads($deleteuploads) {
 500          $this->deleteuploads = $deleteuploads;
 501      }
 502  
 503      protected function create_navbar() {
 504          global $PAGE, $CFG;
 505  
 506          parent::create_navbar();
 507  
 508          $PAGE->navbar->add(get_string('edit', 'wiki'));
 509      }
 510  
 511      protected function check_locks() {
 512          global $OUTPUT, $USER, $CFG;
 513  
 514          if (!wiki_set_lock($this->page->id, $USER->id, $this->section, true)) {
 515              print $OUTPUT->box(get_string('pageislocked', 'wiki'), 'generalbox boxwidthnormal boxaligncenter');
 516  
 517              if ($this->overridelock) {
 518                  $params = 'pageid=' . $this->page->id;
 519  
 520                  if ($this->section) {
 521                      $params .= '&section=' . urlencode($this->section);
 522                  }
 523  
 524                  $form = '<form method="post" action="' . $CFG->wwwroot . '/mod/wiki/overridelocks.php?' . $params . '">';
 525                  $form .= '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
 526                  $form .= '<input type="submit" class="btn btn-secondary" value="' . get_string('overridelocks', 'wiki') . '" />';
 527                  $form .= '</form>';
 528  
 529                  print $OUTPUT->box($form, 'generalbox boxwidthnormal boxaligncenter');
 530              }
 531              return false;
 532          }
 533          return true;
 534      }
 535  
 536      protected function print_edit($content = null) {
 537          global $CFG, $OUTPUT, $USER, $PAGE;
 538  
 539          if (!$this->check_locks()) {
 540              return;
 541          }
 542  
 543          //delete old locks (> 1 hour)
 544          wiki_delete_old_locks();
 545  
 546          $version = wiki_get_current_version($this->page->id);
 547          $format = $version->contentformat;
 548  
 549          if ($content == null) {
 550              if (empty($this->section)) {
 551                  $content = $version->content;
 552              } else {
 553                  $content = $this->sectioncontent;
 554              }
 555          }
 556  
 557          $versionnumber = $version->version;
 558          if ($this->versionnumber >= 0) {
 559              if ($version->version != $this->versionnumber) {
 560                  print $OUTPUT->box(get_string('wrongversionlock', 'wiki'), 'errorbox');
 561                  $versionnumber = $this->versionnumber;
 562              }
 563          }
 564  
 565          $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
 566          if (!empty($this->section)) {
 567              $url .= "&section=" . urlencode($this->section);
 568          }
 569  
 570          $params = array(
 571              'attachmentoptions' => page_wiki_edit::$attachmentoptions,
 572              'format' => $version->contentformat,
 573              'version' => $versionnumber,
 574              'pagetitle' => $this->page->title,
 575              'contextid' => $this->modcontext->id
 576          );
 577  
 578          $data = new StdClass();
 579          $data->newcontent = $content;
 580          $data->version = $versionnumber;
 581          $data->format = $format;
 582  
 583          switch ($format) {
 584          case 'html':
 585              $data->newcontentformat = FORMAT_HTML;
 586              // Append editor context to editor options, giving preference to existing context.
 587              page_wiki_edit::$attachmentoptions = array_merge(array('context' => $this->modcontext), page_wiki_edit::$attachmentoptions);
 588              $data = file_prepare_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id);
 589              break;
 590          default:
 591              break;
 592          }
 593  
 594          if ($version->contentformat != 'html') {
 595              $params['fileitemid'] = $this->subwiki->id;
 596              $params['component']  = 'mod_wiki';
 597              $params['filearea']   = 'attachments';
 598          }
 599  
 600          $data->tags = core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $this->page->id);
 601  
 602          $form = new mod_wiki_edit_form($url, $params);
 603          $form->set_data($data);
 604          $form->display();
 605      }
 606  
 607  }
 608  
 609  /**
 610   * Class that models the behavior of wiki's view comments page
 611   *
 612   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 613   */
 614  class page_wiki_comments extends page_wiki {
 615  
 616      function print_header() {
 617  
 618          parent::print_header();
 619  
 620          $this->print_pagetitle();
 621  
 622      }
 623  
 624      function print_content() {
 625          global $CFG, $OUTPUT, $USER, $PAGE;
 626          require_once($CFG->dirroot . '/mod/wiki/locallib.php');
 627  
 628          $page = $this->page;
 629          $subwiki = $this->subwiki;
 630          $wiki = $PAGE->activityrecord;
 631          list($context, $course, $cm) = get_context_info_array($this->modcontext->id);
 632  
 633          require_capability('mod/wiki:viewcomment', $this->modcontext, NULL, true, 'noviewcommentpermission', 'wiki');
 634  
 635          $comments = wiki_get_comments($this->modcontext->id, $page->id);
 636  
 637          if (has_capability('mod/wiki:editcomment', $this->modcontext)) {
 638              echo '<div class="midpad"><a href="' . $CFG->wwwroot . '/mod/wiki/editcomments.php?action=add&amp;pageid=' . $page->id . '">' . get_string('addcomment', 'wiki') . '</a></div>';
 639          }
 640  
 641          $options = array('swid' => $this->page->subwikiid, 'pageid' => $page->id);
 642          $version = wiki_get_current_version($this->page->id);
 643          $format = $version->contentformat;
 644  
 645          if (empty($comments)) {
 646              echo html_writer::tag('p', get_string('nocomments', 'wiki'), array('class' => 'bold'));
 647          }
 648  
 649          foreach ($comments as $comment) {
 650  
 651              $user = wiki_get_user_info($comment->userid);
 652  
 653              $fullname = fullname($user, has_capability('moodle/site:viewfullnames', context_course::instance($course->id)));
 654              $by = new stdclass();
 655              $by->name = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $user->id . '&amp;course=' . $course->id . '">' . $fullname . '</a>';
 656              $by->date = userdate($comment->timecreated);
 657  
 658              $t = new html_table();
 659              $t->id = 'wiki-comments';
 660              $cell1 = new html_table_cell($OUTPUT->user_picture($user, array('popup' => true)));
 661              $cell2 = new html_table_cell(get_string('bynameondate', 'forum', $by));
 662              $cell3 = new html_table_cell();
 663              $cell4 = new html_table_cell();
 664              $cell5 = new html_table_cell();
 665  
 666              $row1 = new html_table_row();
 667              $row1->cells[] = $cell1;
 668              $row1->cells[] = $cell2;
 669              $row2 = new html_table_row();
 670              $row2->cells[] = $cell3;
 671  
 672              if ($format != 'html') {
 673                  if ($format == 'creole') {
 674                      $parsedcontent = wiki_parse_content('creole', $comment->content, $options);
 675                  } else if ($format == 'nwiki') {
 676                      $parsedcontent = wiki_parse_content('nwiki', $comment->content, $options);
 677                  }
 678  
 679                  $cell4->text = format_text(html_entity_decode($parsedcontent['parsed_text'], ENT_QUOTES, 'UTF-8'), FORMAT_HTML);
 680              } else {
 681                  $cell4->text = format_text($comment->content, FORMAT_HTML);
 682              }
 683  
 684              $row2->cells[] = $cell4;
 685  
 686              $t->data = array($row1, $row2);
 687  
 688              $canedit = $candelete = false;
 689              if ((has_capability('mod/wiki:editcomment', $this->modcontext)) and ($USER->id == $user->id)) {
 690                  $candelete = $canedit = true;
 691              }
 692              if ((has_capability('mod/wiki:managecomment', $this->modcontext))) {
 693                  $candelete = true;
 694              }
 695  
 696              $editicon = $deleteicon = '';
 697              if ($canedit) {
 698                  $urledit = new moodle_url('/mod/wiki/editcomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'edit'));
 699                  $editicon = $OUTPUT->action_icon($urledit, new pix_icon('t/edit', get_string('edit'), '', array('class' => 'iconsmall')));
 700              }
 701              if ($candelete) {
 702                  $urldelete = new moodle_url('/mod/wiki/instancecomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'delete'));
 703                  $deleteicon = $OUTPUT->action_icon($urldelete,
 704                                                    new pix_icon('t/delete',
 705                                                                 get_string('delete'),
 706                                                                 '',
 707                                                                 array('class' => 'iconsmall')));
 708              }
 709  
 710              if ($candelete || $canedit) {
 711                  $cell6 = new html_table_cell($editicon.$deleteicon);
 712                  $row3 = new html_table_row();
 713                  $row3->cells[] = $cell5;
 714                  $row3->cells[] = $cell6;
 715                  $t->data[] = $row3;
 716              }
 717  
 718              echo html_writer::tag('div', html_writer::table($t), array('class'=>'no-overflow'));
 719  
 720          }
 721      }
 722  
 723      function set_url() {
 724          global $PAGE, $CFG;
 725          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
 726      }
 727  
 728      protected function create_navbar() {
 729          global $PAGE, $CFG;
 730  
 731          parent::create_navbar();
 732          $PAGE->navbar->add(get_string('comments', 'wiki'));
 733      }
 734  
 735  }
 736  
 737  /**
 738   * Class that models the behavior of wiki's edit comment
 739   *
 740   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 741   */
 742  class page_wiki_editcomment extends page_wiki {
 743      private $comment;
 744      private $action;
 745      private $form;
 746      private $format;
 747  
 748      function set_url() {
 749          global $PAGE, $CFG;
 750          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
 751      }
 752  
 753      function print_header() {
 754          parent::print_header();
 755          $this->print_pagetitle();
 756      }
 757  
 758      function print_content() {
 759          global $PAGE;
 760  
 761          require_capability('mod/wiki:editcomment', $this->modcontext, NULL, true, 'noeditcommentpermission', 'wiki');
 762  
 763          if ($this->action == 'add') {
 764              $this->add_comment_form();
 765          } else if ($this->action == 'edit') {
 766              $this->edit_comment_form($this->comment);
 767          }
 768      }
 769  
 770      function set_action($action, $comment) {
 771          global $CFG;
 772          require_once($CFG->dirroot . '/mod/wiki/comments_form.php');
 773  
 774          $this->action = $action;
 775          $this->comment = $comment;
 776          $version = wiki_get_current_version($this->page->id);
 777          $this->format = $version->contentformat;
 778  
 779          if ($this->format == 'html') {
 780              $destination = $CFG->wwwroot . '/mod/wiki/instancecomments.php?pageid=' . $this->page->id;
 781              $this->form = new mod_wiki_comments_form($destination);
 782          }
 783      }
 784  
 785      protected function create_navbar() {
 786          global $PAGE, $CFG;
 787  
 788          $PAGE->navbar->add(get_string('comments', 'wiki'), $CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $this->page->id);
 789  
 790          if ($this->action == 'add') {
 791              $PAGE->navbar->add(get_string('insertcomment', 'wiki'));
 792          } else {
 793              $PAGE->navbar->add(get_string('editcomment', 'wiki'));
 794          }
 795      }
 796  
 797      protected function setup_tabs($options = array()) {
 798          parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
 799      }
 800  
 801      /**
 802       * This method returns the action bar.
 803       *
 804       * @param int $pageid The page id.
 805       * @param moodle_url $pageurl The page url.
 806       * @return string The HTML for the action bar.
 807       */
 808      protected function action_bar(int $pageid, moodle_url $pageurl): string {
 809          // The given page does not require an action bar.
 810          return '';
 811      }
 812  
 813      private function add_comment_form() {
 814          global $CFG;
 815          require_once($CFG->dirroot . '/mod/wiki/editors/wiki_editor.php');
 816  
 817          $pageid = $this->page->id;
 818  
 819          if ($this->format == 'html') {
 820              $com = new stdClass();
 821              $com->action = 'add';
 822              $com->commentoptions = array('trusttext' => true, 'maxfiles' => 0);
 823              $this->form->set_data($com);
 824              $this->form->display();
 825          } else {
 826              wiki_print_editor_wiki($this->page->id, null, $this->format, -1, null, false, null, 'addcomments');
 827          }
 828      }
 829  
 830      private function edit_comment_form($com) {
 831          global $CFG;
 832          require_once($CFG->dirroot . '/mod/wiki/comments_form.php');
 833          require_once($CFG->dirroot . '/mod/wiki/editors/wiki_editor.php');
 834  
 835          if ($this->format == 'html') {
 836              $com->action = 'edit';
 837              $com->entrycomment_editor['text'] = clean_text($com->content, $this->format);
 838              $com->commentoptions = array('trusttext' => true, 'maxfiles' => 0);
 839  
 840              $this->form->set_data($com);
 841              $this->form->display();
 842          } else {
 843              wiki_print_editor_wiki($this->page->id, $com->content, $this->format, -1, null, false, array(), 'editcomments', $com->id);
 844          }
 845  
 846      }
 847  
 848  }
 849  
 850  /**
 851   * Wiki page search page
 852   *
 853   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 854   */
 855  class page_wiki_search extends page_wiki {
 856      private $search_result;
 857  
 858      protected function create_navbar() {
 859          global $PAGE, $CFG;
 860  
 861          $PAGE->navbar->add(format_string($this->title));
 862      }
 863  
 864      function set_search_string($search, $searchcontent) {
 865          $swid = $this->subwiki->id;
 866          if ($searchcontent) {
 867              $this->search_result = wiki_search_all($swid, $search);
 868          } else {
 869              $this->search_result = wiki_search_title($swid, $search);
 870          }
 871  
 872      }
 873  
 874      function set_url() {
 875          global $PAGE, $CFG;
 876          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/search.php');
 877      }
 878  
 879      function print_header() {
 880          global $PAGE;
 881  
 882          parent::print_header();
 883  
 884          $wiki = $PAGE->activityrecord;
 885          $page = (object)array('title' => $wiki->firstpagetitle);
 886          $this->wikioutput->wiki_print_subwiki_selector($wiki, $this->subwiki, $page, 'search');
 887      }
 888  
 889      function print_content() {
 890          global $PAGE;
 891  
 892          require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
 893  
 894          echo $this->wikioutput->search_result($this->search_result, $this->subwiki);
 895      }
 896  }
 897  
 898  /**
 899   *
 900   * Class that models the behavior of wiki's
 901   * create page
 902   *
 903   */
 904  class page_wiki_create extends page_wiki {
 905  
 906      private $format;
 907      private $swid;
 908      private $wid;
 909      private $action;
 910      private $mform;
 911      private $groups;
 912  
 913      function print_header() {
 914          $this->set_url();
 915          parent::print_header();
 916      }
 917  
 918      function set_url() {
 919          global $PAGE, $CFG;
 920  
 921          $params = array();
 922          $params['swid'] = $this->swid;
 923          if ($this->action == 'new') {
 924              $params['action'] = 'new';
 925              $params['wid'] = $this->wid;
 926              if ($this->title != get_string('newpage', 'wiki')) {
 927                  $params['title'] = $this->title;
 928              }
 929          } else {
 930              $params['action'] = 'create';
 931          }
 932          $PAGE->set_url(new moodle_url('/mod/wiki/create.php', $params));
 933      }
 934  
 935      function set_format($format) {
 936          $this->format = $format;
 937      }
 938  
 939      function set_wid($wid) {
 940          $this->wid = $wid;
 941      }
 942  
 943      function set_swid($swid) {
 944          $this->swid = $swid;
 945      }
 946  
 947      function set_availablegroups($group) {
 948          $this->groups = $group;
 949      }
 950  
 951      function set_action($action) {
 952          global $PAGE;
 953          $this->action = $action;
 954  
 955          require_once (__DIR__ . '/create_form.php');
 956          $url = new moodle_url('/mod/wiki/create.php', array('action' => 'create', 'wid' => $PAGE->activityrecord->id, 'group' => $this->gid, 'uid' => $this->uid));
 957          $formats = wiki_get_formats();
 958          $options = array('formats' => $formats, 'defaultformat' => $PAGE->activityrecord->defaultformat, 'forceformat' => $PAGE->activityrecord->forceformat, 'groups' => $this->groups);
 959          if ($this->title != get_string('newpage', 'wiki')) {
 960              $options['disable_pagetitle'] = true;
 961          }
 962          $this->mform = new mod_wiki_create_form($url->out(false), $options);
 963      }
 964  
 965      protected function create_navbar() {
 966          global $PAGE;
 967          // navigation_node::get_content formats this before printing.
 968          $PAGE->navbar->add($this->title);
 969      }
 970  
 971      function print_content($pagetitle = '') {
 972          global $PAGE;
 973  
 974          // @TODO: Change this to has_capability and show an alternative interface.
 975          require_capability('mod/wiki:createpage', $this->modcontext, NULL, true, 'nocreatepermission', 'wiki');
 976          $data = new stdClass();
 977          if (!empty($pagetitle)) {
 978              $data->pagetitle = $pagetitle;
 979          }
 980          $data->pageformat = $PAGE->activityrecord->defaultformat;
 981  
 982          $this->mform->set_data($data);
 983          $this->mform->display();
 984      }
 985  
 986      function create_page($pagetitle) {
 987          global $USER, $PAGE;
 988  
 989          $data = $this->mform->get_data();
 990          if (isset($data->groupinfo)) {
 991              $groupid = $data->groupinfo;
 992          } else if (!empty($this->gid)) {
 993              $groupid = $this->gid;
 994          } else {
 995              $groupid = '0';
 996          }
 997          if (empty($this->subwiki)) {
 998              // If subwiki is not set then try find one and set else create one.
 999              if (!$this->subwiki = wiki_get_subwiki_by_group($this->wid, $groupid, $this->uid)) {
1000                  $swid = wiki_add_subwiki($PAGE->activityrecord->id, $groupid, $this->uid);
1001                  $this->subwiki = wiki_get_subwiki($swid);
1002              }
1003          }
1004          if ($data) {
1005              $this->set_title($data->pagetitle);
1006              $id = wiki_create_page($this->subwiki->id, $data->pagetitle, $data->pageformat, $USER->id);
1007          } else {
1008              $this->set_title($pagetitle);
1009              $id = wiki_create_page($this->subwiki->id, $pagetitle, $PAGE->activityrecord->defaultformat, $USER->id);
1010          }
1011          $this->page = $id;
1012          return $id;
1013      }
1014  }
1015  
1016  class page_wiki_preview extends page_wiki_edit {
1017  
1018      private $newcontent;
1019  
1020      function print_header() {
1021          global $PAGE, $CFG;
1022  
1023          parent::print_header();
1024  
1025      }
1026  
1027      function print_content() {
1028          global $PAGE;
1029  
1030          require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki');
1031  
1032          $this->print_preview();
1033      }
1034  
1035      function set_newcontent($newcontent) {
1036          $this->newcontent = $newcontent;
1037      }
1038  
1039      function set_url() {
1040          global $PAGE, $CFG;
1041  
1042          $params = array('pageid' => $this->page->id
1043          );
1044  
1045          if (isset($this->section)) {
1046              $params['section'] = $this->section;
1047          }
1048  
1049          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/edit.php', $params);
1050      }
1051  
1052      protected function setup_tabs($options = array()) {
1053          parent::setup_tabs(array('linkedwhenactive' => 'view', 'activetab' => 'view'));
1054      }
1055  
1056      protected function check_locks() {
1057          return true;
1058      }
1059  
1060      protected function print_preview() {
1061          global $CFG, $PAGE, $OUTPUT;
1062  
1063          $version = wiki_get_current_version($this->page->id);
1064          $format = $version->contentformat;
1065          $content = $version->content;
1066  
1067          $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
1068          if (!empty($this->section)) {
1069              $url .= "&section=" . urlencode($this->section);
1070          }
1071          $params = array(
1072              'attachmentoptions' => page_wiki_edit::$attachmentoptions,
1073              'format' => $this->format,
1074              'version' => $this->versionnumber,
1075              'contextid' => $this->modcontext->id
1076          );
1077  
1078          if ($this->format != 'html') {
1079              $params['component'] = 'mod_wiki';
1080              $params['filearea'] = 'attachments';
1081              $params['fileitemid'] = $this->page->id;
1082          }
1083          $form = new mod_wiki_edit_form($url, $params);
1084  
1085  
1086          $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true);
1087  
1088          if ($data = $form->get_data()) {
1089              if (isset($data->newcontent)) {
1090                  // wiki fromat
1091                  $text = $data->newcontent;
1092              } else {
1093                  // html format
1094                  $text = $data->newcontent_editor['text'];
1095              }
1096              $parseroutput = wiki_parse_content($data->contentformat, $text, $options);
1097              $this->set_newcontent($text);
1098              echo $OUTPUT->notification(get_string('previewwarning', 'wiki'), 'notifyproblem');
1099              $content = format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true, 'filter'=>false));
1100              echo $OUTPUT->box($content, 'generalbox wiki_previewbox');
1101              $content = $this->newcontent;
1102          }
1103  
1104          $this->print_edit($content);
1105      }
1106  
1107  }
1108  
1109  /**
1110   *
1111   * Class that models the behavior of wiki's
1112   * view differences
1113   *
1114   */
1115  class page_wiki_diff extends page_wiki {
1116  
1117      private $compare;
1118      private $comparewith;
1119  
1120      function print_header() {
1121          global $OUTPUT;
1122  
1123          parent::print_header();
1124  
1125          $this->print_pagetitle();
1126          $vstring = new stdClass();
1127          $vstring->old = $this->compare;
1128          $vstring->new = $this->comparewith;
1129          echo html_writer::tag('div', get_string('comparewith', 'wiki', $vstring), array('class' => 'wiki_headingtitle'));
1130      }
1131  
1132      /**
1133       * Print the diff view
1134       */
1135      function print_content() {
1136          global $PAGE;
1137  
1138          require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1139  
1140          $this->print_diff_content();
1141      }
1142  
1143      function set_url() {
1144          global $PAGE, $CFG;
1145  
1146          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/diff.php', array('pageid' => $this->page->id, 'comparewith' => $this->comparewith, 'compare' => $this->compare));
1147      }
1148  
1149      function set_comparison($compare, $comparewith) {
1150          $this->compare = $compare;
1151          $this->comparewith = $comparewith;
1152      }
1153  
1154      protected function create_navbar() {
1155          global $PAGE, $CFG;
1156  
1157          parent::create_navbar();
1158          $PAGE->navbar->add(get_string('history', 'wiki'), $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $this->page->id);
1159          $PAGE->navbar->add(get_string('diff', 'wiki'));
1160      }
1161  
1162      protected function setup_tabs($options = array()) {
1163          parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history'));
1164      }
1165  
1166      /**
1167       * This method returns the action bar.
1168       *
1169       * @param int $pageid The page id.
1170       * @param moodle_url $pageurl The page url.
1171       * @return string The HTML for the action bar.
1172       */
1173      protected function action_bar(int $pageid, moodle_url $pageurl): string {
1174          $backlink = new moodle_url('/mod/wiki/history.php', ['pageid' => $pageid]);
1175          return html_writer::link($backlink, get_string('back'), ['class' => 'btn btn-secondary mb-4']);
1176      }
1177  
1178      /**
1179       * Given two versions of a page, prints a page displaying the differences between them.
1180       *
1181       * @global object $CFG
1182       * @global object $OUTPUT
1183       * @global object $PAGE
1184       */
1185      private function print_diff_content() {
1186          global $CFG, $OUTPUT, $PAGE;
1187  
1188          $pageid = $this->page->id;
1189          $total = wiki_count_wiki_page_versions($pageid) - 1;
1190  
1191          $oldversion = wiki_get_wiki_page_version($pageid, $this->compare);
1192  
1193          $newversion = wiki_get_wiki_page_version($pageid, $this->comparewith);
1194  
1195          if ($oldversion && $newversion) {
1196  
1197              $oldtext = format_text(file_rewrite_pluginfile_urls($oldversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id));
1198              $newtext = format_text(file_rewrite_pluginfile_urls($newversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id));
1199              list($diff1, $diff2) = ouwiki_diff_html($oldtext, $newtext);
1200              $oldversion->diff = $diff1;
1201              $oldversion->user = wiki_get_user_info($oldversion->userid);
1202              $newversion->diff = $diff2;
1203              $newversion->user = wiki_get_user_info($newversion->userid);
1204  
1205              echo $this->wikioutput->diff($pageid, $oldversion, $newversion, array('total' => $total));
1206          } else {
1207              throw new \moodle_exception('versionerror', 'wiki');
1208          }
1209      }
1210  }
1211  
1212  /**
1213   *
1214   * Class that models the behavior of wiki's history page
1215   *
1216   */
1217  class page_wiki_history extends page_wiki {
1218      /**
1219       * @var int $paging current page
1220       */
1221      private $paging;
1222  
1223      /**
1224       * @var int @rowsperpage Items per page
1225       */
1226      private $rowsperpage = 10;
1227  
1228      /**
1229       * @var int $allversion if $allversion != 0, all versions will be printed in a signle table
1230       */
1231      private $allversion;
1232  
1233      /**
1234       * The page_wiki_history constructor.
1235       *
1236       * @param stdClass $wiki Current wiki.
1237       * @param stdClass $subwiki Current subwiki.
1238       * @param stdClass $cm Current course_module.
1239       * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
1240       */
1241      public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
1242          global $PAGE;
1243          parent::__construct($wiki, $subwiki, $cm, $activesecondarytab);
1244          $PAGE->requires->js_init_call('M.mod_wiki.history', null, true);
1245      }
1246  
1247      function print_header() {
1248          parent::print_header();
1249          $this->print_pagetitle();
1250      }
1251  
1252      function print_pagetitle() {
1253          global $OUTPUT;
1254          $html = '';
1255  
1256          $html .= $OUTPUT->container_start('wiki_headingtitle');
1257          $html .= $OUTPUT->heading_with_help(format_string($this->title), 'history', 'wiki', '', '', 3);
1258          $html .= $OUTPUT->container_end();
1259          echo $html;
1260      }
1261  
1262      function print_content() {
1263          global $PAGE;
1264  
1265          require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1266  
1267          $this->print_history_content();
1268      }
1269  
1270      function set_url() {
1271          global $PAGE, $CFG;
1272          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/history.php', array('pageid' => $this->page->id));
1273      }
1274  
1275      function set_paging($paging) {
1276          $this->paging = $paging;
1277      }
1278  
1279      function set_allversion($allversion) {
1280          $this->allversion = $allversion;
1281      }
1282  
1283      protected function create_navbar() {
1284          global $PAGE, $CFG;
1285  
1286          parent::create_navbar();
1287          $PAGE->navbar->add(get_string('history', 'wiki'));
1288      }
1289  
1290      /**
1291       * Prints the history for a given wiki page
1292       *
1293       * @global object $CFG
1294       * @global object $OUTPUT
1295       * @global object $PAGE
1296       */
1297      private function print_history_content() {
1298          global $CFG, $OUTPUT, $PAGE;
1299  
1300          $pageid = $this->page->id;
1301          $offset = $this->paging * $this->rowsperpage;
1302          // vcount is the latest version
1303          $vcount = wiki_count_wiki_page_versions($pageid) - 1;
1304          if ($this->allversion) {
1305              $versions = wiki_get_wiki_page_versions($pageid, 0, $vcount);
1306          } else {
1307              $versions = wiki_get_wiki_page_versions($pageid, $offset, $this->rowsperpage);
1308          }
1309          // We don't want version 0 to be displayed
1310          // version 0 is blank page
1311          if (end($versions)->version == 0) {
1312              array_pop($versions);
1313          }
1314  
1315          $contents = array();
1316  
1317          $version0page = wiki_get_wiki_page_version($this->page->id, 0);
1318          $creator = wiki_get_user_info($version0page->userid);
1319          $a = new StdClass;
1320          $a->date = userdate($this->page->timecreated, get_string('strftimedaydatetime', 'langconfig'));
1321          $a->username = fullname($creator);
1322          echo html_writer::tag ('div', get_string('createddate', 'wiki', $a), array('class' => 'wiki_headingtime'));
1323          if ($vcount > 0) {
1324  
1325              /// If there is only one version, we don't need radios nor forms
1326              if (count($versions) == 1) {
1327  
1328                  $row = array_shift($versions);
1329  
1330                  $username = wiki_get_user_info($row->userid);
1331                  $picture = $OUTPUT->user_picture($username);
1332                  $date = userdate($row->timecreated, get_string('strftimedate', 'langconfig'));
1333                  $time = userdate($row->timecreated, get_string('strftimetime', 'langconfig'));
1334                  $versionid = wiki_get_version($row->id);
1335                  $versionlink = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
1336                  $userlink = new moodle_url('/user/view.php', array('id' => $username->id, 'course' => $this->cm->course));
1337                  $contents[] = array('', html_writer::link($versionlink->out(false), $row->version), $picture . html_writer::link($userlink->out(false), fullname($username)), $time, $OUTPUT->container($date, 'wiki_histdate'));
1338  
1339                  $table = new html_table();
1340                  $table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
1341                  $table->data = $contents;
1342  
1343                  echo html_writer::table($table);
1344  
1345              } else {
1346  
1347                  $checked = $vcount - $offset;
1348                  $rowclass = array();
1349  
1350                  foreach ($versions as $version) {
1351                      $user = wiki_get_user_info($version->userid);
1352                      $picture = $OUTPUT->user_picture($user, array('popup' => true));
1353                      $date = userdate($version->timecreated, get_string('strftimedate'));
1354                      $rowclass[] = 'wiki_histnewdate';
1355                      $time = userdate($version->timecreated, get_string('strftimetime', 'langconfig'));
1356                      $versionid = wiki_get_version($version->id);
1357                      if ($versionid) {
1358                          $url = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
1359                          $viewlink = html_writer::link($url->out(false), $version->version);
1360                      } else {
1361                          $viewlink = $version->version;
1362                      }
1363                      $userlink = new moodle_url('/user/view.php', array('id' => $version->userid, 'course' => $this->cm->course));
1364                      $contents[] = array($this->choose_from_radio(array($version->version  => null), 'compare', 'M.mod_wiki.history()', $checked - 1, true) . $this->choose_from_radio(array($version->version  => null), 'comparewith', 'M.mod_wiki.history()', $checked, true), $viewlink, $picture . html_writer::link($userlink->out(false), fullname($user)), $time, $OUTPUT->container($date, 'wiki_histdate'));
1365                  }
1366  
1367                  $table = new html_table();
1368  
1369                  $icon = $OUTPUT->help_icon('diff', 'wiki');
1370  
1371                  $table->head = array(get_string('diff', 'wiki') . $icon, get_string('version'), get_string('user'), get_string('modified'), '');
1372                  $table->data = $contents;
1373                  $table->attributes['class'] = 'table generaltable';
1374                  $table->rowclasses = $rowclass;
1375  
1376                  // Print the form.
1377                  echo html_writer::start_tag('form', array('action'=>new moodle_url('/mod/wiki/diff.php'), 'method'=>'get', 'id'=>'diff'));
1378                  echo html_writer::tag('div', html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'pageid', 'value'=>$pageid)));
1379                  echo html_writer::table($table);
1380                  echo html_writer::start_tag('div');
1381                  echo html_writer::empty_tag('input', array('type'=>'submit', 'class'=>'wiki_form-button btn btn-secondary', 'value'=>get_string('comparesel', 'wiki')));
1382                  echo html_writer::end_tag('div');
1383                  echo html_writer::end_tag('form');
1384              }
1385          } else {
1386              print_string('nohistory', 'wiki');
1387          }
1388          if (!$this->allversion) {
1389              //$pagingbar = moodle_paging_bar::make($vcount, $this->paging, $this->rowsperpage, $CFG->wwwroot.'/mod/wiki/history.php?pageid='.$pageid.'&amp;');
1390              // $pagingbar->pagevar = $pagevar;
1391              echo $OUTPUT->paging_bar($vcount, $this->paging, $this->rowsperpage, $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $pageid . '&amp;');
1392              //print_paging_bar($vcount, $paging, $rowsperpage,$CFG->wwwroot.'/mod/wiki/history.php?pageid='.$pageid.'&amp;','paging');
1393              } else {
1394              $link = new moodle_url('/mod/wiki/history.php', array('pageid' => $pageid));
1395              $OUTPUT->container(html_writer::link($link->out(false), get_string('viewperpage', 'wiki', $this->rowsperpage)));
1396          }
1397          if ($vcount > $this->rowsperpage && !$this->allversion) {
1398              $link = new moodle_url('/mod/wiki/history.php', array('pageid' => $pageid, 'allversion' => 1));
1399              $OUTPUT->container(html_writer::link($link->out(false), get_string('viewallhistory', 'wiki')));
1400          }
1401      }
1402  
1403      /**
1404       * Given an array of values, creates a group of radio buttons to be part of a form
1405       *
1406       * @param array  $options  An array of value-label pairs for the radio group (values as keys).
1407       * @param string $name     Name of the radiogroup (unique in the form).
1408       * @param string $onclick  Function to be executed when the radios are clicked.
1409       * @param string $checked  The value that is already checked.
1410       * @param bool   $return   If true, return the HTML as a string, otherwise print it.
1411       *
1412       * @return mixed If $return is false, returns nothing, otherwise returns a string of HTML.
1413       */
1414      private function choose_from_radio($options, $name, $onclick = '', $checked = '', $return = false) {
1415  
1416          static $idcounter = 0;
1417  
1418          if (!$name) {
1419              $name = 'unnamed';
1420          }
1421  
1422          $output = '<span class="radiogroup ' . $name . "\">\n";
1423  
1424          if (!empty($options)) {
1425              $currentradio = 0;
1426              foreach ($options as $value => $label) {
1427                  $htmlid = 'auto-rb' . sprintf('%04d', ++$idcounter);
1428                  $output .= ' <span class="radioelement ' . $name . ' rb' . $currentradio . "\">";
1429                  $output .= '<input name="' . $name . '" id="' . $htmlid . '" type="radio" value="' . $value . '"';
1430                  if ($value == $checked) {
1431                      $output .= ' checked="checked"';
1432                  }
1433                  if ($onclick) {
1434                      $output .= ' onclick="' . $onclick . '"';
1435                  }
1436                  if ($label === '') {
1437                      $output .= ' /> <label for="' . $htmlid . '">' . $value . '</label></span>' . "\n";
1438                  } else {
1439                      $output .= ' /> <label for="' . $htmlid . '">' . $label . '</label></span>' . "\n";
1440                  }
1441                  $currentradio = ($currentradio + 1) % 2;
1442              }
1443          }
1444  
1445          $output .= '</span>' . "\n";
1446  
1447          if ($return) {
1448              return $output;
1449          } else {
1450              echo $output;
1451          }
1452      }
1453  }
1454  
1455  /**
1456   * Class that models the behavior of wiki's map page
1457   *
1458   */
1459  class page_wiki_map extends page_wiki {
1460  
1461      /**
1462       * @var int wiki view option
1463       */
1464      private $view;
1465  
1466      function print_header() {
1467          parent::print_header();
1468          $this->print_pagetitle();
1469      }
1470  
1471      function print_content() {
1472          global $CFG, $PAGE;
1473  
1474          require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1475  
1476          if ($this->view > 0) {
1477              //echo '<div><a href="' . $CFG->wwwroot . '/mod/wiki/map.php?pageid=' . $this->page->id . '">' . get_string('backtomapmenu', 'wiki') . '</a></div>';
1478          }
1479  
1480          switch ($this->view) {
1481          case 1:
1482              echo $this->wikioutput->menu_map($this->page->id, $this->view);
1483              $this->print_contributions_content();
1484              break;
1485          case 2:
1486              echo $this->wikioutput->menu_map($this->page->id, $this->view);
1487              $this->print_navigation_content();
1488              break;
1489          case 3:
1490              echo $this->wikioutput->menu_map($this->page->id, $this->view);
1491              $this->print_orphaned_content();
1492              break;
1493          case 4:
1494              echo $this->wikioutput->menu_map($this->page->id, $this->view);
1495              $this->print_index_content();
1496              break;
1497          case 6:
1498              echo $this->wikioutput->menu_map($this->page->id, $this->view);
1499              $this->print_updated_content();
1500              break;
1501          case 5:
1502          default:
1503              echo $this->wikioutput->menu_map($this->page->id, $this->view);
1504              $this->print_page_list_content();
1505          }
1506      }
1507  
1508      function set_view($option) {
1509          $this->view = $option;
1510      }
1511  
1512      function set_url() {
1513          global $PAGE, $CFG;
1514          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/map.php', array('pageid' => $this->page->id));
1515      }
1516  
1517      protected function create_navbar() {
1518          global $PAGE;
1519  
1520          parent::create_navbar();
1521          $PAGE->navbar->add(get_string('map', 'wiki'));
1522      }
1523  
1524      /**
1525       * Prints the contributions tab content
1526       *
1527       * @uses $OUTPUT, $USER
1528       *
1529       */
1530      private function print_contributions_content() {
1531          global $CFG, $OUTPUT, $USER;
1532          $page = $this->page;
1533  
1534          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1535              $fresh = wiki_refresh_cachedcontent($page);
1536              $page = $fresh['page'];
1537          }
1538  
1539          $swid = $this->subwiki->id;
1540  
1541          $table = new html_table();
1542          $table->head = array(get_string('contributions', 'wiki') . $OUTPUT->help_icon('contributions', 'wiki'));
1543          $table->attributes['class'] = 'generalbox table';
1544          $table->data = array();
1545          $table->rowclasses = array();
1546  
1547          $lastversions = array();
1548          $pages = array();
1549          $users = array();
1550  
1551          if ($contribs = wiki_get_contributions($swid, $USER->id)) {
1552              foreach ($contribs as $contrib) {
1553                  if (!array_key_exists($contrib->pageid, $pages)) {
1554                      $page = wiki_get_page($contrib->pageid);
1555                      $pages[$contrib->pageid] = $page;
1556                  } else {
1557                      continue;
1558                  }
1559  
1560                  if (!array_key_exists($page->id, $lastversions)) {
1561                      $version = wiki_get_last_version($page->id);
1562                      $lastversions[$page->id] = $version;
1563                  } else {
1564                      $version = $lastversions[$page->id];
1565                  }
1566  
1567                  if (!array_key_exists($version->userid, $users)) {
1568                      $user = wiki_get_user_info($version->userid);
1569                      $users[$version->userid] = $user;
1570                  } else {
1571                      $user = $users[$version->userid];
1572                  }
1573  
1574                  $link = wiki_parser_link($page->title, array('swid' => $swid));
1575                  $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1576  
1577                  $linkpage = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content'], true, array('context' => $this->modcontext)) . '</a>';
1578                  $icon = $OUTPUT->user_picture($user, array('popup' => true));
1579  
1580                  $table->data[] = array("$icon&nbsp;$linkpage");
1581              }
1582          } else {
1583              $table->data[] = array(get_string('nocontribs', 'wiki'));
1584          }
1585          echo html_writer::table($table);
1586      }
1587  
1588      /**
1589       * Prints the navigation tab content
1590       *
1591       * @uses $OUTPUT
1592       *
1593       */
1594      private function print_navigation_content() {
1595          global $OUTPUT;
1596          $page = $this->page;
1597  
1598          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1599              $fresh = wiki_refresh_cachedcontent($page);
1600              $page = $fresh['page'];
1601          }
1602  
1603          $tolinks = wiki_get_linked_to_pages($page->id);
1604          $fromlinks = wiki_get_linked_from_pages($page->id);
1605  
1606          $table = new html_table();
1607          $table->attributes['class'] = 'wiki_navigation_from table';
1608          $table->head = array(get_string('navigationfrom', 'wiki') . $OUTPUT->help_icon('navigationfrom', 'wiki') . ':');
1609          $table->data = array();
1610          $table->rowclasses = array();
1611          foreach ($fromlinks as $link) {
1612              $lpage = wiki_get_page($link->frompageid);
1613              $link = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
1614              $table->data[] = array(html_writer::link($link->out(false), format_string($lpage->title)));
1615          }
1616  
1617          $table_left = $OUTPUT->container(html_writer::table($table), 'col-md-6');
1618  
1619          $table = new html_table();
1620          $table->attributes['class'] = 'wiki_navigation_to table';
1621          $table->head = array(get_string('navigationto', 'wiki') . $OUTPUT->help_icon('navigationto', 'wiki') . ':');
1622          $table->data = array();
1623          $table->rowclasses = array();
1624          foreach ($tolinks as $link) {
1625              if ($link->tomissingpage) {
1626                  $viewlink = new moodle_url('/mod/wiki/create.php', array('swid' => $page->subwikiid, 'title' => $link->tomissingpage, 'action' => 'new'));
1627                  $table->data[] = array(html_writer::link($viewlink->out(false), format_string($link->tomissingpage), array('class' => 'wiki_newentry')));
1628              } else {
1629                  $lpage = wiki_get_page($link->topageid);
1630                  $viewlink = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
1631                  $table->data[] = array(html_writer::link($viewlink->out(false), format_string($lpage->title)));
1632              }
1633          }
1634          $table_right = $OUTPUT->container(html_writer::table($table), 'col-md-6');
1635          echo $OUTPUT->container($table_left . $table_right, 'wiki_navigation_container row');
1636      }
1637  
1638      /**
1639       * Prints the index page tab content
1640       *
1641       *
1642       */
1643      private function print_index_content() {
1644          global $OUTPUT;
1645          $page = $this->page;
1646  
1647          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1648              $fresh = wiki_refresh_cachedcontent($page);
1649              $page = $fresh['page'];
1650          }
1651  
1652          // navigation_node get_content calls format string for us
1653          $node = new navigation_node($page->title);
1654  
1655          $keys = array();
1656          $tree = array();
1657          $tree = wiki_build_tree($page, $node, $keys);
1658  
1659          $table = new html_table();
1660          $table->head = array(get_string('pageindex', 'wiki') . $OUTPUT->help_icon('pageindex', 'wiki'));
1661          $table->attributes['class'] = 'generalbox table';
1662          $table->data[] = array($this->render_navigation_node($tree));
1663  
1664          echo html_writer::table($table);
1665      }
1666  
1667      /**
1668       * Prints the page list tab content
1669       *
1670       *
1671       */
1672      private function print_page_list_content() {
1673          global $OUTPUT;
1674          $page = $this->page;
1675  
1676          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1677              $fresh = wiki_refresh_cachedcontent($page);
1678              $page = $fresh['page'];
1679          }
1680  
1681          $pages = wiki_get_page_list($this->subwiki->id);
1682  
1683          $stdaux = new stdClass();
1684          $strspecial = get_string('special', 'wiki');
1685  
1686          foreach ($pages as $page) {
1687              // We need to format the title here to account for any filtering
1688              $letter = format_string($page->title, true, array('context' => $this->modcontext));
1689              $letter = core_text::substr($letter, 0, 1);
1690              if (preg_match('/^[a-zA-Z]$/', $letter)) {
1691                  $letter = core_text::strtoupper($letter);
1692                  $stdaux->{$letter}[] = wiki_parser_link($page);
1693              } else {
1694                  $stdaux->{$strspecial}[] = wiki_parser_link($page);
1695              }
1696          }
1697  
1698          $table = new html_table();
1699          $table->head = array(get_string('pagelist', 'wiki') . $OUTPUT->help_icon('pagelist', 'wiki'));
1700          $table->attributes['class'] = 'generalbox table';
1701          foreach ($stdaux as $key => $elem) {
1702              $table->data[] = array($key);
1703              foreach ($elem as $e) {
1704                  $table->data[] = array(html_writer::link($e['url'], format_string($e['content'], true, array('context' => $this->modcontext))));
1705              }
1706          }
1707          echo html_writer::table($table);
1708      }
1709  
1710      /**
1711       * Prints the orphaned tab content
1712       *
1713       *
1714       */
1715      private function print_orphaned_content() {
1716          global $OUTPUT;
1717  
1718          $page = $this->page;
1719  
1720          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1721              $fresh = wiki_refresh_cachedcontent($page);
1722              $page = $fresh['page'];
1723          }
1724  
1725          $swid = $this->subwiki->id;
1726  
1727          $table = new html_table();
1728          $table->head = array(get_string('orphaned', 'wiki') . $OUTPUT->help_icon('orphaned', 'wiki'));
1729          $table->attributes['class'] = 'generalbox table';
1730          $table->data = array();
1731          $table->rowclasses = array();
1732  
1733          if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
1734              foreach ($orphanedpages as $page) {
1735                  $link = wiki_parser_link($page->title, array('swid' => $swid));
1736                  $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1737                  $table->data[] = array('<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>');
1738              }
1739          } else {
1740              $table->data[] = array(get_string('noorphanedpages', 'wiki'));
1741          }
1742  
1743          echo html_writer::table($table);
1744      }
1745  
1746      /**
1747       * Prints the updated tab content
1748       *
1749       * @uses $COURSE, $OUTPUT
1750       *
1751       */
1752      private function print_updated_content() {
1753          global $COURSE, $OUTPUT;
1754          $page = $this->page;
1755  
1756          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1757              $fresh = wiki_refresh_cachedcontent($page);
1758              $page = $fresh['page'];
1759          }
1760  
1761          $swid = $this->subwiki->id;
1762  
1763          $table = new html_table();
1764          $table->head = array(get_string('updatedpages', 'wiki') . $OUTPUT->help_icon('updatedpages', 'wiki'));
1765          $table->attributes['class'] = 'generalbox table';
1766          $table->data = array();
1767          $table->rowclasses = array();
1768  
1769          if ($pages = wiki_get_updated_pages_by_subwiki($swid)) {
1770              $strdataux = '';
1771              foreach ($pages as $page) {
1772                  $user = wiki_get_user_info($page->userid);
1773                  $strdata = date('d M Y', $page->timemodified);
1774                  if ($strdata != $strdataux) {
1775                      $table->data[] = array($OUTPUT->heading($strdata, 4));
1776                      $strdataux = $strdata;
1777                  }
1778                  $link = wiki_parser_link($page->title, array('swid' => $swid));
1779                  $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1780  
1781                  $linkpage = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>';
1782                  $icon = $OUTPUT->user_picture($user, array($COURSE->id));
1783                  $table->data[] = array("$icon&nbsp;$linkpage");
1784              }
1785          } else {
1786              $table->data[] = array(get_string('noupdatedpages', 'wiki'));
1787          }
1788  
1789          echo html_writer::table($table);
1790      }
1791  
1792      protected function render_navigation_node($items, $attrs = array(), $expansionlimit = null, $depth = 1) {
1793  
1794          // exit if empty, we don't want an empty ul element
1795          if (count($items) == 0) {
1796              return '';
1797          }
1798  
1799          // array of nested li elements
1800          $lis = array();
1801          foreach ($items as $item) {
1802              if (!$item->display) {
1803                  continue;
1804              }
1805              $content = $item->get_content();
1806              $title = $item->get_title();
1807              if ($item->icon instanceof renderable) {
1808                  $icon = $this->wikioutput->render($item->icon);
1809                  $content = $icon . '&nbsp;' . $content; // use CSS for spacing of icons
1810                  }
1811              if ($item->helpbutton !== null) {
1812                  $content = trim($item->helpbutton) . html_writer::tag('span', $content, array('class' => 'clearhelpbutton'));
1813              }
1814  
1815              if ($content === '') {
1816                  continue;
1817              }
1818  
1819              if ($item->action instanceof action_link) {
1820                  //TODO: to be replaced with something else
1821                  $link = $item->action;
1822                  if ($item->hidden) {
1823                      $link->add_class('dimmed');
1824                  }
1825                  $content = $this->output->render($link);
1826              } else if ($item->action instanceof moodle_url) {
1827                  $attributes = array();
1828                  if ($title !== '') {
1829                      $attributes['title'] = $title;
1830                  }
1831                  if ($item->hidden) {
1832                      $attributes['class'] = 'dimmed_text';
1833                  }
1834                  $content = html_writer::link($item->action, $content, $attributes);
1835  
1836              } else if (is_string($item->action) || empty($item->action)) {
1837                  $attributes = array();
1838                  if ($title !== '') {
1839                      $attributes['title'] = $title;
1840                  }
1841                  if ($item->hidden) {
1842                      $attributes['class'] = 'dimmed_text';
1843                  }
1844                  $content = html_writer::tag('span', $content, $attributes);
1845              }
1846  
1847              // this applies to the li item which contains all child lists too
1848              $liclasses = array($item->get_css_type(), 'depth_' . $depth);
1849              if ($item->has_children() && (!$item->forceopen || $item->collapse)) {
1850                  $liclasses[] = 'collapsed';
1851              }
1852              if ($item->isactive === true) {
1853                  $liclasses[] = 'current_branch';
1854              }
1855              $liattr = array('class' => join(' ', $liclasses));
1856              // class attribute on the div item which only contains the item content
1857              $divclasses = array('tree_item');
1858              if ((empty($expansionlimit) || $item->type != $expansionlimit) && ($item->children->count() > 0 || ($item->nodetype == navigation_node::NODETYPE_BRANCH && $item->children->count() == 0 && isloggedin()))) {
1859                  $divclasses[] = 'branch';
1860              } else {
1861                  $divclasses[] = 'leaf';
1862              }
1863              if (!empty($item->classes) && count($item->classes) > 0) {
1864                  $divclasses[] = join(' ', $item->classes);
1865              }
1866              $divattr = array('class' => join(' ', $divclasses));
1867              if (!empty($item->id)) {
1868                  $divattr['id'] = $item->id;
1869              }
1870              $content = html_writer::tag('p', $content, $divattr) . $this->render_navigation_node($item->children, array(), $expansionlimit, $depth + 1);
1871              if (!empty($item->preceedwithhr) && $item->preceedwithhr === true) {
1872                  $content = html_writer::empty_tag('hr') . $content;
1873              }
1874              $content = html_writer::tag('li', $content, $liattr);
1875              $lis[] = $content;
1876          }
1877  
1878          if (count($lis)) {
1879              return html_writer::tag('ul', implode("\n", $lis), $attrs);
1880          } else {
1881              return '';
1882          }
1883      }
1884  
1885  }
1886  
1887  /**
1888   * Class that models the behavior of wiki's restore version page
1889   *
1890   */
1891  class page_wiki_restoreversion extends page_wiki {
1892      private $version;
1893  
1894      function print_header() {
1895          parent::print_header();
1896          $this->print_pagetitle();
1897      }
1898  
1899      function print_content() {
1900          global $PAGE;
1901  
1902          $wiki = $PAGE->activityrecord;
1903          if (wiki_user_can_edit($this->subwiki, $wiki)) {
1904              $this->print_restoreversion();
1905          } else {
1906              echo get_string('cannoteditpage', 'wiki');
1907          }
1908  
1909      }
1910  
1911      function set_url() {
1912          global $PAGE, $CFG;
1913          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
1914      }
1915  
1916      function set_versionid($versionid) {
1917          $this->version = wiki_get_version($versionid);
1918      }
1919  
1920      protected function create_navbar() {
1921          global $PAGE, $CFG;
1922  
1923          parent::create_navbar();
1924          $PAGE->navbar->add(get_string('restoreversion', 'wiki'));
1925      }
1926  
1927      protected function setup_tabs($options = array()) {
1928          parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history'));
1929      }
1930  
1931      /**
1932       * This method returns the action bar.
1933       *
1934       * @param int $pageid The page id.
1935       * @param moodle_url $pageurl The page url.
1936       * @return string The HTML for the action bar.
1937       */
1938      protected function action_bar(int $pageid, moodle_url $pageurl): string {
1939          // The given page does not require an action bar.
1940          return '';
1941      }
1942  
1943      /**
1944       * Prints the restore version content
1945       *
1946       * @uses $CFG
1947       *
1948       * @param page $page The page whose version will be restored
1949       * @param int  $versionid The version to be restored
1950       * @param bool $confirm If false, shows a yes/no confirmation page.
1951       *     If true, restores the old version and redirects the user to the 'view' tab.
1952       */
1953      private function print_restoreversion() {
1954          global $OUTPUT;
1955  
1956          $version = wiki_get_version($this->version->id);
1957  
1958          $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'versionid'=>$version->id, 'sesskey'=>sesskey());
1959          $restoreurl = new moodle_url('/mod/wiki/restoreversion.php', $optionsyes);
1960          $return = new moodle_url('/mod/wiki/viewversion.php', array('pageid'=>$this->page->id, 'versionid'=>$version->id));
1961  
1962          echo $OUTPUT->container_start();
1963          echo html_writer::tag('div', get_string('restoreconfirm', 'wiki', $version->version));
1964          echo $OUTPUT->container_start('mt-2', 'wiki_restoreform');
1965          $yesbutton = new single_button($restoreurl, get_string('yes'), 'post');
1966          $nobutton = new single_button($return, get_string('no'), 'post');
1967          $nobutton->class .= ' ml-2';
1968          echo $OUTPUT->render($yesbutton);
1969          echo $OUTPUT->render($nobutton);
1970          echo $OUTPUT->container_end();
1971          echo $OUTPUT->container_end();
1972      }
1973  }
1974  /**
1975   * Class that models the behavior of wiki's delete comment confirmation page
1976   *
1977   */
1978  class page_wiki_deletecomment extends page_wiki {
1979      private $commentid;
1980  
1981      function print_header() {
1982          parent::print_header();
1983          $this->print_pagetitle();
1984      }
1985  
1986      function print_content() {
1987          $this->printconfirmdelete();
1988      }
1989  
1990      function set_url() {
1991          global $PAGE;
1992          $PAGE->set_url('/mod/wiki/instancecomments.php', array('pageid' => $this->page->id, 'commentid' => $this->commentid));
1993      }
1994  
1995      public function set_action($action, $commentid, $content) {
1996          $this->action = $action;
1997          $this->commentid = $commentid;
1998          $this->content = $content;
1999      }
2000  
2001      protected function create_navbar() {
2002          global $PAGE;
2003  
2004          parent::create_navbar();
2005          $PAGE->navbar->add(get_string('deletecommentcheck', 'wiki'));
2006      }
2007  
2008      protected function setup_tabs($options = array()) {
2009          parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
2010      }
2011  
2012      /**
2013       * This method returns the action bar.
2014       *
2015       * @param int $pageid The page id.
2016       * @param moodle_url $pageurl The page url.
2017       * @return string The HTML for the action bar.
2018       */
2019      protected function action_bar(int $pageid, moodle_url $pageurl): string {
2020          // The given page does not require an action bar.
2021          return '';
2022      }
2023  
2024      /**
2025       * Prints the comment deletion confirmation form
2026       */
2027      private function printconfirmdelete() {
2028          global $OUTPUT;
2029  
2030          $strdeletecheckfull = get_string('deletecommentcheckfull', 'wiki');
2031  
2032          //ask confirmation
2033          $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'action'=>'delete', 'commentid'=>$this->commentid, 'sesskey'=>sesskey());
2034          $deleteurl = new moodle_url('/mod/wiki/instancecomments.php', $optionsyes);
2035          $return = new moodle_url('/mod/wiki/comments.php', array('pageid'=>$this->page->id));
2036  
2037          echo $OUTPUT->confirm($strdeletecheckfull, $deleteurl, $return);
2038      }
2039  }
2040  
2041  /**
2042   * Class that models the behavior of wiki's
2043   * save page
2044   *
2045   */
2046  class page_wiki_save extends page_wiki_edit {
2047  
2048      private $newcontent;
2049  
2050      function print_header() {
2051      }
2052  
2053      function print_content() {
2054          global $PAGE;
2055  
2056          $context = context_module::instance($this->cm->id);
2057          require_capability('mod/wiki:editpage', $context, NULL, true, 'noeditpermission', 'wiki');
2058  
2059          $this->print_save();
2060      }
2061  
2062      function set_newcontent($newcontent) {
2063          $this->newcontent = $newcontent;
2064      }
2065  
2066      protected function set_session_url() {
2067      }
2068  
2069      protected function print_save() {
2070          global $CFG, $USER, $OUTPUT, $PAGE;
2071  
2072          $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
2073          if (!empty($this->section)) {
2074              $url .= "&section=" . urlencode($this->section);
2075          }
2076  
2077          $params = array(
2078              'attachmentoptions' => page_wiki_edit::$attachmentoptions,
2079              'format' => $this->format,
2080              'version' => $this->versionnumber,
2081              'contextid' => $this->modcontext->id
2082          );
2083  
2084          if ($this->format != 'html') {
2085              $params['fileitemid'] = $this->page->id;
2086              $params['component']  = 'mod_wiki';
2087              $params['filearea']   = 'attachments';
2088          }
2089  
2090          $form = new mod_wiki_edit_form($url, $params);
2091  
2092          $save = false;
2093          $data = false;
2094          if ($data = $form->get_data()) {
2095              if ($this->format == 'html') {
2096                  $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id);
2097              }
2098  
2099              if (isset($this->section)) {
2100                  $save = wiki_save_section($this->page, $this->section, $data->newcontent, $USER->id);
2101              } else {
2102                  $save = wiki_save_page($this->page, $data->newcontent, $USER->id);
2103              }
2104          }
2105  
2106          if ($save && $data) {
2107              core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $this->page->id, $this->modcontext, $data->tags);
2108  
2109              $message = '<p>' . get_string('saving', 'wiki') . '</p>';
2110  
2111              if (!empty($save['sections'])) {
2112                  foreach ($save['sections'] as $s) {
2113                      $message .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
2114                  }
2115              }
2116  
2117              if ($this->versionnumber + 1 != $save['version']) {
2118                  $message .= '<p>' . get_string('wrongversionsave', 'wiki') . '</p>';
2119              }
2120  
2121              if (isset($errors) && !empty($errors)) {
2122                  foreach ($errors as $e) {
2123                      $message .= "<p>" . get_string('filenotuploadederror', 'wiki', $e->get_filename()) . "</p>";
2124                  }
2125              }
2126  
2127              //deleting old locks
2128              wiki_delete_locks($this->page->id, $USER->id, $this->section);
2129              $url = new moodle_url('/mod/wiki/view.php', array('pageid' => $this->page->id, 'group' => $this->subwiki->groupid));
2130              redirect($url);
2131          } else {
2132              throw new \moodle_exception('savingerror', 'wiki');
2133          }
2134      }
2135  }
2136  
2137  /**
2138   * Class that models the behavior of wiki's view an old version of a page
2139   *
2140   */
2141  class page_wiki_viewversion extends page_wiki {
2142  
2143      private $version;
2144  
2145      function print_header() {
2146          parent::print_header();
2147          $this->print_pagetitle();
2148      }
2149  
2150      function print_content() {
2151          global $PAGE;
2152  
2153          require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2154  
2155          $this->print_version_view();
2156      }
2157  
2158      function set_url() {
2159          global $PAGE, $CFG;
2160          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2161      }
2162  
2163      function set_versionid($versionid) {
2164          $this->version = wiki_get_version($versionid);
2165      }
2166  
2167      protected function create_navbar() {
2168          global $PAGE, $CFG;
2169  
2170          parent::create_navbar();
2171          $PAGE->navbar->add(get_string('history', 'wiki'), $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $this->page->id);
2172          $PAGE->navbar->add(get_string('versionnum', 'wiki', $this->version->version));
2173      }
2174  
2175      protected function setup_tabs($options = array()) {
2176          parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history', 'inactivetabs' => array('edit')));
2177      }
2178  
2179      /**
2180       * This method returns the action bar.
2181       *
2182       * @param int $pageid The page id.
2183       * @param moodle_url $pageurl The page url.
2184       * @return string The HTML for the action bar.
2185       */
2186      protected function action_bar(int $pageid, moodle_url $pageurl): string {
2187          $backlink = new moodle_url('/mod/wiki/history.php', ['pageid' => $pageid]);
2188          return html_writer::link($backlink, get_string('back'), ['class' => 'btn btn-secondary mb-4']);
2189      }
2190  
2191      /**
2192       * Given an old page version, output the version content
2193       *
2194       * @global object $CFG
2195       * @global object $OUTPUT
2196       * @global object $PAGE
2197       */
2198      private function print_version_view() {
2199          global $CFG, $OUTPUT, $PAGE;
2200          $pageversion = wiki_get_version($this->version->id);
2201  
2202          if ($pageversion) {
2203              $restorelink = new moodle_url('/mod/wiki/restoreversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2204              echo html_writer::tag('div', get_string('viewversion', 'wiki', $pageversion->version) . '<br />' .
2205                  html_writer::link($restorelink->out(false), '(' . get_string('restorethis', 'wiki') .
2206                  ')', array('class' => 'wiki_restore')) . '&nbsp;', array('class' => 'wiki_headingtitle'));
2207              $userinfo = wiki_get_user_info($pageversion->userid);
2208              $heading = '<p><strong>' . get_string('modified', 'wiki') . ':</strong>&nbsp;' . userdate($pageversion->timecreated, get_string('strftimedatetime', 'langconfig'));
2209              $viewlink = new moodle_url('/user/view.php', array('id' => $userinfo->id));
2210              $heading .= '&nbsp;&nbsp;&nbsp;<strong>' . get_string('user') . ':</strong>&nbsp;' . html_writer::link($viewlink->out(false), fullname($userinfo));
2211              $heading .= '&nbsp;&nbsp;&rarr;&nbsp;' . $OUTPUT->user_picture(wiki_get_user_info($pageversion->userid), array('popup' => true)) . '</p>';
2212              echo $OUTPUT->container($heading, 'wiki_headingtime', 'wiki_modifieduser');
2213              $options = array('swid' => $this->subwiki->id, 'pretty_print' => true, 'pageid' => $this->page->id);
2214  
2215              $pageversion->content = file_rewrite_pluginfile_urls($pageversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id);
2216  
2217              $parseroutput = wiki_parse_content($pageversion->contentformat, $pageversion->content, $options);
2218              $content = $OUTPUT->container(format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true)), false, '', '', true);
2219              echo $OUTPUT->box($content, 'generalbox wiki_contentbox');
2220  
2221          } else {
2222              throw new \moodle_exception('versionerror', 'wiki');
2223          }
2224      }
2225  }
2226  
2227  class page_wiki_confirmrestore extends page_wiki_save {
2228  
2229      private $version;
2230  
2231      function set_url() {
2232          global $PAGE, $CFG;
2233          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2234      }
2235  
2236      function print_header() {
2237          $this->set_url();
2238      }
2239  
2240      function print_content() {
2241          global $CFG, $PAGE;
2242  
2243          $version = wiki_get_version($this->version->id);
2244          $wiki = $PAGE->activityrecord;
2245          if (wiki_user_can_edit($this->subwiki, $wiki) &&
2246                  wiki_restore_page($this->page, $version, $this->modcontext)) {
2247              redirect($CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $this->page->id, get_string('restoring', 'wiki', $version->version), 3);
2248          } else {
2249              throw new \moodle_exception('restoreerror', 'wiki', $version->version);
2250          }
2251      }
2252  
2253      function set_versionid($versionid) {
2254          $this->version = wiki_get_version($versionid);
2255      }
2256  }
2257  
2258  class page_wiki_prettyview extends page_wiki {
2259  
2260      function __construct($wiki, $subwiki, $cm) {
2261          global $PAGE;
2262          $PAGE->set_pagelayout('embedded');
2263          $PAGE->activityheader->disable();
2264          parent::__construct($wiki, $subwiki, $cm);
2265      }
2266  
2267      function print_header() {
2268          global $OUTPUT;
2269          $this->set_url();
2270  
2271          echo $OUTPUT->header();
2272          // Print dialog link.
2273          $printtext = get_string('print', 'wiki');
2274          $printlinkatt = array('onclick' => 'window.print();return false;', 'class' => 'printicon');
2275          $printiconlink = html_writer::link('#', $printtext, $printlinkatt);
2276          echo html_writer::tag('div', $printiconlink, array('class' => 'displayprinticon'));
2277          echo html_writer::tag('h1', format_string($this->title), array('id' => 'wiki_printable_title'));
2278      }
2279  
2280      function print_content() {
2281          global $PAGE;
2282  
2283          require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2284  
2285          $this->print_pretty_view();
2286      }
2287  
2288      function set_url() {
2289          global $PAGE, $CFG;
2290  
2291          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/prettyview.php', array('pageid' => $this->page->id));
2292      }
2293  
2294      private function print_pretty_view() {
2295          $version = wiki_get_current_version($this->page->id);
2296  
2297          $content = wiki_parse_content($version->contentformat, $version->content, array('printable' => true, 'swid' => $this->subwiki->id, 'pageid' => $this->page->id, 'pretty_print' => true));
2298  
2299          $html = $content['parsed_text'];
2300          $id = $this->subwiki->wikiid;
2301          if ($cm = get_coursemodule_from_instance("wiki", $id)) {
2302              $context = context_module::instance($cm->id);
2303              $html = file_rewrite_pluginfile_urls($html, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $this->subwiki->id);
2304          }
2305          echo '<div id="wiki_printable_content">';
2306          echo format_text($html, FORMAT_HTML);
2307          echo '</div>';
2308      }
2309  }
2310  
2311  class page_wiki_handlecomments extends page_wiki {
2312      private $action;
2313      private $content;
2314      private $commentid;
2315      private $format;
2316  
2317      function print_header() {
2318          $this->set_url();
2319      }
2320  
2321      public function print_content() {
2322          global $CFG, $PAGE, $USER;
2323  
2324          if ($this->action == 'add') {
2325              require_capability('mod/wiki:editcomment', $this->modcontext);
2326              $this->add_comment($this->content, $this->commentid);
2327          } else if ($this->action == 'edit') {
2328              require_capability('mod/wiki:editcomment', $this->modcontext);
2329  
2330              $comment = wiki_get_comment($this->commentid);
2331              $owner = ($comment->userid == $USER->id);
2332  
2333              if ($owner) {
2334                  $this->add_comment($this->content, $this->commentid);
2335              }
2336          } else if ($this->action == 'delete') {
2337              $comment = wiki_get_comment($this->commentid);
2338  
2339              $manage = has_capability('mod/wiki:managecomment', $this->modcontext);
2340              $edit = has_capability('mod/wiki:editcomment', $this->modcontext);
2341              $owner = ($comment->userid == $USER->id);
2342  
2343              if ($manage || ($owner && $edit)) {
2344                  $this->delete_comment($this->commentid);
2345                  redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $this->page->id, get_string('deletecomment', 'wiki'), 2);
2346              } else {
2347                  throw new \moodle_exception('nopermissiontoeditcomment');
2348              }
2349          }
2350  
2351      }
2352  
2353      public function set_url() {
2354          global $PAGE, $CFG;
2355          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
2356      }
2357  
2358      public function set_action($action, $commentid, $content) {
2359          $this->action = $action;
2360          $this->commentid = $commentid;
2361          $this->content = $content;
2362  
2363          $version = wiki_get_current_version($this->page->id);
2364          $format = $version->contentformat;
2365  
2366          $this->format = $format;
2367      }
2368  
2369      private function add_comment($content, $idcomment) {
2370          global $CFG, $PAGE;
2371          require_once($CFG->dirroot . "/mod/wiki/locallib.php");
2372  
2373          $pageid = $this->page->id;
2374  
2375          wiki_add_comment($this->modcontext, $pageid, $content, $this->format);
2376  
2377          if (!$idcomment) {
2378              redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('createcomment', 'wiki'), 2);
2379          } else {
2380              $this->delete_comment($idcomment);
2381              redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('editingcomment', 'wiki'), 2);
2382          }
2383      }
2384  
2385      private function delete_comment($commentid) {
2386          global $CFG, $PAGE;
2387  
2388          $pageid = $this->page->id;
2389  
2390          wiki_delete_comment($commentid, $this->modcontext, $pageid);
2391      }
2392  
2393  }
2394  
2395  class page_wiki_lock extends page_wiki_edit {
2396  
2397      public function print_header() {
2398          $this->set_url();
2399      }
2400  
2401      protected function set_url() {
2402          global $PAGE, $CFG;
2403  
2404          $params = array('pageid' => $this->page->id);
2405  
2406          if ($this->section) {
2407              $params['section'] = $this->section;
2408          }
2409  
2410          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/lock.php', $params);
2411      }
2412  
2413      protected function set_session_url() {
2414      }
2415  
2416      public function print_content() {
2417          global $USER, $PAGE;
2418  
2419          require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki');
2420  
2421          wiki_set_lock($this->page->id, $USER->id, $this->section);
2422      }
2423  
2424      public function print_footer() {
2425      }
2426  }
2427  
2428  class page_wiki_overridelocks extends page_wiki_edit {
2429      function print_header() {
2430          $this->set_url();
2431      }
2432  
2433      function print_content() {
2434          global $CFG, $PAGE;
2435  
2436          require_capability('mod/wiki:overridelock', $this->modcontext, NULL, true, 'nooverridelockpermission', 'wiki');
2437  
2438          wiki_delete_locks($this->page->id, null, $this->section, true, true);
2439  
2440          $args = "pageid=" . $this->page->id;
2441  
2442          if (!empty($this->section)) {
2443              $args .= "&section=" . urlencode($this->section);
2444          }
2445  
2446          redirect($CFG->wwwroot . '/mod/wiki/edit.php?' . $args, get_string('overridinglocks', 'wiki'), 2);
2447      }
2448  
2449      function set_url() {
2450          global $PAGE, $CFG;
2451  
2452          $params = array('pageid' => $this->page->id);
2453  
2454          if (!empty($this->section)) {
2455              $params['section'] = $this->section;
2456          }
2457  
2458          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/overridelocks.php', $params);
2459      }
2460  
2461      protected function set_session_url() {
2462      }
2463  
2464      private function print_overridelocks() {
2465          global $CFG;
2466  
2467          wiki_delete_locks($this->page->id, null, $this->section, true, true);
2468  
2469          $args = "pageid=" . $this->page->id;
2470  
2471          if (!empty($this->section)) {
2472              $args .= "&section=" . urlencode($this->section);
2473          }
2474  
2475          redirect($CFG->wwwroot . '/mod/wiki/edit.php?' . $args, get_string('overridinglocks', 'wiki'), 2);
2476      }
2477  
2478  }
2479  
2480  /**
2481   * This class will let user to delete wiki pages and page versions
2482   *
2483   */
2484  class page_wiki_admin extends page_wiki {
2485  
2486      public $view, $action;
2487      public $listorphan = false;
2488  
2489      /**
2490       * Constructor
2491       *
2492       * @global object $PAGE
2493       * @param mixed $wiki instance of wiki
2494       * @param mixed $subwiki instance of subwiki
2495       * @param stdClass $cm course module
2496       * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
2497       */
2498      public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
2499          global $PAGE;
2500          parent::__construct($wiki, $subwiki, $cm, $activesecondarytab);
2501          $PAGE->requires->js_init_call('M.mod_wiki.deleteversion', null, true);
2502      }
2503  
2504      /**
2505       * Prints header for wiki page
2506       */
2507      function print_header() {
2508          parent::print_header();
2509          $this->print_pagetitle();
2510      }
2511  
2512      /**
2513       * This function will display administration view to users with managewiki capability
2514       */
2515      function print_content() {
2516          //make sure anyone trying to access this page has managewiki capabilities
2517          require_capability('mod/wiki:managewiki', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2518  
2519          //update wiki cache if timedout
2520          $page = $this->page;
2521          if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
2522              $fresh = wiki_refresh_cachedcontent($page);
2523              $page = $fresh['page'];
2524          }
2525  
2526          //dispaly admin menu
2527          echo $this->wikioutput->menu_admin($this->page->id, $this->view);
2528  
2529          //Display appropriate admin view
2530          switch ($this->view) {
2531              case 1: //delete page view
2532                  $this->print_delete_content($this->listorphan);
2533                  break;
2534              case 2: //delete version view
2535                  $this->print_delete_version();
2536                  break;
2537              default: //default is delete view
2538                  $this->print_delete_content($this->listorphan);
2539                  break;
2540          }
2541      }
2542  
2543      /**
2544       * Sets admin view option
2545       *
2546       * @param int $view page view id
2547       * @param bool $listorphan is only valid for view 1.
2548       */
2549      public function set_view($view, $listorphan = true) {
2550          $this->view = $view;
2551          $this->listorphan = $listorphan;
2552      }
2553  
2554      /**
2555       * Sets page url
2556       *
2557       * @global object $PAGE
2558       * @global object $CFG
2559       */
2560      function set_url() {
2561          global $PAGE, $CFG;
2562          $PAGE->set_url($CFG->wwwroot . '/mod/wiki/admin.php', array('pageid' => $this->page->id));
2563      }
2564  
2565      /**
2566       * sets navigation bar for the page
2567       *
2568       * @global object $PAGE
2569       */
2570      protected function create_navbar() {
2571          global $PAGE;
2572  
2573          parent::create_navbar();
2574          $PAGE->navbar->add(get_string('admin', 'wiki'));
2575      }
2576  
2577      /**
2578       * Show wiki page delete options
2579       *
2580       * @param bool $showorphan
2581       */
2582      protected function print_delete_content($showorphan = true) {
2583          $contents = array();
2584          $table = new html_table();
2585          $table->head = array('', get_string('pagename','wiki'));
2586          $table->attributes['class'] = 'table generaltable';
2587          $swid = $this->subwiki->id;
2588          if ($showorphan) {
2589              if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
2590                  $this->add_page_delete_options($orphanedpages, $swid, $table);
2591              } else {
2592                  $table->data[] = array('', get_string('noorphanedpages', 'wiki'));
2593              }
2594          } else {
2595              if ($pages = wiki_get_page_list($swid)) {
2596                  $this->add_page_delete_options($pages, $swid, $table);
2597              } else {
2598                  $table->data[] = array('', get_string('nopages', 'wiki'));
2599              }
2600          }
2601  
2602          ///Print the form
2603          echo html_writer::start_tag('form', array(
2604                                                  'action' => new moodle_url('/mod/wiki/admin.php'),
2605                                                  'method' => 'post'));
2606          echo html_writer::tag('div', html_writer::empty_tag('input', array(
2607                                                                           'type'  => 'hidden',
2608                                                                           'name'  => 'pageid',
2609                                                                           'value' => $this->page->id)));
2610  
2611          echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
2612          echo html_writer::table($table);
2613          echo html_writer::start_tag('div');
2614          if (!$showorphan) {
2615              echo html_writer::empty_tag('input', array(
2616                                                       'type'    => 'submit',
2617                                                       'class'   => 'wiki_form-button',
2618                                                       'value'   => get_string('listorphan', 'wiki'),
2619                                                       'sesskey' => sesskey()));
2620          } else {
2621              echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'listall', 'value'=>'1'));
2622              echo html_writer::empty_tag('input', array(
2623                                                       'type'    => 'submit',
2624                                                       'class'   => 'wiki_form-button btn btn-secondary',
2625                                                       'value'   => get_string('listall', 'wiki'),
2626                                                       'sesskey' => sesskey()));
2627          }
2628          echo html_writer::end_tag('div');
2629          echo html_writer::end_tag('form');
2630      }
2631  
2632      /**
2633       * helper function for print_delete_content. This will add data to the table.
2634       *
2635       * @global object $OUTPUT
2636       * @param array $pages objects of wiki pages in subwiki
2637       * @param int $swid id of subwiki
2638       * @param object $table reference to the table in which data needs to be added
2639       */
2640      protected function add_page_delete_options($pages, $swid, &$table) {
2641          global $OUTPUT;
2642          foreach ($pages as $page) {
2643              $link = wiki_parser_link($page->title, array('swid' => $swid));
2644              $class = ($link['new']) ? 'class="wiki_newentry"' : '';
2645              $pagelink = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>';
2646              $urledit = new moodle_url('/mod/wiki/edit.php', array('pageid' => $page->id, 'sesskey' => sesskey()));
2647              $urldelete = new moodle_url('/mod/wiki/admin.php', array(
2648                                                                     'pageid'  => $this->page->id,
2649                                                                     'delete'  => $page->id,
2650                                                                     'option'  => $this->view,
2651                                                                     'listall' => !$this->listorphan?'1': '',
2652                                                                     'sesskey' => sesskey()));
2653  
2654              $editlinks = $OUTPUT->action_icon($urledit, new pix_icon('t/edit', get_string('edit')));
2655              $editlinks .= $OUTPUT->action_icon($urldelete, new pix_icon('t/delete', get_string('delete')));
2656              $table->data[] = array($editlinks, $pagelink);
2657          }
2658      }
2659  
2660      /**
2661       * Prints lists of versions which can be deleted
2662       *
2663       * @global core_renderer $OUTPUT
2664       * @global moodle_page $PAGE
2665       */
2666      private function print_delete_version() {
2667          global $OUTPUT, $PAGE;
2668          $pageid = $this->page->id;
2669  
2670          // versioncount is the latest version
2671          $versioncount = wiki_count_wiki_page_versions($pageid) - 1;
2672          $versions = wiki_get_wiki_page_versions($pageid, 0, $versioncount);
2673  
2674          // We don't want version 0 to be displayed
2675          // version 0 is blank page
2676          if (end($versions)->version == 0) {
2677              array_pop($versions);
2678          }
2679  
2680          $contents = array();
2681          $version0page = wiki_get_wiki_page_version($this->page->id, 0);
2682          $creator = wiki_get_user_info($version0page->userid);
2683          $a = new stdClass();
2684          $a->date = userdate($this->page->timecreated, get_string('strftimedaydatetime', 'langconfig'));
2685          $a->username = fullname($creator);
2686          echo $OUTPUT->heading(get_string('createddate', 'wiki', $a), 4);
2687          if ($versioncount > 0) {
2688              /// If there is only one version, we don't need radios nor forms
2689              if (count($versions) == 1) {
2690                  $row = array_shift($versions);
2691                  $username = wiki_get_user_info($row->userid);
2692                  $picture = $OUTPUT->user_picture($username);
2693                  $date = userdate($row->timecreated, get_string('strftimedate', 'langconfig'));
2694                  $time = userdate($row->timecreated, get_string('strftimetime', 'langconfig'));
2695                  $versionid = wiki_get_version($row->id);
2696                  $versionlink = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
2697                  $userlink = new moodle_url('/user/view.php', array('id' => $username->id, 'course' => $this->cm->course));
2698                  $picturelink = $picture . html_writer::link($userlink->out(false), fullname($username));
2699                  $historydate = $OUTPUT->container($date, 'wiki_histdate');
2700                  $contents[] = array('', html_writer::link($versionlink->out(false), $row->version), $picturelink, $time, $historydate);
2701  
2702                  //Show current version
2703                  $table = new html_table();
2704                  $table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
2705                  $table->data = $contents;
2706  
2707                  echo html_writer::table($table);
2708              } else {
2709                  $lastdate = '';
2710                  $rowclass = array();
2711  
2712                  foreach ($versions as $version) {
2713                      $user = wiki_get_user_info($version->userid);
2714                      $picture = $OUTPUT->user_picture($user, array('popup' => true));
2715                      $date = userdate($version->timecreated, get_string('strftimedate'));
2716                      if ($date == $lastdate) {
2717                          $date = '';
2718                          $rowclass[] = '';
2719                      } else {
2720                          $lastdate = $date;
2721                          $rowclass[] = 'wiki_histnewdate';
2722                      }
2723  
2724                      $time = userdate($version->timecreated, get_string('strftimetime', 'langconfig'));
2725                      $versionid = wiki_get_version($version->id);
2726                      if ($versionid) {
2727                          $url = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
2728                          $viewlink = html_writer::link($url->out(false), $version->version);
2729                      } else {
2730                          $viewlink = $version->version;
2731                      }
2732  
2733                      $userlink = new moodle_url('/user/view.php', array('id' => $version->userid, 'course' => $this->cm->course));
2734                      $picturelink = $picture . html_writer::link($userlink->out(false), fullname($user));
2735                      $historydate = $OUTPUT->container($date, 'wiki_histdate');
2736                      $radiofromelement = $this->choose_from_radio(array($version->version  => null), 'fromversion', 'M.mod_wiki.deleteversion()', $versioncount, true);
2737                      $radiotoelement = $this->choose_from_radio(array($version->version  => null), 'toversion', 'M.mod_wiki.deleteversion()', $versioncount, true);
2738                      $contents[] = array( $radiofromelement . $radiotoelement, $viewlink, $picturelink, $time, $historydate);
2739                  }
2740  
2741                  $table = new html_table();
2742                  $table->head = array(get_string('deleteversions', 'wiki'), get_string('version'), get_string('user'), get_string('modified'), '');
2743                  $table->data = $contents;
2744                  $table->attributes['class'] = 'table generaltable';
2745                  $table->rowclasses = $rowclass;
2746  
2747                  ///Print the form
2748                  echo html_writer::start_tag('form', array('action'=>new moodle_url('/mod/wiki/admin.php'), 'method' => 'post'));
2749                  echo html_writer::tag('div', html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'pageid', 'value' => $pageid)));
2750                  echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
2751                  echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' =>  sesskey()));
2752                  echo html_writer::table($table);
2753                  echo html_writer::start_tag('div');
2754                  echo html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'wiki_form-button btn btn-secondary', 'value' => get_string('deleteversions', 'wiki')));
2755                  echo html_writer::end_tag('div');
2756                  echo html_writer::end_tag('form');
2757              }
2758          } else {
2759              print_string('nohistory', 'wiki');
2760          }
2761      }
2762  
2763      /**
2764       * Given an array of values, creates a group of radio buttons to be part of a form
2765       * helper function for print_delete_version
2766       *
2767       * @param array  $options  An array of value-label pairs for the radio group (values as keys).
2768       * @param string $name     Name of the radiogroup (unique in the form).
2769       * @param string $onclick  Function to be executed when the radios are clicked.
2770       * @param string $checked  The value that is already checked.
2771       * @param bool   $return   If true, return the HTML as a string, otherwise print it.
2772       *
2773       * @return mixed If $return is false, returns nothing, otherwise returns a string of HTML.
2774       */
2775      private function choose_from_radio($options, $name, $onclick = '', $checked = '', $return = false) {
2776  
2777          static $idcounter = 0;
2778  
2779          if (!$name) {
2780              $name = 'unnamed';
2781          }
2782  
2783          $output = '<span class="radiogroup ' . $name . "\">\n";
2784  
2785          if (!empty($options)) {
2786              $currentradio = 0;
2787              foreach ($options as $value => $label) {
2788                  $htmlid = 'auto-rb' . sprintf('%04d', ++$idcounter);
2789                  $output .= ' <span class="radioelement ' . $name . ' rb' . $currentradio . "\">";
2790                  $output .= '<input name="' . $name . '" id="' . $htmlid . '" type="radio" value="' . $value . '"';
2791                  if ($value == $checked) {
2792                      $output .= ' checked="checked"';
2793                  }
2794                  if ($onclick) {
2795                      $output .= ' onclick="' . $onclick . '"';
2796                  }
2797                  if ($label === '') {
2798                      $output .= ' /> <label for="' . $htmlid . '">' . $value . '</label></span>' . "\n";
2799                  } else {
2800                      $output .= ' /> <label for="' . $htmlid . '">' . $label . '</label></span>' . "\n";
2801                  }
2802                  $currentradio = ($currentradio + 1) % 2;
2803              }
2804          }
2805  
2806          $output .= '</span>' . "\n";
2807  
2808          if ($return) {
2809              return $output;
2810          } else {
2811              echo $output;
2812          }
2813      }
2814  }