Merge branch 'MDL-81457-main' of https://github.com/andrewnicols/moodle
[moodle.git] / mod / wiki / pagelib.php
blob11c1887d57a8bbf876982494e3bcb658edc30e94
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 $cell4 = new html_table_cell();
664 $cell5 = new html_table_cell();
666 $row1 = new html_table_row();
667 $row1->cells[] = $cell1;
668 $row1->cells[] = $cell2;
669 $row2 = new html_table_row();
670 $row2->cells[] = $cell3;
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);
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);
684 $row2->cells[] = $cell4;
686 $t->data = array($row1, $row2);
688 $canedit = $candelete = false;
689 if ((has_capability('mod/wiki:editcomment', $this->modcontext)) and ($USER->id == $user->id)) {
690 $candelete = $canedit = true;
692 if ((has_capability('mod/wiki:managecomment', $this->modcontext))) {
693 $candelete = true;
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')));
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'),
707 array('class' => 'iconsmall')));
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;
718 echo html_writer::tag('div', html_writer::table($t), array('class'=>'no-overflow'));
723 function set_url() {
724 global $PAGE, $CFG;
725 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
728 protected function create_navbar() {
729 global $PAGE, $CFG;
731 parent::create_navbar();
732 $PAGE->navbar->add(get_string('comments', 'wiki'));
738 * Class that models the behavior of wiki's edit comment
740 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
742 class page_wiki_editcomment extends page_wiki {
743 private $comment;
744 private $action;
745 private $form;
746 private $format;
748 function set_url() {
749 global $PAGE, $CFG;
750 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
753 function print_header() {
754 parent::print_header();
755 $this->print_pagetitle();
758 function print_content() {
759 global $PAGE;
761 require_capability('mod/wiki:editcomment', $this->modcontext, NULL, true, 'noeditcommentpermission', 'wiki');
763 if ($this->action == 'add') {
764 $this->add_comment_form();
765 } else if ($this->action == 'edit') {
766 $this->edit_comment_form($this->comment);
770 function set_action($action, $comment) {
771 global $CFG;
772 require_once($CFG->dirroot . '/mod/wiki/comments_form.php');
774 $this->action = $action;
775 $this->comment = $comment;
776 $version = wiki_get_current_version($this->page->id);
777 $this->format = $version->contentformat;
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);
785 protected function create_navbar() {
786 global $PAGE, $CFG;
788 $PAGE->navbar->add(get_string('comments', 'wiki'), $CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $this->page->id);
790 if ($this->action == 'add') {
791 $PAGE->navbar->add(get_string('insertcomment', 'wiki'));
792 } else {
793 $PAGE->navbar->add(get_string('editcomment', 'wiki'));
797 protected function setup_tabs($options = array()) {
798 parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
802 * This method returns the action bar.
804 * @param int $pageid The page id.
805 * @param moodle_url $pageurl The page url.
806 * @return string The HTML for the action bar.
808 protected function action_bar(int $pageid, moodle_url $pageurl): string {
809 // The given page does not require an action bar.
810 return '';
813 private function add_comment_form() {
814 global $CFG;
815 require_once($CFG->dirroot . '/mod/wiki/editors/wiki_editor.php');
817 $pageid = $this->page->id;
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');
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');
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);
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);
851 * Wiki page search page
853 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
855 class page_wiki_search extends page_wiki {
856 private $search_result;
858 protected function create_navbar() {
859 global $PAGE, $CFG;
861 $PAGE->navbar->add(format_string($this->title));
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);
874 function set_url() {
875 global $PAGE, $CFG;
876 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/search.php');
879 function print_header() {
880 global $PAGE;
882 parent::print_header();
884 $wiki = $PAGE->activityrecord;
885 $page = (object)array('title' => $wiki->firstpagetitle);
886 $this->wikioutput->wiki_print_subwiki_selector($wiki, $this->subwiki, $page, 'search');
889 function print_content() {
890 global $PAGE;
892 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
894 echo $this->wikioutput->search_result($this->search_result, $this->subwiki);
900 * Class that models the behavior of wiki's
901 * create page
904 class page_wiki_create extends page_wiki {
906 private $format;
907 private $swid;
908 private $wid;
909 private $action;
910 private $mform;
911 private $groups;
913 function print_header() {
914 $this->set_url();
915 parent::print_header();
918 function set_url() {
919 global $PAGE, $CFG;
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;
929 } else {
930 $params['action'] = 'create';
932 $PAGE->set_url(new moodle_url('/mod/wiki/create.php', $params));
935 function set_format($format) {
936 $this->format = $format;
939 function set_wid($wid) {
940 $this->wid = $wid;
943 function set_swid($swid) {
944 $this->swid = $swid;
947 function set_availablegroups($group) {
948 $this->groups = $group;
951 function set_action($action) {
952 global $PAGE;
953 $this->action = $action;
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;
962 $this->mform = new mod_wiki_create_form($url->out(false), $options);
965 protected function create_navbar() {
966 global $PAGE;
967 // navigation_node::get_content formats this before printing.
968 $PAGE->navbar->add($this->title);
971 function print_content($pagetitle = '') {
972 global $PAGE;
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;
980 $data->pageformat = $PAGE->activityrecord->defaultformat;
982 $this->mform->set_data($data);
983 $this->mform->display();
986 function create_page($pagetitle) {
987 global $USER, $PAGE;
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';
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);
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);
1011 $this->page = $id;
1012 return $id;
1016 class page_wiki_preview extends page_wiki_edit {
1018 private $newcontent;
1020 function print_header() {
1021 global $PAGE, $CFG;
1023 parent::print_header();
1027 function print_content() {
1028 global $PAGE;
1030 require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki');
1032 $this->print_preview();
1035 function set_newcontent($newcontent) {
1036 $this->newcontent = $newcontent;
1039 function set_url() {
1040 global $PAGE, $CFG;
1042 $params = array('pageid' => $this->page->id
1045 if (isset($this->section)) {
1046 $params['section'] = $this->section;
1049 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/edit.php', $params);
1052 protected function setup_tabs($options = array()) {
1053 parent::setup_tabs(array('linkedwhenactive' => 'view', 'activetab' => 'view'));
1056 protected function check_locks() {
1057 return true;
1060 protected function print_preview() {
1061 global $CFG, $PAGE, $OUTPUT;
1063 $version = wiki_get_current_version($this->page->id);
1064 $format = $version->contentformat;
1065 $content = $version->content;
1067 $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
1068 if (!empty($this->section)) {
1069 $url .= "&section=" . urlencode($this->section);
1071 $params = array(
1072 'attachmentoptions' => page_wiki_edit::$attachmentoptions,
1073 'format' => $this->format,
1074 'version' => $this->versionnumber,
1075 'contextid' => $this->modcontext->id
1078 if ($this->format != 'html') {
1079 $params['component'] = 'mod_wiki';
1080 $params['filearea'] = 'attachments';
1081 $params['fileitemid'] = $this->page->id;
1083 $form = new mod_wiki_edit_form($url, $params);
1086 $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true);
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'];
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;
1104 $this->print_edit($content);
1111 * Class that models the behavior of wiki's
1112 * view differences
1115 class page_wiki_diff extends page_wiki {
1117 private $compare;
1118 private $comparewith;
1120 function print_header() {
1121 global $OUTPUT;
1123 parent::print_header();
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'));
1133 * Print the diff view
1135 function print_content() {
1136 global $PAGE;
1138 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1140 $this->print_diff_content();
1143 function set_url() {
1144 global $PAGE, $CFG;
1146 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/diff.php', array('pageid' => $this->page->id, 'comparewith' => $this->comparewith, 'compare' => $this->compare));
1149 function set_comparison($compare, $comparewith) {
1150 $this->compare = $compare;
1151 $this->comparewith = $comparewith;
1154 protected function create_navbar() {
1155 global $PAGE, $CFG;
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'));
1162 protected function setup_tabs($options = array()) {
1163 parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history'));
1167 * This method returns the action bar.
1169 * @param int $pageid The page id.
1170 * @param moodle_url $pageurl The page url.
1171 * @return string The HTML for the action bar.
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']);
1179 * Given two versions of a page, prints a page displaying the differences between them.
1181 * @global object $CFG
1182 * @global object $OUTPUT
1183 * @global object $PAGE
1185 private function print_diff_content() {
1186 global $CFG, $OUTPUT, $PAGE;
1188 $pageid = $this->page->id;
1189 $total = wiki_count_wiki_page_versions($pageid) - 1;
1191 $oldversion = wiki_get_wiki_page_version($pageid, $this->compare);
1193 $newversion = wiki_get_wiki_page_version($pageid, $this->comparewith);
1195 if ($oldversion && $newversion) {
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);
1205 echo $this->wikioutput->diff($pageid, $oldversion, $newversion, array('total' => $total));
1206 } else {
1207 throw new \moodle_exception('versionerror', 'wiki');
1214 * Class that models the behavior of wiki's history page
1217 class page_wiki_history extends page_wiki {
1219 * @var int $paging current page
1221 private $paging;
1224 * @var int @rowsperpage Items per page
1226 private $rowsperpage = 10;
1229 * @var int $allversion if $allversion != 0, all versions will be printed in a signle table
1231 private $allversion;
1234 * The page_wiki_history constructor.
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
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);
1247 function print_header() {
1248 parent::print_header();
1249 $this->print_pagetitle();
1252 function print_pagetitle() {
1253 global $OUTPUT;
1254 $html = '';
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;
1262 function print_content() {
1263 global $PAGE;
1265 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1267 $this->print_history_content();
1270 function set_url() {
1271 global $PAGE, $CFG;
1272 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/history.php', array('pageid' => $this->page->id));
1275 function set_paging($paging) {
1276 $this->paging = $paging;
1279 function set_allversion($allversion) {
1280 $this->allversion = $allversion;
1283 protected function create_navbar() {
1284 global $PAGE, $CFG;
1286 parent::create_navbar();
1287 $PAGE->navbar->add(get_string('history', 'wiki'));
1291 * Prints the history for a given wiki page
1293 * @global object $CFG
1294 * @global object $OUTPUT
1295 * @global object $PAGE
1297 private function print_history_content() {
1298 global $CFG, $OUTPUT, $PAGE;
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);
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);
1315 $contents = array();
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) {
1325 /// If there is only one version, we don't need radios nor forms
1326 if (count($versions) == 1) {
1328 $row = array_shift($versions);
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'));
1339 $table = new html_table();
1340 $table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
1341 $table->data = $contents;
1343 echo html_writer::table($table);
1345 } else {
1347 $checked = $vcount - $offset;
1348 $rowclass = array();
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;
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'));
1367 $table = new html_table();
1369 $icon = $OUTPUT->help_icon('diff', 'wiki');
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;
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');
1385 } else {
1386 print_string('nohistory', 'wiki');
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)));
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')));
1404 * Given an array of values, creates a group of radio buttons to be part of a form
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.
1412 * @return mixed If $return is false, returns nothing, otherwise returns a string of HTML.
1414 private function choose_from_radio($options, $name, $onclick = '', $checked = '', $return = false) {
1416 static $idcounter = 0;
1418 if (!$name) {
1419 $name = 'unnamed';
1422 $output = '<span class="radiogroup ' . $name . "\">\n";
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"';
1433 if ($onclick) {
1434 $output .= ' onclick="' . $onclick . '"';
1436 if ($label === '') {
1437 $output .= ' /> <label for="' . $htmlid . '">' . $value . '</label></span>' . "\n";
1438 } else {
1439 $output .= ' /> <label for="' . $htmlid . '">' . $label . '</label></span>' . "\n";
1441 $currentradio = ($currentradio + 1) % 2;
1445 $output .= '</span>' . "\n";
1447 if ($return) {
1448 return $output;
1449 } else {
1450 echo $output;
1456 * Class that models the behavior of wiki's map page
1459 class page_wiki_map extends page_wiki {
1462 * @var int wiki view option
1464 private $view;
1466 /** @var renderer_base */
1467 protected $output;
1469 function print_header() {
1470 parent::print_header();
1471 $this->print_pagetitle();
1474 function print_content() {
1475 global $CFG, $PAGE;
1477 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
1479 if ($this->view > 0) {
1480 //echo '<div><a href="' . $CFG->wwwroot . '/mod/wiki/map.php?pageid=' . $this->page->id . '">' . get_string('backtomapmenu', 'wiki') . '</a></div>';
1483 switch ($this->view) {
1484 case 1:
1485 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1486 $this->print_contributions_content();
1487 break;
1488 case 2:
1489 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1490 $this->print_navigation_content();
1491 break;
1492 case 3:
1493 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1494 $this->print_orphaned_content();
1495 break;
1496 case 4:
1497 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1498 $this->print_index_content();
1499 break;
1500 case 6:
1501 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1502 $this->print_updated_content();
1503 break;
1504 case 5:
1505 default:
1506 echo $this->wikioutput->menu_map($this->page->id, $this->view);
1507 $this->print_page_list_content();
1511 function set_view($option) {
1512 $this->view = $option;
1515 function set_url() {
1516 global $PAGE, $CFG;
1517 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/map.php', array('pageid' => $this->page->id));
1520 protected function create_navbar() {
1521 global $PAGE;
1523 parent::create_navbar();
1524 $PAGE->navbar->add(get_string('map', 'wiki'));
1528 * Prints the contributions tab content
1530 * @uses $OUTPUT, $USER
1533 private function print_contributions_content() {
1534 global $CFG, $OUTPUT, $USER;
1535 $page = $this->page;
1537 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1538 $fresh = wiki_refresh_cachedcontent($page);
1539 $page = $fresh['page'];
1542 $swid = $this->subwiki->id;
1544 $table = new html_table();
1545 $table->head = array(get_string('contributions', 'wiki') . $OUTPUT->help_icon('contributions', 'wiki'));
1546 $table->attributes['class'] = 'generalbox table';
1547 $table->data = array();
1548 $table->rowclasses = array();
1550 $lastversions = array();
1551 $pages = array();
1552 $users = array();
1554 if ($contribs = wiki_get_contributions($swid, $USER->id)) {
1555 foreach ($contribs as $contrib) {
1556 if (!array_key_exists($contrib->pageid, $pages)) {
1557 $page = wiki_get_page($contrib->pageid);
1558 $pages[$contrib->pageid] = $page;
1559 } else {
1560 continue;
1563 if (!array_key_exists($page->id, $lastversions)) {
1564 $version = wiki_get_last_version($page->id);
1565 $lastversions[$page->id] = $version;
1566 } else {
1567 $version = $lastversions[$page->id];
1570 if (!array_key_exists($version->userid, $users)) {
1571 $user = wiki_get_user_info($version->userid);
1572 $users[$version->userid] = $user;
1573 } else {
1574 $user = $users[$version->userid];
1577 $link = wiki_parser_link($page->title, array('swid' => $swid));
1578 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1580 $linkpage = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content'], true, array('context' => $this->modcontext)) . '</a>';
1581 $icon = $OUTPUT->user_picture($user, array('popup' => true));
1583 $table->data[] = array("$icon&nbsp;$linkpage");
1585 } else {
1586 $table->data[] = array(get_string('nocontribs', 'wiki'));
1588 echo html_writer::table($table);
1592 * Prints the navigation tab content
1594 * @uses $OUTPUT
1597 private function print_navigation_content() {
1598 global $OUTPUT;
1599 $page = $this->page;
1601 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1602 $fresh = wiki_refresh_cachedcontent($page);
1603 $page = $fresh['page'];
1606 $tolinks = wiki_get_linked_to_pages($page->id);
1607 $fromlinks = wiki_get_linked_from_pages($page->id);
1609 $table = new html_table();
1610 $table->attributes['class'] = 'wiki_navigation_from table';
1611 $table->head = array(get_string('navigationfrom', 'wiki') . $OUTPUT->help_icon('navigationfrom', 'wiki') . ':');
1612 $table->data = array();
1613 $table->rowclasses = array();
1614 foreach ($fromlinks as $link) {
1615 $lpage = wiki_get_page($link->frompageid);
1616 $link = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
1617 $table->data[] = array(html_writer::link($link->out(false), format_string($lpage->title)));
1620 $table_left = $OUTPUT->container(html_writer::table($table), 'col-md-6');
1622 $table = new html_table();
1623 $table->attributes['class'] = 'wiki_navigation_to table';
1624 $table->head = array(get_string('navigationto', 'wiki') . $OUTPUT->help_icon('navigationto', 'wiki') . ':');
1625 $table->data = array();
1626 $table->rowclasses = array();
1627 foreach ($tolinks as $link) {
1628 if ($link->tomissingpage) {
1629 $viewlink = new moodle_url('/mod/wiki/create.php', array('swid' => $page->subwikiid, 'title' => $link->tomissingpage, 'action' => 'new'));
1630 $table->data[] = array(html_writer::link($viewlink->out(false), format_string($link->tomissingpage), array('class' => 'wiki_newentry')));
1631 } else {
1632 $lpage = wiki_get_page($link->topageid);
1633 $viewlink = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
1634 $table->data[] = array(html_writer::link($viewlink->out(false), format_string($lpage->title)));
1637 $table_right = $OUTPUT->container(html_writer::table($table), 'col-md-6');
1638 echo $OUTPUT->container($table_left . $table_right, 'wiki_navigation_container row');
1642 * Prints the index page tab content
1646 private function print_index_content() {
1647 global $OUTPUT;
1648 $page = $this->page;
1650 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1651 $fresh = wiki_refresh_cachedcontent($page);
1652 $page = $fresh['page'];
1655 // navigation_node get_content calls format string for us
1656 $node = new navigation_node($page->title);
1658 $keys = array();
1659 $tree = array();
1660 $tree = wiki_build_tree($page, $node, $keys);
1662 $table = new html_table();
1663 $table->head = array(get_string('pageindex', 'wiki') . $OUTPUT->help_icon('pageindex', 'wiki'));
1664 $table->attributes['class'] = 'generalbox table';
1665 $table->data[] = array($this->render_navigation_node($tree));
1667 echo html_writer::table($table);
1671 * Prints the page list tab content
1675 private function print_page_list_content() {
1676 global $OUTPUT;
1677 $page = $this->page;
1679 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1680 $fresh = wiki_refresh_cachedcontent($page);
1681 $page = $fresh['page'];
1684 $pages = wiki_get_page_list($this->subwiki->id);
1686 $stdaux = new stdClass();
1687 $strspecial = get_string('special', 'wiki');
1689 foreach ($pages as $page) {
1690 // We need to format the title here to account for any filtering
1691 $letter = format_string($page->title, true, array('context' => $this->modcontext));
1692 $letter = core_text::substr($letter, 0, 1);
1693 if (preg_match('/^[a-zA-Z]$/', $letter)) {
1694 $letter = core_text::strtoupper($letter);
1695 $stdaux->{$letter}[] = wiki_parser_link($page);
1696 } else {
1697 $stdaux->{$strspecial}[] = wiki_parser_link($page);
1701 $table = new html_table();
1702 $table->head = array(get_string('pagelist', 'wiki') . $OUTPUT->help_icon('pagelist', 'wiki'));
1703 $table->attributes['class'] = 'generalbox table';
1704 foreach ($stdaux as $key => $elem) {
1705 $table->data[] = array($key);
1706 foreach ($elem as $e) {
1707 $table->data[] = array(html_writer::link($e['url'], format_string($e['content'], true, array('context' => $this->modcontext))));
1710 echo html_writer::table($table);
1714 * Prints the orphaned tab content
1718 private function print_orphaned_content() {
1719 global $OUTPUT;
1721 $page = $this->page;
1723 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1724 $fresh = wiki_refresh_cachedcontent($page);
1725 $page = $fresh['page'];
1728 $swid = $this->subwiki->id;
1730 $table = new html_table();
1731 $table->head = array(get_string('orphaned', 'wiki') . $OUTPUT->help_icon('orphaned', 'wiki'));
1732 $table->attributes['class'] = 'generalbox table';
1733 $table->data = array();
1734 $table->rowclasses = array();
1736 if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
1737 foreach ($orphanedpages as $page) {
1738 $link = wiki_parser_link($page->title, array('swid' => $swid));
1739 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1740 $table->data[] = array('<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>');
1742 } else {
1743 $table->data[] = array(get_string('noorphanedpages', 'wiki'));
1746 echo html_writer::table($table);
1750 * Prints the updated tab content
1752 * @uses $COURSE, $OUTPUT
1755 private function print_updated_content() {
1756 global $COURSE, $OUTPUT;
1757 $page = $this->page;
1759 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1760 $fresh = wiki_refresh_cachedcontent($page);
1761 $page = $fresh['page'];
1764 $swid = $this->subwiki->id;
1766 $table = new html_table();
1767 $table->head = array(get_string('updatedpages', 'wiki') . $OUTPUT->help_icon('updatedpages', 'wiki'));
1768 $table->attributes['class'] = 'generalbox table';
1769 $table->data = array();
1770 $table->rowclasses = array();
1772 if ($pages = wiki_get_updated_pages_by_subwiki($swid)) {
1773 $strdataux = '';
1774 foreach ($pages as $page) {
1775 $user = wiki_get_user_info($page->userid);
1776 $strdata = date('d M Y', $page->timemodified);
1777 if ($strdata != $strdataux) {
1778 $table->data[] = array($OUTPUT->heading($strdata, 4));
1779 $strdataux = $strdata;
1781 $link = wiki_parser_link($page->title, array('swid' => $swid));
1782 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
1784 $linkpage = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>';
1785 $icon = $OUTPUT->user_picture($user, array($COURSE->id));
1786 $table->data[] = array("$icon&nbsp;$linkpage");
1788 } else {
1789 $table->data[] = array(get_string('noupdatedpages', 'wiki'));
1792 echo html_writer::table($table);
1795 protected function render_navigation_node($items, $attrs = array(), $expansionlimit = null, $depth = 1) {
1797 // exit if empty, we don't want an empty ul element
1798 if (count($items) == 0) {
1799 return '';
1802 // array of nested li elements
1803 $lis = array();
1804 foreach ($items as $item) {
1805 if (!$item->display) {
1806 continue;
1808 $content = $item->get_content();
1809 $title = $item->get_title();
1810 if ($item->icon instanceof renderable) {
1811 $icon = $this->wikioutput->render($item->icon);
1812 $content = $icon . '&nbsp;' . $content; // use CSS for spacing of icons
1814 if ($item->helpbutton !== null) {
1815 $content = trim($item->helpbutton) . html_writer::tag('span', $content, array('class' => 'clearhelpbutton'));
1818 if ($content === '') {
1819 continue;
1822 if ($item->action instanceof action_link) {
1823 //TODO: to be replaced with something else
1824 $link = $item->action;
1825 if ($item->hidden) {
1826 $link->add_class('dimmed');
1828 $content = $this->output->render($link);
1829 } else if ($item->action instanceof moodle_url) {
1830 $attributes = array();
1831 if ($title !== '') {
1832 $attributes['title'] = $title;
1834 if ($item->hidden) {
1835 $attributes['class'] = 'dimmed_text';
1837 $content = html_writer::link($item->action, $content, $attributes);
1839 } else if (is_string($item->action) || empty($item->action)) {
1840 $attributes = array();
1841 if ($title !== '') {
1842 $attributes['title'] = $title;
1844 if ($item->hidden) {
1845 $attributes['class'] = 'dimmed_text';
1847 $content = html_writer::tag('span', $content, $attributes);
1850 // this applies to the li item which contains all child lists too
1851 $liclasses = array($item->get_css_type(), 'depth_' . $depth);
1852 if ($item->has_children() && (!$item->forceopen || $item->collapse)) {
1853 $liclasses[] = 'collapsed';
1855 if ($item->isactive === true) {
1856 $liclasses[] = 'current_branch';
1858 $liattr = array('class' => join(' ', $liclasses));
1859 // class attribute on the div item which only contains the item content
1860 $divclasses = array('tree_item');
1861 if ((empty($expansionlimit) || $item->type != $expansionlimit) && ($item->children->count() > 0 || ($item->nodetype == navigation_node::NODETYPE_BRANCH && $item->children->count() == 0 && isloggedin()))) {
1862 $divclasses[] = 'branch';
1863 } else {
1864 $divclasses[] = 'leaf';
1866 if (!empty($item->classes) && count($item->classes) > 0) {
1867 $divclasses[] = join(' ', $item->classes);
1869 $divattr = array('class' => join(' ', $divclasses));
1870 if (!empty($item->id)) {
1871 $divattr['id'] = $item->id;
1873 $content = html_writer::tag('p', $content, $divattr) . $this->render_navigation_node($item->children, array(), $expansionlimit, $depth + 1);
1874 if (!empty($item->preceedwithhr) && $item->preceedwithhr === true) {
1875 $content = html_writer::empty_tag('hr') . $content;
1877 $content = html_writer::tag('li', $content, $liattr);
1878 $lis[] = $content;
1881 if (count($lis)) {
1882 return html_writer::tag('ul', implode("\n", $lis), $attrs);
1883 } else {
1884 return '';
1891 * Class that models the behavior of wiki's restore version page
1894 class page_wiki_restoreversion extends page_wiki {
1895 private $version;
1897 function print_header() {
1898 parent::print_header();
1899 $this->print_pagetitle();
1902 function print_content() {
1903 global $PAGE;
1905 $wiki = $PAGE->activityrecord;
1906 if (wiki_user_can_edit($this->subwiki, $wiki)) {
1907 $this->print_restoreversion();
1908 } else {
1909 echo get_string('cannoteditpage', 'wiki');
1914 function set_url() {
1915 global $PAGE, $CFG;
1916 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
1919 function set_versionid($versionid) {
1920 $this->version = wiki_get_version($versionid);
1923 protected function create_navbar() {
1924 global $PAGE, $CFG;
1926 parent::create_navbar();
1927 $PAGE->navbar->add(get_string('restoreversion', 'wiki'));
1930 protected function setup_tabs($options = array()) {
1931 parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history'));
1935 * This method returns the action bar.
1937 * @param int $pageid The page id.
1938 * @param moodle_url $pageurl The page url.
1939 * @return string The HTML for the action bar.
1941 protected function action_bar(int $pageid, moodle_url $pageurl): string {
1942 // The given page does not require an action bar.
1943 return '';
1947 * Prints the restore version content
1949 * @uses $CFG
1951 * @param page $page The page whose version will be restored
1952 * @param int $versionid The version to be restored
1953 * @param bool $confirm If false, shows a yes/no confirmation page.
1954 * If true, restores the old version and redirects the user to the 'view' tab.
1956 private function print_restoreversion() {
1957 global $OUTPUT;
1959 $version = wiki_get_version($this->version->id);
1961 $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'versionid'=>$version->id, 'sesskey'=>sesskey());
1962 $restoreurl = new moodle_url('/mod/wiki/restoreversion.php', $optionsyes);
1963 $return = new moodle_url('/mod/wiki/viewversion.php', array('pageid'=>$this->page->id, 'versionid'=>$version->id));
1965 echo $OUTPUT->container_start();
1966 echo html_writer::tag('div', get_string('restoreconfirm', 'wiki', $version->version));
1967 echo $OUTPUT->container_start('mt-2', 'wiki_restoreform');
1968 $yesbutton = new single_button($restoreurl, get_string('yes'), 'post');
1969 $nobutton = new single_button($return, get_string('no'), 'post');
1970 $nobutton->class .= ' ml-2';
1971 echo $OUTPUT->render($yesbutton);
1972 echo $OUTPUT->render($nobutton);
1973 echo $OUTPUT->container_end();
1974 echo $OUTPUT->container_end();
1978 * Class that models the behavior of wiki's delete comment confirmation page
1981 class page_wiki_deletecomment extends page_wiki {
1982 private $commentid;
1984 function print_header() {
1985 parent::print_header();
1986 $this->print_pagetitle();
1989 function print_content() {
1990 $this->printconfirmdelete();
1993 function set_url() {
1994 global $PAGE;
1995 $PAGE->set_url('/mod/wiki/instancecomments.php', array('pageid' => $this->page->id, 'commentid' => $this->commentid));
1998 public function set_action($action, $commentid, $content) {
1999 $this->commentid = $commentid;
2002 protected function create_navbar() {
2003 global $PAGE;
2005 parent::create_navbar();
2006 $PAGE->navbar->add(get_string('deletecommentcheck', 'wiki'));
2009 protected function setup_tabs($options = array()) {
2010 parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
2014 * This method returns the action bar.
2016 * @param int $pageid The page id.
2017 * @param moodle_url $pageurl The page url.
2018 * @return string The HTML for the action bar.
2020 protected function action_bar(int $pageid, moodle_url $pageurl): string {
2021 // The given page does not require an action bar.
2022 return '';
2026 * Prints the comment deletion confirmation form
2028 private function printconfirmdelete() {
2029 global $OUTPUT;
2031 $strdeletecheckfull = get_string('deletecommentcheckfull', 'wiki');
2033 //ask confirmation
2034 $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'action'=>'delete', 'commentid'=>$this->commentid, 'sesskey'=>sesskey());
2035 $deleteurl = new moodle_url('/mod/wiki/instancecomments.php', $optionsyes);
2036 $return = new moodle_url('/mod/wiki/comments.php', array('pageid'=>$this->page->id));
2038 echo $OUTPUT->confirm($strdeletecheckfull, $deleteurl, $return);
2043 * Class that models the behavior of wiki's
2044 * save page
2047 class page_wiki_save extends page_wiki_edit {
2049 private $newcontent;
2051 function print_header() {
2054 function print_content() {
2055 global $PAGE;
2057 $context = context_module::instance($this->cm->id);
2058 require_capability('mod/wiki:editpage', $context, NULL, true, 'noeditpermission', 'wiki');
2060 $this->print_save();
2063 function set_newcontent($newcontent) {
2064 $this->newcontent = $newcontent;
2067 protected function set_session_url() {
2070 protected function print_save() {
2071 global $CFG, $USER, $OUTPUT, $PAGE;
2073 $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id;
2074 if (!empty($this->section)) {
2075 $url .= "&section=" . urlencode($this->section);
2078 $params = array(
2079 'attachmentoptions' => page_wiki_edit::$attachmentoptions,
2080 'format' => $this->format,
2081 'version' => $this->versionnumber,
2082 'contextid' => $this->modcontext->id
2085 if ($this->format != 'html') {
2086 $params['fileitemid'] = $this->page->id;
2087 $params['component'] = 'mod_wiki';
2088 $params['filearea'] = 'attachments';
2091 $form = new mod_wiki_edit_form($url, $params);
2093 $save = false;
2094 $data = false;
2095 if ($data = $form->get_data()) {
2096 if ($this->format == 'html') {
2097 $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id);
2100 if (isset($this->section)) {
2101 $save = wiki_save_section($this->page, $this->section, $data->newcontent, $USER->id);
2102 } else {
2103 $save = wiki_save_page($this->page, $data->newcontent, $USER->id);
2107 if ($save && $data) {
2108 core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $this->page->id, $this->modcontext, $data->tags);
2110 $message = '<p>' . get_string('saving', 'wiki') . '</p>';
2112 if (!empty($save['sections'])) {
2113 foreach ($save['sections'] as $s) {
2114 $message .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
2118 if ($this->versionnumber + 1 != $save['version']) {
2119 $message .= '<p>' . get_string('wrongversionsave', 'wiki') . '</p>';
2122 if (isset($errors) && !empty($errors)) {
2123 foreach ($errors as $e) {
2124 $message .= "<p>" . get_string('filenotuploadederror', 'wiki', $e->get_filename()) . "</p>";
2128 //deleting old locks
2129 wiki_delete_locks($this->page->id, $USER->id, $this->section);
2130 $url = new moodle_url('/mod/wiki/view.php', array('pageid' => $this->page->id, 'group' => $this->subwiki->groupid));
2131 redirect($url);
2132 } else {
2133 throw new \moodle_exception('savingerror', 'wiki');
2139 * Class that models the behavior of wiki's view an old version of a page
2142 class page_wiki_viewversion extends page_wiki {
2144 private $version;
2146 function print_header() {
2147 parent::print_header();
2148 $this->print_pagetitle();
2151 function print_content() {
2152 global $PAGE;
2154 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2156 $this->print_version_view();
2159 function set_url() {
2160 global $PAGE, $CFG;
2161 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2164 function set_versionid($versionid) {
2165 $this->version = wiki_get_version($versionid);
2168 protected function create_navbar() {
2169 global $PAGE, $CFG;
2171 parent::create_navbar();
2172 $PAGE->navbar->add(get_string('history', 'wiki'), $CFG->wwwroot . '/mod/wiki/history.php?pageid=' . $this->page->id);
2173 $PAGE->navbar->add(get_string('versionnum', 'wiki', $this->version->version));
2176 protected function setup_tabs($options = array()) {
2177 parent::setup_tabs(array('linkedwhenactive' => 'history', 'activetab' => 'history', 'inactivetabs' => array('edit')));
2181 * This method returns the action bar.
2183 * @param int $pageid The page id.
2184 * @param moodle_url $pageurl The page url.
2185 * @return string The HTML for the action bar.
2187 protected function action_bar(int $pageid, moodle_url $pageurl): string {
2188 $backlink = new moodle_url('/mod/wiki/history.php', ['pageid' => $pageid]);
2189 return html_writer::link($backlink, get_string('back'), ['class' => 'btn btn-secondary mb-4']);
2193 * Given an old page version, output the version content
2195 * @global object $CFG
2196 * @global object $OUTPUT
2197 * @global object $PAGE
2199 private function print_version_view() {
2200 global $CFG, $OUTPUT, $PAGE;
2201 $pageversion = wiki_get_version($this->version->id);
2203 if ($pageversion) {
2204 $restorelink = new moodle_url('/mod/wiki/restoreversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2205 echo html_writer::tag('div', get_string('viewversion', 'wiki', $pageversion->version) . '<br />' .
2206 html_writer::link($restorelink->out(false), '(' . get_string('restorethis', 'wiki') .
2207 ')', array('class' => 'wiki_restore')) . '&nbsp;', array('class' => 'wiki_headingtitle'));
2208 $userinfo = wiki_get_user_info($pageversion->userid);
2209 $heading = '<p><strong>' . get_string('modified', 'wiki') . ':</strong>&nbsp;' . userdate($pageversion->timecreated, get_string('strftimedatetime', 'langconfig'));
2210 $viewlink = new moodle_url('/user/view.php', array('id' => $userinfo->id));
2211 $heading .= '&nbsp;&nbsp;&nbsp;<strong>' . get_string('user') . ':</strong>&nbsp;' . html_writer::link($viewlink->out(false), fullname($userinfo));
2212 $heading .= '&nbsp;&nbsp;&rarr;&nbsp;' . $OUTPUT->user_picture(wiki_get_user_info($pageversion->userid), array('popup' => true)) . '</p>';
2213 echo $OUTPUT->container($heading, 'wiki_headingtime', 'wiki_modifieduser');
2214 $options = array('swid' => $this->subwiki->id, 'pretty_print' => true, 'pageid' => $this->page->id);
2216 $pageversion->content = file_rewrite_pluginfile_urls($pageversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id);
2218 $parseroutput = wiki_parse_content($pageversion->contentformat, $pageversion->content, $options);
2219 $content = $OUTPUT->container(format_text($parseroutput['parsed_text'], FORMAT_HTML, ['overflowdiv' => true]));
2220 echo $OUTPUT->box($content, 'generalbox wiki_contentbox');
2222 } else {
2223 throw new \moodle_exception('versionerror', 'wiki');
2228 class page_wiki_confirmrestore extends page_wiki_save {
2230 private $version;
2232 function set_url() {
2233 global $PAGE, $CFG;
2234 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/viewversion.php', array('pageid' => $this->page->id, 'versionid' => $this->version->id));
2237 function print_header() {
2238 $this->set_url();
2241 function print_content() {
2242 global $CFG, $PAGE;
2244 $version = wiki_get_version($this->version->id);
2245 $wiki = $PAGE->activityrecord;
2246 if (wiki_user_can_edit($this->subwiki, $wiki) &&
2247 wiki_restore_page($this->page, $version, $this->modcontext)) {
2248 redirect($CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $this->page->id, get_string('restoring', 'wiki', $version->version), 3);
2249 } else {
2250 throw new \moodle_exception('restoreerror', 'wiki', $version->version);
2254 function set_versionid($versionid) {
2255 $this->version = wiki_get_version($versionid);
2259 class page_wiki_prettyview extends page_wiki {
2261 function __construct($wiki, $subwiki, $cm) {
2262 global $PAGE;
2263 $PAGE->set_pagelayout('embedded');
2264 $PAGE->activityheader->disable();
2265 parent::__construct($wiki, $subwiki, $cm);
2268 function print_header() {
2269 global $OUTPUT;
2270 $this->set_url();
2272 echo $OUTPUT->header();
2273 // Print dialog link.
2274 $printtext = get_string('print', 'wiki');
2275 $printlinkatt = array('onclick' => 'window.print();return false;', 'class' => 'printicon');
2276 $printiconlink = html_writer::link('#', $printtext, $printlinkatt);
2277 echo html_writer::tag('div', $printiconlink, array('class' => 'displayprinticon'));
2278 echo html_writer::tag('h1', format_string($this->title), array('id' => 'wiki_printable_title'));
2281 function print_content() {
2282 global $PAGE;
2284 require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2286 $this->print_pretty_view();
2289 function set_url() {
2290 global $PAGE, $CFG;
2292 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/prettyview.php', array('pageid' => $this->page->id));
2295 private function print_pretty_view() {
2296 $version = wiki_get_current_version($this->page->id);
2298 $content = wiki_parse_content($version->contentformat, $version->content, array('printable' => true, 'swid' => $this->subwiki->id, 'pageid' => $this->page->id, 'pretty_print' => true));
2300 $html = $content['parsed_text'];
2301 $id = $this->subwiki->wikiid;
2302 if ($cm = get_coursemodule_from_instance("wiki", $id)) {
2303 $context = context_module::instance($cm->id);
2304 $html = file_rewrite_pluginfile_urls($html, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $this->subwiki->id);
2306 echo '<div id="wiki_printable_content">';
2307 echo format_text($html, FORMAT_HTML);
2308 echo '</div>';
2312 class page_wiki_handlecomments extends page_wiki {
2313 private $action;
2314 private $content;
2315 private $commentid;
2316 private $format;
2318 function print_header() {
2319 $this->set_url();
2322 public function print_content() {
2323 global $CFG, $PAGE, $USER;
2325 if ($this->action == 'add') {
2326 require_capability('mod/wiki:editcomment', $this->modcontext);
2327 $this->add_comment($this->content, $this->commentid);
2328 } else if ($this->action == 'edit') {
2329 require_capability('mod/wiki:editcomment', $this->modcontext);
2331 $comment = wiki_get_comment($this->commentid);
2332 $owner = ($comment->userid == $USER->id);
2334 if ($owner) {
2335 $this->add_comment($this->content, $this->commentid);
2337 } else if ($this->action == 'delete') {
2338 $comment = wiki_get_comment($this->commentid);
2340 $manage = has_capability('mod/wiki:managecomment', $this->modcontext);
2341 $edit = has_capability('mod/wiki:editcomment', $this->modcontext);
2342 $owner = ($comment->userid == $USER->id);
2344 if ($manage || ($owner && $edit)) {
2345 $this->delete_comment($this->commentid);
2346 redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $this->page->id, get_string('deletecomment', 'wiki'), 2);
2347 } else {
2348 throw new \moodle_exception('nopermissiontoeditcomment');
2354 public function set_url() {
2355 global $PAGE, $CFG;
2356 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/comments.php', array('pageid' => $this->page->id));
2359 public function set_action($action, $commentid, $content) {
2360 $this->action = $action;
2361 $this->commentid = $commentid;
2362 $this->content = $content;
2364 $version = wiki_get_current_version($this->page->id);
2365 $format = $version->contentformat;
2367 $this->format = $format;
2370 private function add_comment($content, $idcomment) {
2371 global $CFG, $PAGE;
2372 require_once($CFG->dirroot . "/mod/wiki/locallib.php");
2374 $pageid = $this->page->id;
2376 wiki_add_comment($this->modcontext, $pageid, $content, $this->format);
2378 if (!$idcomment) {
2379 redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('createcomment', 'wiki'), 2);
2380 } else {
2381 $this->delete_comment($idcomment);
2382 redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('editingcomment', 'wiki'), 2);
2386 private function delete_comment($commentid) {
2387 global $CFG, $PAGE;
2389 $pageid = $this->page->id;
2391 wiki_delete_comment($commentid, $this->modcontext, $pageid);
2396 class page_wiki_lock extends page_wiki_edit {
2398 public function print_header() {
2399 $this->set_url();
2402 protected function set_url() {
2403 global $PAGE, $CFG;
2405 $params = array('pageid' => $this->page->id);
2407 if ($this->section) {
2408 $params['section'] = $this->section;
2411 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/lock.php', $params);
2414 protected function set_session_url() {
2417 public function print_content() {
2418 global $USER, $PAGE;
2420 require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki');
2422 wiki_set_lock($this->page->id, $USER->id, $this->section);
2425 public function print_footer() {
2429 class page_wiki_overridelocks extends page_wiki_edit {
2430 function print_header() {
2431 $this->set_url();
2434 function print_content() {
2435 global $CFG, $PAGE;
2437 require_capability('mod/wiki:overridelock', $this->modcontext, NULL, true, 'nooverridelockpermission', 'wiki');
2439 wiki_delete_locks($this->page->id, null, $this->section, true, true);
2441 $args = "pageid=" . $this->page->id;
2443 if (!empty($this->section)) {
2444 $args .= "&section=" . urlencode($this->section);
2447 redirect($CFG->wwwroot . '/mod/wiki/edit.php?' . $args, get_string('overridinglocks', 'wiki'), 2);
2450 function set_url() {
2451 global $PAGE, $CFG;
2453 $params = array('pageid' => $this->page->id);
2455 if (!empty($this->section)) {
2456 $params['section'] = $this->section;
2459 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/overridelocks.php', $params);
2462 protected function set_session_url() {
2465 private function print_overridelocks() {
2466 global $CFG;
2468 wiki_delete_locks($this->page->id, null, $this->section, true, true);
2470 $args = "pageid=" . $this->page->id;
2472 if (!empty($this->section)) {
2473 $args .= "&section=" . urlencode($this->section);
2476 redirect($CFG->wwwroot . '/mod/wiki/edit.php?' . $args, get_string('overridinglocks', 'wiki'), 2);
2482 * This class will let user to delete wiki pages and page versions
2485 class page_wiki_admin extends page_wiki {
2487 public $view, $action;
2488 public $listorphan = false;
2491 * Constructor
2493 * @global object $PAGE
2494 * @param mixed $wiki instance of wiki
2495 * @param mixed $subwiki instance of subwiki
2496 * @param stdClass $cm course module
2497 * @param string|null $activesecondarytab Secondary navigation node to be activated on the page, if required
2499 public function __construct($wiki, $subwiki, $cm, ?string $activesecondarytab = null) {
2500 global $PAGE;
2501 parent::__construct($wiki, $subwiki, $cm, $activesecondarytab);
2502 $PAGE->requires->js_init_call('M.mod_wiki.deleteversion', null, true);
2506 * Prints header for wiki page
2508 function print_header() {
2509 parent::print_header();
2510 $this->print_pagetitle();
2514 * This function will display administration view to users with managewiki capability
2516 function print_content() {
2517 //make sure anyone trying to access this page has managewiki capabilities
2518 require_capability('mod/wiki:managewiki', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki');
2520 //update wiki cache if timedout
2521 $page = $this->page;
2522 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
2523 $fresh = wiki_refresh_cachedcontent($page);
2524 $page = $fresh['page'];
2527 //dispaly admin menu
2528 echo $this->wikioutput->menu_admin($this->page->id, $this->view);
2530 //Display appropriate admin view
2531 switch ($this->view) {
2532 case 1: //delete page view
2533 $this->print_delete_content($this->listorphan);
2534 break;
2535 case 2: //delete version view
2536 $this->print_delete_version();
2537 break;
2538 default: //default is delete view
2539 $this->print_delete_content($this->listorphan);
2540 break;
2545 * Sets admin view option
2547 * @param int $view page view id
2548 * @param bool $listorphan is only valid for view 1.
2550 public function set_view($view, $listorphan = true) {
2551 $this->view = $view;
2552 $this->listorphan = $listorphan;
2556 * Sets page url
2558 * @global object $PAGE
2559 * @global object $CFG
2561 function set_url() {
2562 global $PAGE, $CFG;
2563 $PAGE->set_url($CFG->wwwroot . '/mod/wiki/admin.php', array('pageid' => $this->page->id));
2567 * sets navigation bar for the page
2569 * @global object $PAGE
2571 protected function create_navbar() {
2572 global $PAGE;
2574 parent::create_navbar();
2575 $PAGE->navbar->add(get_string('admin', 'wiki'));
2579 * Show wiki page delete options
2581 * @param bool $showorphan
2583 protected function print_delete_content($showorphan = true) {
2584 $contents = array();
2585 $table = new html_table();
2586 $table->head = array('', get_string('pagename','wiki'));
2587 $table->attributes['class'] = 'table generaltable';
2588 $swid = $this->subwiki->id;
2589 if ($showorphan) {
2590 if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
2591 $this->add_page_delete_options($orphanedpages, $swid, $table);
2592 } else {
2593 $table->data[] = array('', get_string('noorphanedpages', 'wiki'));
2595 } else {
2596 if ($pages = wiki_get_page_list($swid)) {
2597 $this->add_page_delete_options($pages, $swid, $table);
2598 } else {
2599 $table->data[] = array('', get_string('nopages', 'wiki'));
2603 ///Print the form
2604 echo html_writer::start_tag('form', array(
2605 'action' => new moodle_url('/mod/wiki/admin.php'),
2606 'method' => 'post'));
2607 echo html_writer::tag('div', html_writer::empty_tag('input', array(
2608 'type' => 'hidden',
2609 'name' => 'pageid',
2610 'value' => $this->page->id)));
2612 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
2613 echo html_writer::table($table);
2614 echo html_writer::start_tag('div');
2615 if (!$showorphan) {
2616 echo html_writer::empty_tag('input', array(
2617 'type' => 'submit',
2618 'class' => 'wiki_form-button',
2619 'value' => get_string('listorphan', 'wiki'),
2620 'sesskey' => sesskey()));
2621 } else {
2622 echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'listall', 'value'=>'1'));
2623 echo html_writer::empty_tag('input', array(
2624 'type' => 'submit',
2625 'class' => 'wiki_form-button btn btn-secondary',
2626 'value' => get_string('listall', 'wiki'),
2627 'sesskey' => sesskey()));
2629 echo html_writer::end_tag('div');
2630 echo html_writer::end_tag('form');
2634 * helper function for print_delete_content. This will add data to the table.
2636 * @global object $OUTPUT
2637 * @param array $pages objects of wiki pages in subwiki
2638 * @param int $swid id of subwiki
2639 * @param object $table reference to the table in which data needs to be added
2641 protected function add_page_delete_options($pages, $swid, &$table) {
2642 global $OUTPUT;
2643 foreach ($pages as $page) {
2644 $link = wiki_parser_link($page->title, array('swid' => $swid));
2645 $class = ($link['new']) ? 'class="wiki_newentry"' : '';
2646 $pagelink = '<a href="' . $link['url'] . '"' . $class . '>' . format_string($link['content']) . '</a>';
2647 $urledit = new moodle_url('/mod/wiki/edit.php', array('pageid' => $page->id, 'sesskey' => sesskey()));
2648 $urldelete = new moodle_url('/mod/wiki/admin.php', array(
2649 'pageid' => $this->page->id,
2650 'delete' => $page->id,
2651 'option' => $this->view,
2652 'listall' => !$this->listorphan?'1': '',
2653 'sesskey' => sesskey()));
2655 $editlinks = $OUTPUT->action_icon($urledit, new pix_icon('t/edit', get_string('edit')));
2656 $editlinks .= $OUTPUT->action_icon($urldelete, new pix_icon('t/delete', get_string('delete')));
2657 $table->data[] = array($editlinks, $pagelink);
2662 * Prints lists of versions which can be deleted
2664 * @global core_renderer $OUTPUT
2665 * @global moodle_page $PAGE
2667 private function print_delete_version() {
2668 global $OUTPUT, $PAGE;
2669 $pageid = $this->page->id;
2671 // versioncount is the latest version
2672 $versioncount = wiki_count_wiki_page_versions($pageid) - 1;
2673 $versions = wiki_get_wiki_page_versions($pageid, 0, $versioncount);
2675 // We don't want version 0 to be displayed
2676 // version 0 is blank page
2677 if (end($versions)->version == 0) {
2678 array_pop($versions);
2681 $contents = array();
2682 $version0page = wiki_get_wiki_page_version($this->page->id, 0);
2683 $creator = wiki_get_user_info($version0page->userid);
2684 $a = new stdClass();
2685 $a->date = userdate($this->page->timecreated, get_string('strftimedaydatetime', 'langconfig'));
2686 $a->username = fullname($creator);
2687 echo $OUTPUT->heading(get_string('createddate', 'wiki', $a), 4);
2688 if ($versioncount > 0) {
2689 /// If there is only one version, we don't need radios nor forms
2690 if (count($versions) == 1) {
2691 $row = array_shift($versions);
2692 $username = wiki_get_user_info($row->userid);
2693 $picture = $OUTPUT->user_picture($username);
2694 $date = userdate($row->timecreated, get_string('strftimedate', 'langconfig'));
2695 $time = userdate($row->timecreated, get_string('strftimetime', 'langconfig'));
2696 $versionid = wiki_get_version($row->id);
2697 $versionlink = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
2698 $userlink = new moodle_url('/user/view.php', array('id' => $username->id, 'course' => $this->cm->course));
2699 $picturelink = $picture . html_writer::link($userlink->out(false), fullname($username));
2700 $historydate = $OUTPUT->container($date, 'wiki_histdate');
2701 $contents[] = array('', html_writer::link($versionlink->out(false), $row->version), $picturelink, $time, $historydate);
2703 //Show current version
2704 $table = new html_table();
2705 $table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
2706 $table->data = $contents;
2708 echo html_writer::table($table);
2709 } else {
2710 $lastdate = '';
2711 $rowclass = array();
2713 foreach ($versions as $version) {
2714 $user = wiki_get_user_info($version->userid);
2715 $picture = $OUTPUT->user_picture($user, array('popup' => true));
2716 $date = userdate($version->timecreated, get_string('strftimedate'));
2717 if ($date == $lastdate) {
2718 $date = '';
2719 $rowclass[] = '';
2720 } else {
2721 $lastdate = $date;
2722 $rowclass[] = 'wiki_histnewdate';
2725 $time = userdate($version->timecreated, get_string('strftimetime', 'langconfig'));
2726 $versionid = wiki_get_version($version->id);
2727 if ($versionid) {
2728 $url = new moodle_url('/mod/wiki/viewversion.php', array('pageid' => $pageid, 'versionid' => $versionid->id));
2729 $viewlink = html_writer::link($url->out(false), $version->version);
2730 } else {
2731 $viewlink = $version->version;
2734 $userlink = new moodle_url('/user/view.php', array('id' => $version->userid, 'course' => $this->cm->course));
2735 $picturelink = $picture . html_writer::link($userlink->out(false), fullname($user));
2736 $historydate = $OUTPUT->container($date, 'wiki_histdate');
2737 $radiofromelement = $this->choose_from_radio(array($version->version => null), 'fromversion', 'M.mod_wiki.deleteversion()', $versioncount, true);
2738 $radiotoelement = $this->choose_from_radio(array($version->version => null), 'toversion', 'M.mod_wiki.deleteversion()', $versioncount, true);
2739 $contents[] = array( $radiofromelement . $radiotoelement, $viewlink, $picturelink, $time, $historydate);
2742 $table = new html_table();
2743 $table->head = array(get_string('deleteversions', 'wiki'), get_string('version'), get_string('user'), get_string('modified'), '');
2744 $table->data = $contents;
2745 $table->attributes['class'] = 'table generaltable';
2746 $table->rowclasses = $rowclass;
2748 ///Print the form
2749 echo html_writer::start_tag('form', array('action'=>new moodle_url('/mod/wiki/admin.php'), 'method' => 'post'));
2750 echo html_writer::tag('div', html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'pageid', 'value' => $pageid)));
2751 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
2752 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
2753 echo html_writer::table($table);
2754 echo html_writer::start_tag('div');
2755 echo html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'wiki_form-button btn btn-secondary', 'value' => get_string('deleteversions', 'wiki')));
2756 echo html_writer::end_tag('div');
2757 echo html_writer::end_tag('form');
2759 } else {
2760 print_string('nohistory', 'wiki');
2765 * Given an array of values, creates a group of radio buttons to be part of a form
2766 * helper function for print_delete_version
2768 * @param array $options An array of value-label pairs for the radio group (values as keys).
2769 * @param string $name Name of the radiogroup (unique in the form).
2770 * @param string $onclick Function to be executed when the radios are clicked.
2771 * @param string $checked The value that is already checked.
2772 * @param bool $return If true, return the HTML as a string, otherwise print it.
2774 * @return mixed If $return is false, returns nothing, otherwise returns a string of HTML.
2776 private function choose_from_radio($options, $name, $onclick = '', $checked = '', $return = false) {
2778 static $idcounter = 0;
2780 if (!$name) {
2781 $name = 'unnamed';
2784 $output = '<span class="radiogroup ' . $name . "\">\n";
2786 if (!empty($options)) {
2787 $currentradio = 0;
2788 foreach ($options as $value => $label) {
2789 $htmlid = 'auto-rb' . sprintf('%04d', ++$idcounter);
2790 $output .= ' <span class="radioelement ' . $name . ' rb' . $currentradio . "\">";
2791 $output .= '<input name="' . $name . '" id="' . $htmlid . '" type="radio" value="' . $value . '"';
2792 if ($value == $checked) {
2793 $output .= ' checked="checked"';
2795 if ($onclick) {
2796 $output .= ' onclick="' . $onclick . '"';
2798 if ($label === '') {
2799 $output .= ' /> <label for="' . $htmlid . '">' . $value . '</label></span>' . "\n";
2800 } else {
2801 $output .= ' /> <label for="' . $htmlid . '">' . $label . '</label></span>' . "\n";
2803 $currentradio = ($currentradio + 1) % 2;
2807 $output .= '</span>' . "\n";
2809 if ($return) {
2810 return $output;
2811 } else {
2812 echo $output;