Merge branch 'MDL-79108-master' of https://github.com/sarjona/moodle
[moodle.git] / mod / wiki / pagelib.php
blob6f61dd06261e8ab9d9074b73f9130149f49a8031
1 <?php
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.
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/>.
18 /**
19 * This file contains several classes uses to render the diferent pages
20 * of the wiki module
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
26 * @author Jordi Piguillem
27 * @author Marc Alier
28 * @author David Jimenez
29 * @author Josep Arus
30 * @author Daniel Serrano
31 * @author Kenneth Riba
33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 defined('MOODLE_INTERNAL') || die();
38 require_once($CFG->dirroot . '/mod/wiki/edit_form.php');
40 /**
41 * Class page_wiki contains the common code between all pages
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45 abstract class page_wiki {
47 /**
48 * @var object Current subwiki
50 protected $subwiki;
52 /**
53 * @var int Current page
55 protected $page;
57 /**
58 * @var string Current page title
60 protected $title;
62 /**
63 * @var int Current group ID
65 protected $gid;
67 /**
68 * @var object module context object
70 protected $modcontext;
72 /**
73 * @var int Current user ID
75 protected $uid;
76 /**
77 * @var array The tabs set used in wiki module
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
85 protected $tabs_options = array();
86 /**
87 * @var mod_wiki_renderer wiki renderer
89 protected $wikioutput;
90 /**
91 * @var stdClass course module.
93 protected $cm;
95 /**
96 * The page_wiki constructor.
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
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);
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);
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));
126 * This method prints the top of the page.
128 function print_header() {
129 global $OUTPUT, $PAGE, $SESSION;
131 $PAGE->set_heading($PAGE->course->fullname);
133 $this->set_url();
134 if (isset($SESSION->wikipreviousurl) && is_array($SESSION->wikipreviousurl)) {
135 $this->process_session_url();
137 $this->set_session_url();
139 $this->create_navbar();
141 echo $OUTPUT->header();
143 if (!empty($this->page)) {
144 echo $this->action_bar($this->page->id, $PAGE->url);
149 * This method returns the action bar.
151 * @param int $pageid The page id.
152 * @param moodle_url $pageurl The page url.
153 * @return string The HTML for the action bar.
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);
161 * Protected method to print current page title.
163 protected function print_pagetitle() {
164 global $OUTPUT;
165 $html = '';
167 $html .= $OUTPUT->container_start('wiki_headingtitle');
168 $html .= $OUTPUT->heading(format_string($this->title), 3);
169 $html .= $OUTPUT->container_end();
170 echo $html;
174 * Setup page tabs, if options is empty, will set up active tab automatically
175 * @param array $options, tabs options
177 protected function setup_tabs($options = array()) {
178 global $CFG, $PAGE;
179 $groupmode = groups_get_activity_groupmode($this->cm);
181 if (empty($CFG->usecomments) || !has_capability('mod/wiki:viewcomment', $PAGE->context)){
182 unset($this->tabs['comments']);
185 if (!has_capability('mod/wiki:editpage', $PAGE->context)){
186 unset($this->tabs['edit']);
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']);
198 if (empty($options)) {
199 $this->tabs_options = array('activetab' => substr(get_class($this), 10));
200 } else {
201 $this->tabs_options = $options;
207 * This method must be overwritten to print the page content.
209 function print_content() {
210 throw new coding_exception('Page wiki class does not implement method print_content()');
214 * Method to set the current page
216 * @param object $page Current page
218 function set_page($page) {
219 global $PAGE;
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);
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.
232 function set_title($title) {
233 global $PAGE;
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);
242 * Method to set current group id
243 * @param int $gid Current group id
245 function set_gid($gid) {
246 $this->gid = $gid;
250 * Method to set current user id
251 * @param int $uid Current user id
253 function set_uid($uid) {
254 $this->uid = $uid;
258 * Method to set the URL of the page.
259 * This method must be overwritten by every type of page.
261 protected function set_url() {
262 throw new coding_exception('Page wiki class does not implement method set_url()');
266 * Protected method to create the common items of the navbar in every page type.
268 protected function create_navbar() {
269 global $PAGE, $CFG;
271 $PAGE->navbar->add(format_string($this->title), $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $this->page->id);
275 * This method print the footer of the page.
277 function print_footer() {
278 global $OUTPUT;
279 echo $OUTPUT->footer();
282 protected function process_session_url() {
283 global $USER, $SESSION;
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;
294 protected function set_session_url() {
295 global $SESSION;
296 unset($SESSION->wikipreviousurl);
302 * View a wiki page
304 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
306 class page_wiki_view extends page_wiki {
308 function print_header() {
309 global $PAGE;
311 parent::print_header();
313 $this->wikioutput->wiki_print_subwiki_selector($PAGE->activityrecord, $this->subwiki, $this->page, 'view');
315 //echo $this->wikioutput->page_index();
317 $this->print_pagetitle();
321 * This method returns the action bar.
323 * @param int $pageid The page id.
324 * @param moodle_url $pageurl The page url.
325 * @return string The HTML for the action bar.
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);
332 function print_content() {
333 global $PAGE, $CFG;
335 if (wiki_user_can_view($this->subwiki)) {
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;
348 } else {
349 echo get_string('cannotviewpage', 'wiki');
353 function set_url() {
354 global $PAGE, $CFG;
355 $params = array();
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'));
370 $PAGE->set_url(new moodle_url($CFG->wwwroot . '/mod/wiki/view.php', $params));
373 protected function create_navbar() {
374 global $PAGE;
376 $PAGE->navbar->add(format_string($this->title));
377 $PAGE->navbar->add(get_string('view', 'wiki'));
382 * Wiki page editing page
384 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
386 class page_wiki_edit extends page_wiki {
388 public static $attachmentoptions;
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;
401 * The page_wiki_edit constructor.
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
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;
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);
420 protected function print_pagetitle() {
421 global $OUTPUT;
423 $title = $this->title;
424 if (isset($this->section)) {
425 $title .= ' : ' . $this->section;
427 echo $OUTPUT->container_start('wiki_clear wiki_headingtitle');
428 echo $OUTPUT->heading(format_string($title), 3);
429 echo $OUTPUT->container_end();
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));
436 parent::print_header();
438 $this->print_pagetitle();
440 print '<noscript>' . $OUTPUT->box(get_string('javascriptdisabledlocks', 'wiki'), 'errorbox') . '</noscript>';
443 function print_content() {
444 global $PAGE;
446 if (wiki_user_can_edit($this->subwiki)) {
447 $this->print_edit();
448 } else {
449 echo get_string('cannoteditpage', 'wiki');
453 protected function set_url() {
454 global $PAGE, $CFG;
456 $params = array('pageid' => $this->page->id);
458 if (isset($this->section)) {
459 $params['section'] = $this->section;
462 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/edit.php', $params);
465 protected function set_session_url() {
466 global $SESSION;
468 $SESSION->wikipreviousurl = array('page' => 'edit', 'params' => array('pageid' => $this->page->id, 'section' => $this->section));
471 protected function process_session_url() {
474 function set_section($sectioncontent, $section) {
475 $this->sectioncontent = $sectioncontent;
476 $this->section = $section;
479 public function set_versionnumber($versionnumber) {
480 $this->versionnumber = $versionnumber;
483 public function set_overridelock($override) {
484 $this->overridelock = $override;
487 function set_format($format) {
488 $this->format = $format;
491 public function set_upload($upload) {
492 $this->upload = $upload;
495 public function set_attachments($attachments) {
496 $this->attachments = $attachments;
499 public function set_deleteuploads($deleteuploads) {
500 $this->deleteuploads = $deleteuploads;
503 protected function create_navbar() {
504 global $PAGE, $CFG;
506 parent::create_navbar();
508 $PAGE->navbar->add(get_string('edit', 'wiki'));
511 protected function check_locks() {
512 global $OUTPUT, $USER, $CFG;
514 if (!wiki_set_lock($this->page->id, $USER->id, $this->section, true)) {
515 print $OUTPUT->box(get_string('pageislocked', 'wiki'), 'generalbox boxwidthnormal boxaligncenter');
517 if ($this->overridelock) {
518 $params = 'pageid=' . $this->page->id;
520 if ($this->section) {
521 $params .= '&section=' . urlencode($this->section);
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>';
529 print $OUTPUT->box($form, 'generalbox boxwidthnormal boxaligncenter');
531 return false;
533 return true;
536 protected function print_edit($content = null) {
537 global $CFG, $OUTPUT, $USER, $PAGE;
539 if (!$this->check_locks()) {
540 return;
543 //delete old locks (> 1 hour)
544 wiki_delete_old_locks();
546 $version = wiki_get_current_version($this->page->id);
547 $format = $version->contentformat;
549 if ($content == null) {
550 if (empty($this->section)) {
551 $content = $version->content;
552 } else {
553 $content = $this->sectioncontent;
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;
565 $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
566 if (!empty($this->section)) {
567 $url .= "&section=" . urlencode($this->section);
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
578 $data = new StdClass();
579 $data->newcontent = $content;
580 $data->version = $versionnumber;
581 $data->format = $format;
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;
594 if ($version->contentformat != 'html') {
595 $params['fileitemid'] = $this->subwiki->id;
596 $params['component'] = 'mod_wiki';
597 $params['filearea'] = 'attachments';
600 $data->tags = core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $this->page->id);
602 $form = new mod_wiki_edit_form($url, $params);
603 $form->set_data($data);
604 $form->display();
610 * Class that models the behavior of wiki's view comments page
612 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
614 class page_wiki_comments extends page_wiki {
616 function print_header() {
618 parent::print_header();
620 $this->print_pagetitle();
624 function print_content() {
625 global $CFG, $OUTPUT, $USER, $PAGE;
626 require_once($CFG->dirroot . '/mod/wiki/locallib.php');
628 $page = $this->page;
629 $subwiki = $this->subwiki;
630 $wiki = $PAGE->activityrecord;
631 list($context, $course, $cm) = get_context_info_array($this->modcontext->id);
633 require_capability('mod/wiki:viewcomment', $this->modcontext, NULL, true, 'noviewcommentpermission', 'wiki');
635 $comments = wiki_get_comments($this->modcontext->id, $page->id);
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>';
641 $options = array('swid' => $this->page->subwikiid, 'pageid' => $page->id);
642 $version = wiki_get_current_version($this->page->id);
643 $format = $version->contentformat;
645 if (empty($comments)) {
646 echo html_writer::tag('p', get_string('nocomments', 'wiki'), array('class' => 'bold'));
649 foreach ($comments as $comment) {
651 $user = wiki_get_user_info($comment->userid);
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);
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 $cell3->attributes['width'] = "80%";
664 $cell4 = new html_table_cell();
665 $cell5 = new html_table_cell();
667 $row1 = new html_table_row();
668 $row1->cells[] = $cell1;
669 $row1->cells[] = $cell2;
670 $row2 = new html_table_row();
671 $row2->cells[] = $cell3;
673 if ($format != 'html') {
674 if ($format == 'creole') {
675 $parsedcontent = wiki_parse_content('creole', $comment->content, $options);
676 } else if ($format == 'nwiki') {
677 $parsedcontent = wiki_parse_content('nwiki', $comment->content, $options);
680 $cell4->text = format_text(html_entity_decode($parsedcontent['parsed_text'], ENT_QUOTES, 'UTF-8'), FORMAT_HTML);
681 } else {
682 $cell4->text = format_text($comment->content, FORMAT_HTML);
685 $row2->cells[] = $cell4;
687 $t->data = array($row1, $row2);
689 $canedit = $candelete = false;
690 if ((has_capability('mod/wiki:editcomment', $this->modcontext)) and ($USER->id == $user->id)) {
691 $candelete = $canedit = true;
693 if ((has_capability('mod/wiki:managecomment', $this->modcontext))) {
694 $candelete = true;
697 $editicon = $deleteicon = '';
698 if ($canedit) {
699 $urledit = new moodle_url('/mod/wiki/editcomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'edit'));
700 $editicon = $OUTPUT->action_icon($urledit, new pix_icon('t/edit', get_string('edit'), '', array('class' => 'iconsmall')));
702 if ($candelete) {
703 $urldelete = new moodle_url('/mod/wiki/instancecomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'delete'));
704 $deleteicon = $OUTPUT->action_icon($urldelete,
705 new pix_icon('t/delete',
706 get_string('delete'),
708 array('class' => 'iconsmall')));
711 if ($candelete || $canedit) {
712 $cell6 = new html_table_cell($editicon.$deleteicon);
713 $row3 = new html_table_row();
714 $row3->cells[] = $cell5;
715 $row3->cells[] = $cell6;
716 $t->data[] = $row3;
719 echo html_writer::tag('div', html_writer::table($t), array('class'=>'no-overflow'));
724 function set_url() {
725 global $PAGE, $CFG;
726 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
729 protected function create_navbar() {
730 global $PAGE, $CFG;
732 parent::create_navbar();
733 $PAGE->navbar->add(get_string('comments', 'wiki'));
739 * Class that models the behavior of wiki's edit comment
741 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
743 class page_wiki_editcomment extends page_wiki {
744 private $comment;
745 private $action;
746 private $form;
747 private $format;
749 function set_url() {
750 global $PAGE, $CFG;
751 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
754 function print_header() {
755 parent::print_header();
756 $this->print_pagetitle();
759 function print_content() {
760 global $PAGE;
762 require_capability('mod/wiki:editcomment', $this->modcontext, NULL, true, 'noeditcommentpermission', 'wiki');
764 if ($this->action == 'add') {
765 $this->add_comment_form();
766 } else if ($this->action == 'edit') {
767 $this->edit_comment_form($this->comment);
771 function set_action($action, $comment) {
772 global $CFG;
773 require_once($CFG->dirroot . '/mod/wiki/comments_form.php');
775 $this->action = $action;
776 $this->comment = $comment;
777 $version = wiki_get_current_version($this->page->id);
778 $this->format = $version->contentformat;
780 if ($this->format == 'html') {
781 $destination = $CFG->wwwroot . '/mod/wiki/instancecomments.php?pageid=' . $this->page->id;
782 $this->form = new mod_wiki_comments_form($destination);
786 protected function create_navbar() {
787 global $PAGE, $CFG;
789 $PAGE->navbar->add(get_string('comments', 'wiki'), $CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $this->page->id);
791 if ($this->action == 'add') {
792 $PAGE->navbar->add(get_string('insertcomment', 'wiki'));
793 } else {
794 $PAGE->navbar->add(get_string('editcomment', 'wiki'));
798 protected function setup_tabs($options = array()) {
799 parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
803 * This method returns the action bar.
805 * @param int $pageid The page id.
806 * @param moodle_url $pageurl The page url.
807 * @return string The HTML for the action bar.
809 protected function action_bar(int $pageid, moodle_url $pageurl): string {
810 // The given page does not require an action bar.
811 return '';
814 private function add_comment_form() {
815 global $CFG;
816 require_once($CFG->dirroot . '/mod/wiki/editors/wiki_editor.php');
818 $pageid = $this->page->id;
820 if ($this->format == 'html') {
821 $com = new stdClass();
822 $com->action = 'add';
823 $com->commentoptions = array('trusttext' => true, 'maxfiles' => 0);
824 $this->form->set_data($com);
825 $this->form->display();
826 } else {
827 wiki_print_editor_wiki($this->page->id, null, $this->format, -1, null, false, null, 'addcomments');
831 private function edit_comment_form($com) {
832 global $CFG;
833 require_once($CFG->dirroot . '/mod/wiki/comments_form.php');
834 require_once($CFG->dirroot . '/mod/wiki/editors/wiki_editor.php');
836 if ($this->format == 'html') {
837 $com->action = 'edit';
838 $com->entrycomment_editor['text'] = $com->content;
839 $com->commentoptions = array('trusttext' => true, 'maxfiles' => 0);
841 $this->form->set_data($com);
842 $this->form->display();
843 } else {
844 wiki_print_editor_wiki($this->page->id, $com->content, $this->format, -1, null, false, array(), 'editcomments', $com->id);
852 * Wiki page search page
854 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
856 class page_wiki_search extends page_wiki {
857 private $search_result;
859 protected function create_navbar() {
860 global $PAGE, $CFG;
862 $PAGE->navbar->add(format_string($this->title));
865 function set_search_string($search, $searchcontent) {
866 $swid = $this->subwiki->id;
867 if ($searchcontent) {
868 $this->search_result = wiki_search_all($swid, $search);
869 } else {
870 $this->search_result = wiki_search_title($swid, $search);
875 function set_url() {
876 global $PAGE, $CFG;
877 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/search.php');
880 function print_header() {
881 global $PAGE;
883 parent::print_header();
885 $wiki = $PAGE->activityrecord;
886 $page = (object)array('title' => $wiki->firstpagetitle);
887 $this->wikioutput->wiki_print_subwiki_selector($wiki, $this->subwiki, $page, 'search');
890 function print_content() {
891 global $PAGE;
893 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
895 echo $this->wikioutput->search_result($this->search_result, $this->subwiki);
901 * Class that models the behavior of wiki's
902 * create page
905 class page_wiki_create extends page_wiki {
907 private $format;
908 private $swid;
909 private $wid;
910 private $action;
911 private $mform;
912 private $groups;
914 function print_header() {
915 $this->set_url();
916 parent::print_header();
919 function set_url() {
920 global $PAGE, $CFG;
922 $params = array();
923 $params['swid'] = $this->swid;
924 if ($this->action == 'new') {
925 $params['action'] = 'new';
926 $params['wid'] = $this->wid;
927 if ($this->title != get_string('newpage', 'wiki')) {
928 $params['title'] = $this->title;
930 } else {
931 $params['action'] = 'create';
933 $PAGE->set_url(new moodle_url('/mod/wiki/create.php', $params));
936 function set_format($format) {
937 $this->format = $format;
940 function set_wid($wid) {
941 $this->wid = $wid;
944 function set_swid($swid) {
945 $this->swid = $swid;
948 function set_availablegroups($group) {
949 $this->groups = $group;
952 function set_action($action) {
953 global $PAGE;
954 $this->action = $action;
956 require_once(__DIR__ . '/create_form.php');
957 $url = new moodle_url('/mod/wiki/create.php', array('action' => 'create', 'wid' => $PAGE->activityrecord->id, 'group' => $this->gid, 'uid' => $this->uid));
958 $formats = wiki_get_formats();
959 $options = array('formats' => $formats, 'defaultformat' => $PAGE->activityrecord->defaultformat, 'forceformat' => $PAGE->activityrecord->forceformat, 'groups' => $this->groups);
960 if ($this->title != get_string('newpage', 'wiki')) {
961 $options['disable_pagetitle'] = true;
963 $this->mform = new mod_wiki_create_form($url->out(false), $options);
966 protected function create_navbar() {
967 global $PAGE;
968 // navigation_node::get_content formats this before printing.
969 $PAGE->navbar->add($this->title);
972 function print_content($pagetitle = '') {
973 global $PAGE;
975 // @TODO: Change this to has_capability and show an alternative interface.
976 require_capability('mod/wiki:createpage', $this->modcontext, NULL, true, 'nocreatepermission', 'wiki');
977 $data = new stdClass();
978 if (!empty($pagetitle)) {
979 $data->pagetitle = $pagetitle;
981 $data->pageformat = $PAGE->activityrecord->defaultformat;
983 $this->mform->set_data($data);
984 $this->mform->display();
987 function create_page($pagetitle) {
988 global $USER, $PAGE;
990 $data = $this->mform->get_data();
991 if (isset($data->groupinfo)) {
992 $groupid = $data->groupinfo;
993 } else if (!empty($this->gid)) {
994 $groupid = $this->gid;
995 } else {
996 $groupid = '0';
998 if (empty($this->subwiki)) {
999 // If subwiki is not set then try find one and set else create one.
1000 if (!$this->subwiki = wiki_get_subwiki_by_group($this->wid, $groupid, $this->uid)) {
1001 $swid = wiki_add_subwiki($PAGE->activityrecord->id, $groupid, $this->uid);
1002 $this->subwiki = wiki_get_subwiki($swid);
1005 if ($data) {
1006 $this->set_title($data->pagetitle);
1007 $id = wiki_create_page($this->subwiki->id, $data->pagetitle, $data->pageformat, $USER->id);
1008 } else {
1009 $this->set_title($pagetitle);
1010 $id = wiki_create_page($this->subwiki->id, $pagetitle, $PAGE->activityrecord->defaultformat, $USER->id);
1012 $this->page = $id;
1013 return $id;
1017 class page_wiki_preview extends page_wiki_edit {
1019 private $newcontent;
1021 function print_header() {
1022 global $PAGE, $CFG;
1024 parent::print_header();
1028 function print_content() {
1029 global $PAGE;
1031 require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki');
1033 $this->print_preview();
1036 function set_newcontent($newcontent) {
1037 $this->newcontent = $newcontent;
1040 function set_url() {
1041 global $PAGE, $CFG;
1043 $params = array('pageid' => $this->page->id
1046 if (isset($this->section)) {
1047 $params['section'] = $this->section;
1050 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/edit.php', $params);
1053 protected function setup_tabs($options = array()) {
1054 parent::setup_tabs(array('linkedwhenactive' => 'view', 'activetab' => 'view'));
1057 protected function check_locks() {
1058 return true;
1061 protected function print_preview() {
1062 global $CFG, $PAGE, $OUTPUT;
1064 $version = wiki_get_current_version($this->page->id);
1065 $format = $version->contentformat;
1066 $content = $version->content;
1068 $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
1069 if (!empty($this->section)) {
1070 $url .= "&section=" . urlencode($this->section);
1072 $params = array(
1073 'attachmentoptions' => page_wiki_edit::$attachmentoptions,
1074 'format' => $this->format,
1075 'version' => $this->versionnumber,
1076 'contextid' => $this->modcontext->id
1079 if ($this->format != 'html') {
1080 $params['component'] = 'mod_wiki';
1081 $params['filearea'] = 'attachments';
1082 $params['fileitemid'] = $this->page->id;
1084 $form = new mod_wiki_edit_form($url, $params);
1087 $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true);
1089 if ($data = $form->get_data()) {
1090 if (isset($data->newcontent)) {
1091 // wiki fromat
1092 $text = $data->newcontent;
1093 } else {
1094 // html format
1095 $text = $data->newcontent_editor['text'];
1097 $parseroutput = wiki_parse_content($data->contentformat, $text, $options);
1098 $this->set_newcontent($text);
1099 echo $OUTPUT->notification(get_string('previewwarning', 'wiki'), 'notifyproblem');
1100 $content = format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true, 'filter'=>false));
1101 echo $OUTPUT->box($content, 'generalbox wiki_previewbox');
1102 $content = $this->newcontent;
1105 $this->print_edit($content);
1112 * Class that models the behavior of wiki's
1113 * view differences
1116 class page_wiki_diff extends page_wiki {
1118 private $compare;
1119 private $comparewith;
1121 function print_header() {
1122 global $OUTPUT;
1124 parent::print_header();
1126 $this->print_pagetitle();
1127 $vstring = new stdClass();
1128 $vstring->old = $this->compare;
1129 $vstring->new = $this->comparewith;
1130 echo html_writer::tag('div', get_string('comparewith', 'wiki', $vstring), array('class' => 'wiki_headingtitle'));
1134 * Print the diff view
1136 function print_content() {
1137 global $PAGE;
1139 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1141 $this->print_diff_content();
1144 function set_url() {
1145 global $PAGE, $CFG;
1147 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/diff.php', array('pageid' => $this->page->id, 'comparewith' => $this->comparewith, 'compare' => $this->compare));
1150 function set_comparison($compare, $comparewith) {
1151 $this->compare = $compare;
1152 $this->comparewith = $comparewith;
1155 protected function create_navbar() {
1156 global $PAGE, $CFG;
1158 parent::create_navbar();
1159 $PAGE->navbar->add(get_string('history', 'wiki'), $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $this->page->id);
1160 $PAGE->navbar->add(get_string('diff', 'wiki'));
1163 protected function setup_tabs($options = array()) {
1164 parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history'));
1168 * This method returns the action bar.
1170 * @param int $pageid The page id.
1171 * @param moodle_url $pageurl The page url.
1172 * @return string The HTML for the action bar.
1174 protected function action_bar(int $pageid, moodle_url $pageurl): string {
1175 $backlink = new moodle_url('/mod/wiki/history.php', ['pageid' => $pageid]);
1176 return html_writer::link($backlink, get_string('back'), ['class' => 'btn btn-secondary mb-4']);
1180 * Given two versions of a page, prints a page displaying the differences between them.
1182 * @global object $CFG
1183 * @global object $OUTPUT
1184 * @global object $PAGE
1186 private function print_diff_content() {
1187 global $CFG, $OUTPUT, $PAGE;
1189 $pageid = $this->page->id;
1190 $total = wiki_count_wiki_page_versions($pageid) - 1;
1192 $oldversion = wiki_get_wiki_page_version($pageid, $this->compare);
1194 $newversion = wiki_get_wiki_page_version($pageid, $this->comparewith);
1196 if ($oldversion && $newversion) {
1198 $oldtext = format_text(file_rewrite_pluginfile_urls($oldversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id));
1199 $newtext = format_text(file_rewrite_pluginfile_urls($newversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id));
1200 list($diff1, $diff2) = ouwiki_diff_html($oldtext, $newtext);
1201 $oldversion->diff = $diff1;
1202 $oldversion->user = wiki_get_user_info($oldversion->userid);
1203 $newversion->diff = $diff2;
1204 $newversion->user = wiki_get_user_info($newversion->userid);
1206 echo $this->wikioutput->diff($pageid, $oldversion, $newversion, array('total' => $total));
1207 } else {
1208 throw new \moodle_exception('versionerror', 'wiki');
1215 * Class that models the behavior of wiki's history page
1218 class page_wiki_history extends page_wiki {
1220 * @var int $paging current page
1222 private $paging;
1225 * @var int @rowsperpage Items per page
1227 private $rowsperpage = 10;
1230 * @var int $allversion if $allversion != 0, all versions will be printed in a signle table
1232 private $allversion;
1235 * The page_wiki_history constructor.
1237 * @param stdClass $wiki Current wiki.
1238 * @param stdClass $subwiki Current subwiki.
1239 * @param stdClass $cm Current course_module.
1240 * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
1242 public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
1243 global $PAGE;
1244 parent::__construct($wiki, $subwiki, $cm, $activesecondarytab);
1245 $PAGE->requires->js_init_call('M.mod_wiki.history', null, true);
1248 function print_header() {
1249 parent::print_header();
1250 $this->print_pagetitle();
1253 function print_pagetitle() {
1254 global $OUTPUT;
1255 $html = '';
1257 $html .= $OUTPUT->container_start('wiki_headingtitle');
1258 $html .= $OUTPUT->heading_with_help(format_string($this->title), 'history', 'wiki', '', '', 3);
1259 $html .= $OUTPUT->container_end();
1260 echo $html;
1263 function print_content() {
1264 global $PAGE;
1266 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1268 $this->print_history_content();
1271 function set_url() {
1272 global $PAGE, $CFG;
1273 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/history.php', array('pageid' => $this->page->id));
1276 function set_paging($paging) {
1277 $this->paging = $paging;
1280 function set_allversion($allversion) {
1281 $this->allversion = $allversion;
1284 protected function create_navbar() {
1285 global $PAGE, $CFG;
1287 parent::create_navbar();
1288 $PAGE->navbar->add(get_string('history', 'wiki'));
1292 * Prints the history for a given wiki page
1294 * @global object $CFG
1295 * @global object $OUTPUT
1296 * @global object $PAGE
1298 private function print_history_content() {
1299 global $CFG, $OUTPUT, $PAGE;
1301 $pageid = $this->page->id;
1302 $offset = $this->paging * $this->rowsperpage;
1303 // vcount is the latest version
1304 $vcount = wiki_count_wiki_page_versions($pageid) - 1;
1305 if ($this->allversion) {
1306 $versions = wiki_get_wiki_page_versions($pageid, 0, $vcount);
1307 } else {
1308 $versions = wiki_get_wiki_page_versions($pageid, $offset, $this->rowsperpage);
1310 // We don't want version 0 to be displayed
1311 // version 0 is blank page
1312 if (end($versions)->version == 0) {
1313 array_pop($versions);
1316 $contents = array();
1318 $version0page = wiki_get_wiki_page_version($this->page->id, 0);
1319 $creator = wiki_get_user_info($version0page->userid);
1320 $a = new StdClass;
1321 $a->date = userdate($this->page->timecreated, get_string('strftimedaydatetime', 'langconfig'));
1322 $a->username = fullname($creator);
1323 echo html_writer::tag ('div', get_string('createddate', 'wiki', $a), array('class' => 'wiki_headingtime'));
1324 if ($vcount > 0) {
1326 /// If there is only one version, we don't need radios nor forms
1327 if (count($versions) == 1) {
1329 $row = array_shift($versions);
1331 $username = wiki_get_user_info($row->userid);
1332 $picture = $OUTPUT->user_picture($username);
1333 $date = userdate($row->timecreated, get_string('strftimedate', 'langconfig'));
1334 $time = userdate($row->timecreated, get_string('strftimetime', 'langconfig'));
1335 $versionid = wiki_get_version($row->id);
1336 $versionlink = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
1337 $userlink = new moodle_url('/user/view.php', array('id' => $username->id, 'course' => $this->cm->course));
1338 $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'));
1340 $table = new html_table();
1341 $table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
1342 $table->data = $contents;
1344 echo html_writer::table($table);
1346 } else {
1348 $checked = $vcount - $offset;
1349 $rowclass = array();
1351 foreach ($versions as $version) {
1352 $user = wiki_get_user_info($version->userid);
1353 $picture = $OUTPUT->user_picture($user, array('popup' => true));
1354 $date = userdate($version->timecreated, get_string('strftimedate'));
1355 $rowclass[] = 'wiki_histnewdate';
1356 $time = userdate($version->timecreated, get_string('strftimetime', 'langconfig'));
1357 $versionid = wiki_get_version($version->id);
1358 if ($versionid) {
1359 $url = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
1360 $viewlink = html_writer::link($url->out(false), $version->version);
1361 } else {
1362 $viewlink = $version->version;
1364 $userlink = new moodle_url('/user/view.php', array('id' => $version->userid, 'course' => $this->cm->course));
1365 $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'));
1368 $table = new html_table();
1370 $icon = $OUTPUT->help_icon('diff', 'wiki');
1372 $table->head = array(get_string('diff', 'wiki') . $icon, get_string('version'), get_string('user'), get_string('modified'), '');
1373 $table->data = $contents;
1374 $table->attributes['class'] = 'table generaltable';
1375 $table->rowclasses = $rowclass;
1377 // Print the form.
1378 echo html_writer::start_tag('form', array('action'=>new moodle_url('/mod/wiki/diff.php'), 'method'=>'get', 'id'=>'diff'));
1379 echo html_writer::tag('div', html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'pageid', 'value'=>$pageid)));
1380 echo html_writer::table($table);
1381 echo html_writer::start_tag('div');
1382 echo html_writer::empty_tag('input', array('type'=>'submit', 'class'=>'wiki_form-button btn btn-secondary', 'value'=>get_string('comparesel', 'wiki')));
1383 echo html_writer::end_tag('div');
1384 echo html_writer::end_tag('form');
1386 } else {
1387 print_string('nohistory', 'wiki');
1389 if (!$this->allversion) {
1390 //$pagingbar = moodle_paging_bar::make($vcount, $this->paging, $this->rowsperpage, $CFG->wwwroot.'/mod/wiki/history.php?pageid='.$pageid.'&amp;');
1391 // $pagingbar->pagevar = $pagevar;
1392 echo $OUTPUT->paging_bar($vcount, $this->paging, $this->rowsperpage, $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $pageid . '&amp;');
1393 //print_paging_bar($vcount, $paging, $rowsperpage,$CFG->wwwroot.'/mod/wiki/history.php?pageid='.$pageid.'&amp;','paging');
1394 } else {
1395 $link = new moodle_url('/mod/wiki/history.php', array('pageid' => $pageid));
1396 $OUTPUT->container(html_writer::link($link->out(false), get_string('viewperpage', 'wiki', $this->rowsperpage)));
1398 if ($vcount > $this->rowsperpage && !$this->allversion) {
1399 $link = new moodle_url('/mod/wiki/history.php', array('pageid' => $pageid, 'allversion' => 1));
1400 $OUTPUT->container(html_writer::link($link->out(false), get_string('viewallhistory', 'wiki')));
1405 * Given an array of values, creates a group of radio buttons to be part of a form
1407 * @param array $options An array of value-label pairs for the radio group (values as keys).
1408 * @param string $name Name of the radiogroup (unique in the form).
1409 * @param string $onclick Function to be executed when the radios are clicked.
1410 * @param string $checked The value that is already checked.
1411 * @param bool $return If true, return the HTML as a string, otherwise print it.
1413 * @return mixed If $return is false, returns nothing, otherwise returns a string of HTML.
1415 private function choose_from_radio($options, $name, $onclick = '', $checked = '', $return = false) {
1417 static $idcounter = 0;
1419 if (!$name) {
1420 $name = 'unnamed';
1423 $output = '<span class="radiogroup ' . $name . "\">\n";
1425 if (!empty($options)) {
1426 $currentradio = 0;
1427 foreach ($options as $value => $label) {
1428 $htmlid = 'auto-rb' . sprintf('%04d', ++$idcounter);
1429 $output .= ' <span class="radioelement ' . $name . ' rb' . $currentradio . "\">";
1430 $output .= '<input name="' . $name . '" id="' . $htmlid . '" type="radio" value="' . $value . '"';
1431 if ($value == $checked) {
1432 $output .= ' checked="checked"';
1434 if ($onclick) {
1435 $output .= ' onclick="' . $onclick . '"';
1437 if ($label === '') {
1438 $output .= ' /> <label for="' . $htmlid . '">' . $value . '</label></span>' . "\n";
1439 } else {
1440 $output .= ' /> <label for="' . $htmlid . '">' . $label . '</label></span>' . "\n";
1442 $currentradio = ($currentradio + 1) % 2;
1446 $output .= '</span>' . "\n";
1448 if ($return) {
1449 return $output;
1450 } else {
1451 echo $output;
1457 * Class that models the behavior of wiki's map page
1460 class page_wiki_map extends page_wiki {
1463 * @var int wiki view option
1465 private $view;
1467 /** @var renderer_base */
1468 protected $output;
1470 function print_header() {
1471 parent::print_header();
1472 $this->print_pagetitle();
1475 function print_content() {
1476 global $CFG, $PAGE;
1478 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1480 if ($this->view > 0) {
1481 //echo '<div><a href="' . $CFG->wwwroot . '/mod/wiki/map.php?pageid=' . $this->page->id . '">' . get_string('backtomapmenu', 'wiki') . '</a></div>';
1484 switch ($this->view) {
1485 case 1:
1486 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1487 $this->print_contributions_content();
1488 break;
1489 case 2:
1490 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1491 $this->print_navigation_content();
1492 break;
1493 case 3:
1494 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1495 $this->print_orphaned_content();
1496 break;
1497 case 4:
1498 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1499 $this->print_index_content();
1500 break;
1501 case 6:
1502 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1503 $this->print_updated_content();
1504 break;
1505 case 5:
1506 default:
1507 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1508 $this->print_page_list_content();
1512 function set_view($option) {
1513 $this->view = $option;
1516 function set_url() {
1517 global $PAGE, $CFG;
1518 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/map.php', array('pageid' => $this->page->id));
1521 protected function create_navbar() {
1522 global $PAGE;
1524 parent::create_navbar();
1525 $PAGE->navbar->add(get_string('map', 'wiki'));
1529 * Prints the contributions tab content
1531 * @uses $OUTPUT, $USER
1534 private function print_contributions_content() {
1535 global $CFG, $OUTPUT, $USER;
1536 $page = $this->page;
1538 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1539 $fresh = wiki_refresh_cachedcontent($page);
1540 $page = $fresh['page'];
1543 $swid = $this->subwiki->id;
1545 $table = new html_table();
1546 $table->head = array(get_string('contributions', 'wiki') . $OUTPUT->help_icon('contributions', 'wiki'));
1547 $table->attributes['class'] = 'generalbox table';
1548 $table->data = array();
1549 $table->rowclasses = array();
1551 $lastversions = array();
1552 $pages = array();
1553 $users = array();
1555 if ($contribs = wiki_get_contributions($swid, $USER->id)) {
1556 foreach ($contribs as $contrib) {
1557 if (!array_key_exists($contrib->pageid, $pages)) {
1558 $page = wiki_get_page($contrib->pageid);
1559 $pages[$contrib->pageid] = $page;
1560 } else {
1561 continue;
1564 if (!array_key_exists($page->id, $lastversions)) {
1565 $version = wiki_get_last_version($page->id);
1566 $lastversions[$page->id] = $version;
1567 } else {
1568 $version = $lastversions[$page->id];
1571 if (!array_key_exists($version->userid, $users)) {
1572 $user = wiki_get_user_info($version->userid);
1573 $users[$version->userid] = $user;
1574 } else {
1575 $user = $users[$version->userid];
1578 $link = wiki_parser_link($page->title, array('swid' => $swid));
1579 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1581 $linkpage = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content'], true, array('context' => $this->modcontext)) . '</a>';
1582 $icon = $OUTPUT->user_picture($user, array('popup' => true));
1584 $table->data[] = array("$icon&nbsp;$linkpage");
1586 } else {
1587 $table->data[] = array(get_string('nocontribs', 'wiki'));
1589 echo html_writer::table($table);
1593 * Prints the navigation tab content
1595 * @uses $OUTPUT
1598 private function print_navigation_content() {
1599 global $OUTPUT;
1600 $page = $this->page;
1602 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1603 $fresh = wiki_refresh_cachedcontent($page);
1604 $page = $fresh['page'];
1607 $tolinks = wiki_get_linked_to_pages($page->id);
1608 $fromlinks = wiki_get_linked_from_pages($page->id);
1610 $table = new html_table();
1611 $table->attributes['class'] = 'wiki_navigation_from table';
1612 $table->head = array(get_string('navigationfrom', 'wiki') . $OUTPUT->help_icon('navigationfrom', 'wiki') . ':');
1613 $table->data = array();
1614 $table->rowclasses = array();
1615 foreach ($fromlinks as $link) {
1616 $lpage = wiki_get_page($link->frompageid);
1617 $link = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
1618 $table->data[] = array(html_writer::link($link->out(false), format_string($lpage->title)));
1621 $table_left = $OUTPUT->container(html_writer::table($table), 'col-md-6');
1623 $table = new html_table();
1624 $table->attributes['class'] = 'wiki_navigation_to table';
1625 $table->head = array(get_string('navigationto', 'wiki') . $OUTPUT->help_icon('navigationto', 'wiki') . ':');
1626 $table->data = array();
1627 $table->rowclasses = array();
1628 foreach ($tolinks as $link) {
1629 if ($link->tomissingpage) {
1630 $viewlink = new moodle_url('/mod/wiki/create.php', array('swid' => $page->subwikiid, 'title' => $link->tomissingpage, 'action' => 'new'));
1631 $table->data[] = array(html_writer::link($viewlink->out(false), format_string($link->tomissingpage), array('class' => 'wiki_newentry')));
1632 } else {
1633 $lpage = wiki_get_page($link->topageid);
1634 $viewlink = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
1635 $table->data[] = array(html_writer::link($viewlink->out(false), format_string($lpage->title)));
1638 $table_right = $OUTPUT->container(html_writer::table($table), 'col-md-6');
1639 echo $OUTPUT->container($table_left . $table_right, 'wiki_navigation_container row');
1643 * Prints the index page tab content
1647 private function print_index_content() {
1648 global $OUTPUT;
1649 $page = $this->page;
1651 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1652 $fresh = wiki_refresh_cachedcontent($page);
1653 $page = $fresh['page'];
1656 // navigation_node get_content calls format string for us
1657 $node = new navigation_node($page->title);
1659 $keys = array();
1660 $tree = array();
1661 $tree = wiki_build_tree($page, $node, $keys);
1663 $table = new html_table();
1664 $table->head = array(get_string('pageindex', 'wiki') . $OUTPUT->help_icon('pageindex', 'wiki'));
1665 $table->attributes['class'] = 'generalbox table';
1666 $table->data[] = array($this->render_navigation_node($tree));
1668 echo html_writer::table($table);
1672 * Prints the page list tab content
1676 private function print_page_list_content() {
1677 global $OUTPUT;
1678 $page = $this->page;
1680 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1681 $fresh = wiki_refresh_cachedcontent($page);
1682 $page = $fresh['page'];
1685 $pages = wiki_get_page_list($this->subwiki->id);
1687 $stdaux = new stdClass();
1688 $strspecial = get_string('special', 'wiki');
1690 foreach ($pages as $page) {
1691 // We need to format the title here to account for any filtering
1692 $letter = format_string($page->title, true, array('context' => $this->modcontext));
1693 $letter = core_text::substr($letter, 0, 1);
1694 if (preg_match('/^[a-zA-Z]$/', $letter)) {
1695 $letter = core_text::strtoupper($letter);
1696 $stdaux->{$letter}[] = wiki_parser_link($page);
1697 } else {
1698 $stdaux->{$strspecial}[] = wiki_parser_link($page);
1702 $table = new html_table();
1703 $table->head = array(get_string('pagelist', 'wiki') . $OUTPUT->help_icon('pagelist', 'wiki'));
1704 $table->attributes['class'] = 'generalbox table';
1705 foreach ($stdaux as $key => $elem) {
1706 $table->data[] = array($key);
1707 foreach ($elem as $e) {
1708 $table->data[] = array(html_writer::link($e['url'], format_string($e['content'], true, array('context' => $this->modcontext))));
1711 echo html_writer::table($table);
1715 * Prints the orphaned tab content
1719 private function print_orphaned_content() {
1720 global $OUTPUT;
1722 $page = $this->page;
1724 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1725 $fresh = wiki_refresh_cachedcontent($page);
1726 $page = $fresh['page'];
1729 $swid = $this->subwiki->id;
1731 $table = new html_table();
1732 $table->head = array(get_string('orphaned', 'wiki') . $OUTPUT->help_icon('orphaned', 'wiki'));
1733 $table->attributes['class'] = 'generalbox table';
1734 $table->data = array();
1735 $table->rowclasses = array();
1737 if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
1738 foreach ($orphanedpages as $page) {
1739 $link = wiki_parser_link($page->title, array('swid' => $swid));
1740 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1741 $table->data[] = array('<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>');
1743 } else {
1744 $table->data[] = array(get_string('noorphanedpages', 'wiki'));
1747 echo html_writer::table($table);
1751 * Prints the updated tab content
1753 * @uses $COURSE, $OUTPUT
1756 private function print_updated_content() {
1757 global $COURSE, $OUTPUT;
1758 $page = $this->page;
1760 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1761 $fresh = wiki_refresh_cachedcontent($page);
1762 $page = $fresh['page'];
1765 $swid = $this->subwiki->id;
1767 $table = new html_table();
1768 $table->head = array(get_string('updatedpages', 'wiki') . $OUTPUT->help_icon('updatedpages', 'wiki'));
1769 $table->attributes['class'] = 'generalbox table';
1770 $table->data = array();
1771 $table->rowclasses = array();
1773 if ($pages = wiki_get_updated_pages_by_subwiki($swid)) {
1774 $strdataux = '';
1775 foreach ($pages as $page) {
1776 $user = wiki_get_user_info($page->userid);
1777 $strdata = date('d M Y', $page->timemodified);
1778 if ($strdata != $strdataux) {
1779 $table->data[] = array($OUTPUT->heading($strdata, 4));
1780 $strdataux = $strdata;
1782 $link = wiki_parser_link($page->title, array('swid' => $swid));
1783 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1785 $linkpage = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>';
1786 $icon = $OUTPUT->user_picture($user, array($COURSE->id));
1787 $table->data[] = array("$icon&nbsp;$linkpage");
1789 } else {
1790 $table->data[] = array(get_string('noupdatedpages', 'wiki'));
1793 echo html_writer::table($table);
1796 protected function render_navigation_node($items, $attrs = array(), $expansionlimit = null, $depth = 1) {
1798 // exit if empty, we don't want an empty ul element
1799 if (count($items) == 0) {
1800 return '';
1803 // array of nested li elements
1804 $lis = array();
1805 foreach ($items as $item) {
1806 if (!$item->display) {
1807 continue;
1809 $content = $item->get_content();
1810 $title = $item->get_title();
1811 if ($item->icon instanceof renderable) {
1812 $icon = $this->wikioutput->render($item->icon);
1813 $content = $icon . '&nbsp;' . $content; // use CSS for spacing of icons
1815 if ($item->helpbutton !== null) {
1816 $content = trim($item->helpbutton) . html_writer::tag('span', $content, array('class' => 'clearhelpbutton'));
1819 if ($content === '') {
1820 continue;
1823 if ($item->action instanceof action_link) {
1824 //TODO: to be replaced with something else
1825 $link = $item->action;
1826 if ($item->hidden) {
1827 $link->add_class('dimmed');
1829 $content = $this->output->render($link);
1830 } else if ($item->action instanceof moodle_url) {
1831 $attributes = array();
1832 if ($title !== '') {
1833 $attributes['title'] = $title;
1835 if ($item->hidden) {
1836 $attributes['class'] = 'dimmed_text';
1838 $content = html_writer::link($item->action, $content, $attributes);
1840 } else if (is_string($item->action) || empty($item->action)) {
1841 $attributes = array();
1842 if ($title !== '') {
1843 $attributes['title'] = $title;
1845 if ($item->hidden) {
1846 $attributes['class'] = 'dimmed_text';
1848 $content = html_writer::tag('span', $content, $attributes);
1851 // this applies to the li item which contains all child lists too
1852 $liclasses = array($item->get_css_type(), 'depth_' . $depth);
1853 if ($item->has_children() && (!$item->forceopen || $item->collapse)) {
1854 $liclasses[] = 'collapsed';
1856 if ($item->isactive === true) {
1857 $liclasses[] = 'current_branch';
1859 $liattr = array('class' => join(' ', $liclasses));
1860 // class attribute on the div item which only contains the item content
1861 $divclasses = array('tree_item');
1862 if ((empty($expansionlimit) || $item->type != $expansionlimit) && ($item->children->count() > 0 || ($item->nodetype == navigation_node::NODETYPE_BRANCH && $item->children->count() == 0 && isloggedin()))) {
1863 $divclasses[] = 'branch';
1864 } else {
1865 $divclasses[] = 'leaf';
1867 if (!empty($item->classes) && count($item->classes) > 0) {
1868 $divclasses[] = join(' ', $item->classes);
1870 $divattr = array('class' => join(' ', $divclasses));
1871 if (!empty($item->id)) {
1872 $divattr['id'] = $item->id;
1874 $content = html_writer::tag('p', $content, $divattr) . $this->render_navigation_node($item->children, array(), $expansionlimit, $depth + 1);
1875 if (!empty($item->preceedwithhr) && $item->preceedwithhr === true) {
1876 $content = html_writer::empty_tag('hr') . $content;
1878 $content = html_writer::tag('li', $content, $liattr);
1879 $lis[] = $content;
1882 if (count($lis)) {
1883 return html_writer::tag('ul', implode("\n", $lis), $attrs);
1884 } else {
1885 return '';
1892 * Class that models the behavior of wiki's restore version page
1895 class page_wiki_restoreversion extends page_wiki {
1896 private $version;
1898 function print_header() {
1899 parent::print_header();
1900 $this->print_pagetitle();
1903 function print_content() {
1904 global $PAGE;
1906 $wiki = $PAGE->activityrecord;
1907 if (wiki_user_can_edit($this->subwiki, $wiki)) {
1908 $this->print_restoreversion();
1909 } else {
1910 echo get_string('cannoteditpage', 'wiki');
1915 function set_url() {
1916 global $PAGE, $CFG;
1917 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
1920 function set_versionid($versionid) {
1921 $this->version = wiki_get_version($versionid);
1924 protected function create_navbar() {
1925 global $PAGE, $CFG;
1927 parent::create_navbar();
1928 $PAGE->navbar->add(get_string('restoreversion', 'wiki'));
1931 protected function setup_tabs($options = array()) {
1932 parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history'));
1936 * This method returns the action bar.
1938 * @param int $pageid The page id.
1939 * @param moodle_url $pageurl The page url.
1940 * @return string The HTML for the action bar.
1942 protected function action_bar(int $pageid, moodle_url $pageurl): string {
1943 // The given page does not require an action bar.
1944 return '';
1948 * Prints the restore version content
1950 * @uses $CFG
1952 * @param page $page The page whose version will be restored
1953 * @param int $versionid The version to be restored
1954 * @param bool $confirm If false, shows a yes/no confirmation page.
1955 * If true, restores the old version and redirects the user to the 'view' tab.
1957 private function print_restoreversion() {
1958 global $OUTPUT;
1960 $version = wiki_get_version($this->version->id);
1962 $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'versionid'=>$version->id, 'sesskey'=>sesskey());
1963 $restoreurl = new moodle_url('/mod/wiki/restoreversion.php', $optionsyes);
1964 $return = new moodle_url('/mod/wiki/viewversion.php', array('pageid'=>$this->page->id, 'versionid'=>$version->id));
1966 echo $OUTPUT->container_start();
1967 echo html_writer::tag('div', get_string('restoreconfirm', 'wiki', $version->version));
1968 echo $OUTPUT->container_start('mt-2', 'wiki_restoreform');
1969 $yesbutton = new single_button($restoreurl, get_string('yes'), 'post');
1970 $nobutton = new single_button($return, get_string('no'), 'post');
1971 $nobutton->class .= ' ml-2';
1972 echo $OUTPUT->render($yesbutton);
1973 echo $OUTPUT->render($nobutton);
1974 echo $OUTPUT->container_end();
1975 echo $OUTPUT->container_end();
1979 * Class that models the behavior of wiki's delete comment confirmation page
1982 class page_wiki_deletecomment extends page_wiki {
1983 private $commentid;
1985 function print_header() {
1986 parent::print_header();
1987 $this->print_pagetitle();
1990 function print_content() {
1991 $this->printconfirmdelete();
1994 function set_url() {
1995 global $PAGE;
1996 $PAGE->set_url('/mod/wiki/instancecomments.php', array('pageid' => $this->page->id, 'commentid' => $this->commentid));
1999 public function set_action($action, $commentid, $content) {
2000 $this->commentid = $commentid;
2003 protected function create_navbar() {
2004 global $PAGE;
2006 parent::create_navbar();
2007 $PAGE->navbar->add(get_string('deletecommentcheck', 'wiki'));
2010 protected function setup_tabs($options = array()) {
2011 parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
2015 * This method returns the action bar.
2017 * @param int $pageid The page id.
2018 * @param moodle_url $pageurl The page url.
2019 * @return string The HTML for the action bar.
2021 protected function action_bar(int $pageid, moodle_url $pageurl): string {
2022 // The given page does not require an action bar.
2023 return '';
2027 * Prints the comment deletion confirmation form
2029 private function printconfirmdelete() {
2030 global $OUTPUT;
2032 $strdeletecheckfull = get_string('deletecommentcheckfull', 'wiki');
2034 //ask confirmation
2035 $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'action'=>'delete', 'commentid'=>$this->commentid, 'sesskey'=>sesskey());
2036 $deleteurl = new moodle_url('/mod/wiki/instancecomments.php', $optionsyes);
2037 $return = new moodle_url('/mod/wiki/comments.php', array('pageid'=>$this->page->id));
2039 echo $OUTPUT->confirm($strdeletecheckfull, $deleteurl, $return);
2044 * Class that models the behavior of wiki's
2045 * save page
2048 class page_wiki_save extends page_wiki_edit {
2050 private $newcontent;
2052 function print_header() {
2055 function print_content() {
2056 global $PAGE;
2058 $context = context_module::instance($this->cm->id);
2059 require_capability('mod/wiki:editpage', $context, NULL, true, 'noeditpermission', 'wiki');
2061 $this->print_save();
2064 function set_newcontent($newcontent) {
2065 $this->newcontent = $newcontent;
2068 protected function set_session_url() {
2071 protected function print_save() {
2072 global $CFG, $USER, $OUTPUT, $PAGE;
2074 $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
2075 if (!empty($this->section)) {
2076 $url .= "&section=" . urlencode($this->section);
2079 $params = array(
2080 'attachmentoptions' => page_wiki_edit::$attachmentoptions,
2081 'format' => $this->format,
2082 'version' => $this->versionnumber,
2083 'contextid' => $this->modcontext->id
2086 if ($this->format != 'html') {
2087 $params['fileitemid'] = $this->page->id;
2088 $params['component'] = 'mod_wiki';
2089 $params['filearea'] = 'attachments';
2092 $form = new mod_wiki_edit_form($url, $params);
2094 $save = false;
2095 $data = false;
2096 if ($data = $form->get_data()) {
2097 if ($this->format == 'html') {
2098 $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id);
2101 if (isset($this->section)) {
2102 $save = wiki_save_section($this->page, $this->section, $data->newcontent, $USER->id);
2103 } else {
2104 $save = wiki_save_page($this->page, $data->newcontent, $USER->id);
2108 if ($save && $data) {
2109 core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $this->page->id, $this->modcontext, $data->tags);
2111 $message = '<p>' . get_string('saving', 'wiki') . '</p>';
2113 if (!empty($save['sections'])) {
2114 foreach ($save['sections'] as $s) {
2115 $message .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
2119 if ($this->versionnumber + 1 != $save['version']) {
2120 $message .= '<p>' . get_string('wrongversionsave', 'wiki') . '</p>';
2123 if (isset($errors) && !empty($errors)) {
2124 foreach ($errors as $e) {
2125 $message .= "<p>" . get_string('filenotuploadederror', 'wiki', $e->get_filename()) . "</p>";
2129 //deleting old locks
2130 wiki_delete_locks($this->page->id, $USER->id, $this->section);
2131 $url = new moodle_url('/mod/wiki/view.php', array('pageid' => $this->page->id, 'group' => $this->subwiki->groupid));
2132 redirect($url);
2133 } else {
2134 throw new \moodle_exception('savingerror', 'wiki');
2140 * Class that models the behavior of wiki's view an old version of a page
2143 class page_wiki_viewversion extends page_wiki {
2145 private $version;
2147 function print_header() {
2148 parent::print_header();
2149 $this->print_pagetitle();
2152 function print_content() {
2153 global $PAGE;
2155 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2157 $this->print_version_view();
2160 function set_url() {
2161 global $PAGE, $CFG;
2162 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2165 function set_versionid($versionid) {
2166 $this->version = wiki_get_version($versionid);
2169 protected function create_navbar() {
2170 global $PAGE, $CFG;
2172 parent::create_navbar();
2173 $PAGE->navbar->add(get_string('history', 'wiki'), $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $this->page->id);
2174 $PAGE->navbar->add(get_string('versionnum', 'wiki', $this->version->version));
2177 protected function setup_tabs($options = array()) {
2178 parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history', 'inactivetabs' => array('edit')));
2182 * This method returns the action bar.
2184 * @param int $pageid The page id.
2185 * @param moodle_url $pageurl The page url.
2186 * @return string The HTML for the action bar.
2188 protected function action_bar(int $pageid, moodle_url $pageurl): string {
2189 $backlink = new moodle_url('/mod/wiki/history.php', ['pageid' => $pageid]);
2190 return html_writer::link($backlink, get_string('back'), ['class' => 'btn btn-secondary mb-4']);
2194 * Given an old page version, output the version content
2196 * @global object $CFG
2197 * @global object $OUTPUT
2198 * @global object $PAGE
2200 private function print_version_view() {
2201 global $CFG, $OUTPUT, $PAGE;
2202 $pageversion = wiki_get_version($this->version->id);
2204 if ($pageversion) {
2205 $restorelink = new moodle_url('/mod/wiki/restoreversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2206 echo html_writer::tag('div', get_string('viewversion', 'wiki', $pageversion->version) . '<br />' .
2207 html_writer::link($restorelink->out(false), '(' . get_string('restorethis', 'wiki') .
2208 ')', array('class' => 'wiki_restore')) . '&nbsp;', array('class' => 'wiki_headingtitle'));
2209 $userinfo = wiki_get_user_info($pageversion->userid);
2210 $heading = '<p><strong>' . get_string('modified', 'wiki') . ':</strong>&nbsp;' . userdate($pageversion->timecreated, get_string('strftimedatetime', 'langconfig'));
2211 $viewlink = new moodle_url('/user/view.php', array('id' => $userinfo->id));
2212 $heading .= '&nbsp;&nbsp;&nbsp;<strong>' . get_string('user') . ':</strong>&nbsp;' . html_writer::link($viewlink->out(false), fullname($userinfo));
2213 $heading .= '&nbsp;&nbsp;&rarr;&nbsp;' . $OUTPUT->user_picture(wiki_get_user_info($pageversion->userid), array('popup' => true)) . '</p>';
2214 echo $OUTPUT->container($heading, 'wiki_headingtime', 'wiki_modifieduser');
2215 $options = array('swid' => $this->subwiki->id, 'pretty_print' => true, 'pageid' => $this->page->id);
2217 $pageversion->content = file_rewrite_pluginfile_urls($pageversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id);
2219 $parseroutput = wiki_parse_content($pageversion->contentformat, $pageversion->content, $options);
2220 $content = $OUTPUT->container(format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true)), false, '', '', true);
2221 echo $OUTPUT->box($content, 'generalbox wiki_contentbox');
2223 } else {
2224 throw new \moodle_exception('versionerror', 'wiki');
2229 class page_wiki_confirmrestore extends page_wiki_save {
2231 private $version;
2233 function set_url() {
2234 global $PAGE, $CFG;
2235 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2238 function print_header() {
2239 $this->set_url();
2242 function print_content() {
2243 global $CFG, $PAGE;
2245 $version = wiki_get_version($this->version->id);
2246 $wiki = $PAGE->activityrecord;
2247 if (wiki_user_can_edit($this->subwiki, $wiki) &&
2248 wiki_restore_page($this->page, $version, $this->modcontext)) {
2249 redirect($CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $this->page->id, get_string('restoring', 'wiki', $version->version), 3);
2250 } else {
2251 throw new \moodle_exception('restoreerror', 'wiki', $version->version);
2255 function set_versionid($versionid) {
2256 $this->version = wiki_get_version($versionid);
2260 class page_wiki_prettyview extends page_wiki {
2262 function __construct($wiki, $subwiki, $cm) {
2263 global $PAGE;
2264 $PAGE->set_pagelayout('embedded');
2265 $PAGE->activityheader->disable();
2266 parent::__construct($wiki, $subwiki, $cm);
2269 function print_header() {
2270 global $OUTPUT;
2271 $this->set_url();
2273 echo $OUTPUT->header();
2274 // Print dialog link.
2275 $printtext = get_string('print', 'wiki');
2276 $printlinkatt = array('onclick' => 'window.print();return false;', 'class' => 'printicon');
2277 $printiconlink = html_writer::link('#', $printtext, $printlinkatt);
2278 echo html_writer::tag('div', $printiconlink, array('class' => 'displayprinticon'));
2279 echo html_writer::tag('h1', format_string($this->title), array('id' => 'wiki_printable_title'));
2282 function print_content() {
2283 global $PAGE;
2285 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2287 $this->print_pretty_view();
2290 function set_url() {
2291 global $PAGE, $CFG;
2293 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/prettyview.php', array('pageid' => $this->page->id));
2296 private function print_pretty_view() {
2297 $version = wiki_get_current_version($this->page->id);
2299 $content = wiki_parse_content($version->contentformat, $version->content, array('printable' => true, 'swid' => $this->subwiki->id, 'pageid' => $this->page->id, 'pretty_print' => true));
2301 $html = $content['parsed_text'];
2302 $id = $this->subwiki->wikiid;
2303 if ($cm = get_coursemodule_from_instance("wiki", $id)) {
2304 $context = context_module::instance($cm->id);
2305 $html = file_rewrite_pluginfile_urls($html, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $this->subwiki->id);
2307 echo '<div id="wiki_printable_content">';
2308 echo format_text($html, FORMAT_HTML);
2309 echo '</div>';
2313 class page_wiki_handlecomments extends page_wiki {
2314 private $action;
2315 private $content;
2316 private $commentid;
2317 private $format;
2319 function print_header() {
2320 $this->set_url();
2323 public function print_content() {
2324 global $CFG, $PAGE, $USER;
2326 if ($this->action == 'add') {
2327 require_capability('mod/wiki:editcomment', $this->modcontext);
2328 $this->add_comment($this->content, $this->commentid);
2329 } else if ($this->action == 'edit') {
2330 require_capability('mod/wiki:editcomment', $this->modcontext);
2332 $comment = wiki_get_comment($this->commentid);
2333 $owner = ($comment->userid == $USER->id);
2335 if ($owner) {
2336 $this->add_comment($this->content, $this->commentid);
2338 } else if ($this->action == 'delete') {
2339 $comment = wiki_get_comment($this->commentid);
2341 $manage = has_capability('mod/wiki:managecomment', $this->modcontext);
2342 $edit = has_capability('mod/wiki:editcomment', $this->modcontext);
2343 $owner = ($comment->userid == $USER->id);
2345 if ($manage || ($owner && $edit)) {
2346 $this->delete_comment($this->commentid);
2347 redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $this->page->id, get_string('deletecomment', 'wiki'), 2);
2348 } else {
2349 throw new \moodle_exception('nopermissiontoeditcomment');
2355 public function set_url() {
2356 global $PAGE, $CFG;
2357 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
2360 public function set_action($action, $commentid, $content) {
2361 $this->action = $action;
2362 $this->commentid = $commentid;
2363 $this->content = $content;
2365 $version = wiki_get_current_version($this->page->id);
2366 $format = $version->contentformat;
2368 $this->format = $format;
2371 private function add_comment($content, $idcomment) {
2372 global $CFG, $PAGE;
2373 require_once($CFG->dirroot . "/mod/wiki/locallib.php");
2375 $pageid = $this->page->id;
2377 wiki_add_comment($this->modcontext, $pageid, $content, $this->format);
2379 if (!$idcomment) {
2380 redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('createcomment', 'wiki'), 2);
2381 } else {
2382 $this->delete_comment($idcomment);
2383 redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('editingcomment', 'wiki'), 2);
2387 private function delete_comment($commentid) {
2388 global $CFG, $PAGE;
2390 $pageid = $this->page->id;
2392 wiki_delete_comment($commentid, $this->modcontext, $pageid);
2397 class page_wiki_lock extends page_wiki_edit {
2399 public function print_header() {
2400 $this->set_url();
2403 protected function set_url() {
2404 global $PAGE, $CFG;
2406 $params = array('pageid' => $this->page->id);
2408 if ($this->section) {
2409 $params['section'] = $this->section;
2412 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/lock.php', $params);
2415 protected function set_session_url() {
2418 public function print_content() {
2419 global $USER, $PAGE;
2421 require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki');
2423 wiki_set_lock($this->page->id, $USER->id, $this->section);
2426 public function print_footer() {
2430 class page_wiki_overridelocks extends page_wiki_edit {
2431 function print_header() {
2432 $this->set_url();
2435 function print_content() {
2436 global $CFG, $PAGE;
2438 require_capability('mod/wiki:overridelock', $this->modcontext, NULL, true, 'nooverridelockpermission', 'wiki');
2440 wiki_delete_locks($this->page->id, null, $this->section, true, true);
2442 $args = "pageid=" . $this->page->id;
2444 if (!empty($this->section)) {
2445 $args .= "&section=" . urlencode($this->section);
2448 redirect($CFG->wwwroot . '/mod/wiki/edit.php?' . $args, get_string('overridinglocks', 'wiki'), 2);
2451 function set_url() {
2452 global $PAGE, $CFG;
2454 $params = array('pageid' => $this->page->id);
2456 if (!empty($this->section)) {
2457 $params['section'] = $this->section;
2460 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/overridelocks.php', $params);
2463 protected function set_session_url() {
2466 private function print_overridelocks() {
2467 global $CFG;
2469 wiki_delete_locks($this->page->id, null, $this->section, true, true);
2471 $args = "pageid=" . $this->page->id;
2473 if (!empty($this->section)) {
2474 $args .= "&section=" . urlencode($this->section);
2477 redirect($CFG->wwwroot . '/mod/wiki/edit.php?' . $args, get_string('overridinglocks', 'wiki'), 2);
2483 * This class will let user to delete wiki pages and page versions
2486 class page_wiki_admin extends page_wiki {
2488 public $view, $action;
2489 public $listorphan = false;
2492 * Constructor
2494 * @global object $PAGE
2495 * @param mixed $wiki instance of wiki
2496 * @param mixed $subwiki instance of subwiki
2497 * @param stdClass $cm course module
2498 * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
2500 public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
2501 global $PAGE;
2502 parent::__construct($wiki, $subwiki, $cm, $activesecondarytab);
2503 $PAGE->requires->js_init_call('M.mod_wiki.deleteversion', null, true);
2507 * Prints header for wiki page
2509 function print_header() {
2510 parent::print_header();
2511 $this->print_pagetitle();
2515 * This function will display administration view to users with managewiki capability
2517 function print_content() {
2518 //make sure anyone trying to access this page has managewiki capabilities
2519 require_capability('mod/wiki:managewiki', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2521 //update wiki cache if timedout
2522 $page = $this->page;
2523 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
2524 $fresh = wiki_refresh_cachedcontent($page);
2525 $page = $fresh['page'];
2528 //dispaly admin menu
2529 echo $this->wikioutput->menu_admin($this->page->id, $this->view);
2531 //Display appropriate admin view
2532 switch ($this->view) {
2533 case 1: //delete page view
2534 $this->print_delete_content($this->listorphan);
2535 break;
2536 case 2: //delete version view
2537 $this->print_delete_version();
2538 break;
2539 default: //default is delete view
2540 $this->print_delete_content($this->listorphan);
2541 break;
2546 * Sets admin view option
2548 * @param int $view page view id
2549 * @param bool $listorphan is only valid for view 1.
2551 public function set_view($view, $listorphan = true) {
2552 $this->view = $view;
2553 $this->listorphan = $listorphan;
2557 * Sets page url
2559 * @global object $PAGE
2560 * @global object $CFG
2562 function set_url() {
2563 global $PAGE, $CFG;
2564 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/admin.php', array('pageid' => $this->page->id));
2568 * sets navigation bar for the page
2570 * @global object $PAGE
2572 protected function create_navbar() {
2573 global $PAGE;
2575 parent::create_navbar();
2576 $PAGE->navbar->add(get_string('admin', 'wiki'));
2580 * Show wiki page delete options
2582 * @param bool $showorphan
2584 protected function print_delete_content($showorphan = true) {
2585 $contents = array();
2586 $table = new html_table();
2587 $table->head = array('', get_string('pagename','wiki'));
2588 $table->attributes['class'] = 'table generaltable';
2589 $swid = $this->subwiki->id;
2590 if ($showorphan) {
2591 if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
2592 $this->add_page_delete_options($orphanedpages, $swid, $table);
2593 } else {
2594 $table->data[] = array('', get_string('noorphanedpages', 'wiki'));
2596 } else {
2597 if ($pages = wiki_get_page_list($swid)) {
2598 $this->add_page_delete_options($pages, $swid, $table);
2599 } else {
2600 $table->data[] = array('', get_string('nopages', 'wiki'));
2604 ///Print the form
2605 echo html_writer::start_tag('form', array(
2606 'action' => new moodle_url('/mod/wiki/admin.php'),
2607 'method' => 'post'));
2608 echo html_writer::tag('div', html_writer::empty_tag('input', array(
2609 'type' => 'hidden',
2610 'name' => 'pageid',
2611 'value' => $this->page->id)));
2613 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
2614 echo html_writer::table($table);
2615 echo html_writer::start_tag('div');
2616 if (!$showorphan) {
2617 echo html_writer::empty_tag('input', array(
2618 'type' => 'submit',
2619 'class' => 'wiki_form-button',
2620 'value' => get_string('listorphan', 'wiki'),
2621 'sesskey' => sesskey()));
2622 } else {
2623 echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'listall', 'value'=>'1'));
2624 echo html_writer::empty_tag('input', array(
2625 'type' => 'submit',
2626 'class' => 'wiki_form-button btn btn-secondary',
2627 'value' => get_string('listall', 'wiki'),
2628 'sesskey' => sesskey()));
2630 echo html_writer::end_tag('div');
2631 echo html_writer::end_tag('form');
2635 * helper function for print_delete_content. This will add data to the table.
2637 * @global object $OUTPUT
2638 * @param array $pages objects of wiki pages in subwiki
2639 * @param int $swid id of subwiki
2640 * @param object $table reference to the table in which data needs to be added
2642 protected function add_page_delete_options($pages, $swid, &$table) {
2643 global $OUTPUT;
2644 foreach ($pages as $page) {
2645 $link = wiki_parser_link($page->title, array('swid' => $swid));
2646 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
2647 $pagelink = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>';
2648 $urledit = new moodle_url('/mod/wiki/edit.php', array('pageid' => $page->id, 'sesskey' => sesskey()));
2649 $urldelete = new moodle_url('/mod/wiki/admin.php', array(
2650 'pageid' => $this->page->id,
2651 'delete' => $page->id,
2652 'option' => $this->view,
2653 'listall' => !$this->listorphan?'1': '',
2654 'sesskey' => sesskey()));
2656 $editlinks = $OUTPUT->action_icon($urledit, new pix_icon('t/edit', get_string('edit')));
2657 $editlinks .= $OUTPUT->action_icon($urldelete, new pix_icon('t/delete', get_string('delete')));
2658 $table->data[] = array($editlinks, $pagelink);
2663 * Prints lists of versions which can be deleted
2665 * @global core_renderer $OUTPUT
2666 * @global moodle_page $PAGE
2668 private function print_delete_version() {
2669 global $OUTPUT, $PAGE;
2670 $pageid = $this->page->id;
2672 // versioncount is the latest version
2673 $versioncount = wiki_count_wiki_page_versions($pageid) - 1;
2674 $versions = wiki_get_wiki_page_versions($pageid, 0, $versioncount);
2676 // We don't want version 0 to be displayed
2677 // version 0 is blank page
2678 if (end($versions)->version == 0) {
2679 array_pop($versions);
2682 $contents = array();
2683 $version0page = wiki_get_wiki_page_version($this->page->id, 0);
2684 $creator = wiki_get_user_info($version0page->userid);
2685 $a = new stdClass();
2686 $a->date = userdate($this->page->timecreated, get_string('strftimedaydatetime', 'langconfig'));
2687 $a->username = fullname($creator);
2688 echo $OUTPUT->heading(get_string('createddate', 'wiki', $a), 4);
2689 if ($versioncount > 0) {
2690 /// If there is only one version, we don't need radios nor forms
2691 if (count($versions) == 1) {
2692 $row = array_shift($versions);
2693 $username = wiki_get_user_info($row->userid);
2694 $picture = $OUTPUT->user_picture($username);
2695 $date = userdate($row->timecreated, get_string('strftimedate', 'langconfig'));
2696 $time = userdate($row->timecreated, get_string('strftimetime', 'langconfig'));
2697 $versionid = wiki_get_version($row->id);
2698 $versionlink = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
2699 $userlink = new moodle_url('/user/view.php', array('id' => $username->id, 'course' => $this->cm->course));
2700 $picturelink = $picture . html_writer::link($userlink->out(false), fullname($username));
2701 $historydate = $OUTPUT->container($date, 'wiki_histdate');
2702 $contents[] = array('', html_writer::link($versionlink->out(false), $row->version), $picturelink, $time, $historydate);
2704 //Show current version
2705 $table = new html_table();
2706 $table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
2707 $table->data = $contents;
2709 echo html_writer::table($table);
2710 } else {
2711 $lastdate = '';
2712 $rowclass = array();
2714 foreach ($versions as $version) {
2715 $user = wiki_get_user_info($version->userid);
2716 $picture = $OUTPUT->user_picture($user, array('popup' => true));
2717 $date = userdate($version->timecreated, get_string('strftimedate'));
2718 if ($date == $lastdate) {
2719 $date = '';
2720 $rowclass[] = '';
2721 } else {
2722 $lastdate = $date;
2723 $rowclass[] = 'wiki_histnewdate';
2726 $time = userdate($version->timecreated, get_string('strftimetime', 'langconfig'));
2727 $versionid = wiki_get_version($version->id);
2728 if ($versionid) {
2729 $url = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
2730 $viewlink = html_writer::link($url->out(false), $version->version);
2731 } else {
2732 $viewlink = $version->version;
2735 $userlink = new moodle_url('/user/view.php', array('id' => $version->userid, 'course' => $this->cm->course));
2736 $picturelink = $picture . html_writer::link($userlink->out(false), fullname($user));
2737 $historydate = $OUTPUT->container($date, 'wiki_histdate');
2738 $radiofromelement = $this->choose_from_radio(array($version->version => null), 'fromversion', 'M.mod_wiki.deleteversion()', $versioncount, true);
2739 $radiotoelement = $this->choose_from_radio(array($version->version => null), 'toversion', 'M.mod_wiki.deleteversion()', $versioncount, true);
2740 $contents[] = array( $radiofromelement . $radiotoelement, $viewlink, $picturelink, $time, $historydate);
2743 $table = new html_table();
2744 $table->head = array(get_string('deleteversions', 'wiki'), get_string('version'), get_string('user'), get_string('modified'), '');
2745 $table->data = $contents;
2746 $table->attributes['class'] = 'table generaltable';
2747 $table->rowclasses = $rowclass;
2749 ///Print the form
2750 echo html_writer::start_tag('form', array('action'=>new moodle_url('/mod/wiki/admin.php'), 'method' => 'post'));
2751 echo html_writer::tag('div', html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'pageid', 'value' => $pageid)));
2752 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
2753 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
2754 echo html_writer::table($table);
2755 echo html_writer::start_tag('div');
2756 echo html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'wiki_form-button btn btn-secondary', 'value' => get_string('deleteversions', 'wiki')));
2757 echo html_writer::end_tag('div');
2758 echo html_writer::end_tag('form');
2760 } else {
2761 print_string('nohistory', 'wiki');
2766 * Given an array of values, creates a group of radio buttons to be part of a form
2767 * helper function for print_delete_version
2769 * @param array $options An array of value-label pairs for the radio group (values as keys).
2770 * @param string $name Name of the radiogroup (unique in the form).
2771 * @param string $onclick Function to be executed when the radios are clicked.
2772 * @param string $checked The value that is already checked.
2773 * @param bool $return If true, return the HTML as a string, otherwise print it.
2775 * @return mixed If $return is false, returns nothing, otherwise returns a string of HTML.
2777 private function choose_from_radio($options, $name, $onclick = '', $checked = '', $return = false) {
2779 static $idcounter = 0;
2781 if (!$name) {
2782 $name = 'unnamed';
2785 $output = '<span class="radiogroup ' . $name . "\">\n";
2787 if (!empty($options)) {
2788 $currentradio = 0;
2789 foreach ($options as $value => $label) {
2790 $htmlid = 'auto-rb' . sprintf('%04d', ++$idcounter);
2791 $output .= ' <span class="radioelement ' . $name . ' rb' . $currentradio . "\">";
2792 $output .= '<input name="' . $name . '" id="' . $htmlid . '" type="radio" value="' . $value . '"';
2793 if ($value == $checked) {
2794 $output .= ' checked="checked"';
2796 if ($onclick) {
2797 $output .= ' onclick="' . $onclick . '"';
2799 if ($label === '') {
2800 $output .= ' /> <label for="' . $htmlid . '">' . $value . '</label></span>' . "\n";
2801 } else {
2802 $output .= ' /> <label for="' . $htmlid . '">' . $label . '</label></span>' . "\n";
2804 $currentradio = ($currentradio + 1) % 2;
2808 $output .= '</span>' . "\n";
2810 if ($return) {
2811 return $output;
2812 } else {
2813 echo $output;