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