3 // This file is part of Moodle - http://moodle.org/
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.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * This contains functions and classes that will be used by scripts in wiki module
21 * @package mod-wiki-2.0
22 * @copyrigth 2009 Marc Alier, Jordi Piguillem marc.alier@upc.edu
23 * @copyrigth 2009 Universitat Politecnica de Catalunya http://www.upc.edu
25 * @author Jordi Piguillem
27 * @author David Jimenez
29 * @author Daniel Serrano
30 * @author Kenneth Riba
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 require_once($CFG->dirroot . '/mod/wiki/lib.php');
36 require_once($CFG->dirroot . '/mod/wiki/parser/parser.php');
38 define('WIKI_REFRESH_CACHE_TIME', 30); // @TODO: To be deleted.
39 define('FORMAT_CREOLE', '37');
40 define('FORMAT_NWIKI', '38');
41 define('NO_VALID_RATE', '-999');
42 define('IMPROVEMENT', '+');
46 define('LOCK_TIMEOUT', 30);
50 * @param int $wikiid the instance id of wiki
52 function wiki_get_wiki($wikiid) {
55 return $DB->get_record('wiki', array('id' => $wikiid));
59 * Get sub wiki instances with same wiki id
62 function wiki_get_subwikis($wikiid) {
64 return $DB->get_records('wiki_subwikis', array('wikiid' => $wikiid));
68 * Get a sub wiki instance by wiki id and group id
73 function wiki_get_subwiki_by_group($wikiid, $groupid, $userid = 0) {
75 return $DB->get_record('wiki_subwikis', array('wikiid' => $wikiid, 'groupid' => $groupid, 'userid' => $userid));
79 * Get a sub wiki instace by instance id
80 * @param int $subwikiid
83 function wiki_get_subwiki($subwikiid) {
85 return $DB->get_record('wiki_subwikis', array('id' => $subwikiid));
90 * Add a new sub wiki instance
93 * @return int $insertid
95 function wiki_add_subwiki($wikiid, $groupid, $userid = 0) {
98 $record = new StdClass();
99 $record->wikiid = $wikiid;
100 $record->groupid = $groupid;
101 $record->userid = $userid;
103 $insertid = $DB->insert_record('wiki_subwikis', $record);
108 * Get a wiki instance by pageid
112 function wiki_get_wiki_from_pageid($pageid) {
116 FROM {wiki} w, {wiki_subwikis} s, {wiki_pages} p
118 p.subwikiid = s.id AND
121 return $DB->get_record_sql($sql, array($pageid));
125 * Get a wiki page by pageid
129 function wiki_get_page($pageid) {
131 return $DB->get_record('wiki_pages', array('id' => $pageid));
135 * Get latest version of wiki page
139 function wiki_get_current_version($pageid) {
142 // @TODO: Fix this query
146 ORDER BY version DESC";
147 return array_pop($DB->get_records_sql($sql, array($pageid), 0, 1));
152 * Alias of wiki_get_current_version
153 * @TODO, does the exactly same thing as wiki_get_current_version, should be removed
157 function wiki_get_last_version($pageid) {
158 return wiki_get_current_version($pageid);
164 * @param string $section
166 function wiki_get_section_page($page, $section) {
168 $version = wiki_get_current_version($page->id);
169 return wiki_parser_proxy::get_section($version->content, $version->contentformat, $section);
173 * Get a wiki page by page title
174 * @param int $swid, sub wiki id
175 * @param string $title
178 function wiki_get_page_by_title($swid, $title) {
180 return $DB->get_record('wiki_pages', array('subwikiid' => $swid, 'title' => $title));
184 * Get a version record by record id
185 * @param int $versionid, the version id
188 function wiki_get_version($versionid) {
190 return $DB->get_record('wiki_versions', array('id' => $versionid));
194 * Get first page of wiki instace
195 * @param int $subwikiid
196 * @param int $module, wiki instance object
198 function wiki_get_first_page($subwikid, $module = null) {
202 FROM {wiki} w, {wiki_subwikis} s, {wiki_pages} p
205 w.firstpagetitle = p.title AND
207 return $DB->get_record_sql($sql, array($subwikid));
210 function wiki_save_section($wikipage, $sectiontitle, $sectioncontent, $userid) {
212 $wiki = wiki_get_wiki_from_pageid($wikipage->id);
213 $cm = get_coursemodule_from_instance('wiki', $wiki->id);
214 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
216 if (has_capability('mod/wiki:editpage', $context)) {
217 $version = wiki_get_current_version($wikipage->id);
218 $content = wiki_parser_proxy::get_section($version->content, $version->contentformat, $sectiontitle, true);
220 $newcontent = $content[0] . $sectioncontent . $content[2];
222 return wiki_save_page($wikipage, $newcontent, $userid);
230 * @param object $wikipage
231 * @param string $newcontent
234 function wiki_save_page($wikipage, $newcontent, $userid) {
237 $wiki = wiki_get_wiki_from_pageid($wikipage->id);
238 $cm = get_coursemodule_from_instance('wiki', $wiki->id);
239 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
241 if (has_capability('mod/wiki:editpage', $context)) {
242 $version = wiki_get_current_version($wikipage->id);
244 $version->content = $newcontent;
245 $version->userid = $userid;
247 $version->timecreated = time();
248 $versionid = $DB->insert_record('wiki_versions', $version);
250 $wikipage->timemodified = $version->timecreated;
251 $wikipage->userid = $userid;
252 $return = wiki_refresh_cachedcontent($wikipage, $newcontent);
260 function wiki_refresh_cachedcontent($page, $newcontent = null) {
263 $version = wiki_get_current_version($page->id);
264 if (!isset($newcontent)) {
265 $newcontent = $version->content;
268 $options = array('swid' => $page->subwikiid, 'pageid' => $page->id);
269 $parseroutput = wiki_parse_content($version->contentformat, $newcontent, $options);
270 $page->cachedcontent = $parseroutput['toc'] . $parseroutput['parsed_text'];
271 $page->timerendered = time();
272 $DB->update_record('wiki_pages', $page);
274 wiki_refresh_page_links($page, $parseroutput['link_count']);
276 return array('page' => $page, 'sections' => $parseroutput['repeated_sections'], 'version' => $version->version);
281 function wiki_restore_page($wikipage, $newcontent, $userid) {
282 $return = wiki_save_page($wikipage, $newcontent, $userid);
283 return $return['page'];
286 function wiki_refresh_page_links($page, $links) {
289 $DB->delete_records('wiki_links', array('frompageid' => $page->id));
290 foreach ($links as $linkname => $linkinfo) {
292 $newlink = new stdClass();
293 $newlink->subwikiid = $page->subwikiid;
294 $newlink->frompageid = $page->id;
296 if ($linkinfo['new']) {
297 $newlink->tomissingpage = $linkname;
299 $newlink->topageid = $linkinfo['pageid'];
302 $DB->insert_record('wiki_links', $newlink);
308 * Create a new wiki page, if the page exists, return existing pageid
310 * @param string $title
311 * @param string $format
314 function wiki_create_page($swid, $title, $format, $userid) {
316 $subwiki = wiki_get_subwiki($swid);
317 $cm = get_coursemodule_from_instance('wiki', $subwiki->wikiid);
318 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
319 require_capability('mod/wiki:editpage', $context);
321 if ($page = wiki_get_page_by_title($swid, $title)) {
325 // Creating a new empty version
326 $version = new stdClass();
327 $version->content = '';
328 $version->contentformat = $format;
329 $version->version = 0;
330 $version->timecreated = time();
331 $version->userid = $userid;
334 $versionid = $DB->insert_record('wiki_versions', $version);
336 // Createing a new empty page
337 $page = new stdClass();
338 $page->subwikiid = $swid;
339 $page->title = $title;
340 $page->cachedcontent = '';
341 $page->timecreated = $version->timecreated;
342 $page->timemodified = $version->timecreated;
343 $page->timerendered = $version->timecreated;
344 $page->userid = $userid;
345 $page->pageviews = 0;
348 $pageid = $DB->insert_record('wiki_pages', $page);
350 // Setting the pageid
351 $version->id = $versionid;
352 $version->pageid = $pageid;
353 $DB->update_record('wiki_versions', $version);
355 wiki_make_cache_expire($page->title);
359 function wiki_make_cache_expire($pagename) {
362 $sql = "UPDATE {wiki_pages}
364 WHERE id IN ( SELECT l.frompageid
366 WHERE l.tomissingpage = ?
368 $DB->execute ($sql, array($pagename));
372 * Get a specific version of page
374 * @param int $version
376 function wiki_get_wiki_page_version($pageid, $version) {
378 return $DB->get_record('wiki_versions', array('pageid' => $pageid, 'version' => $version));
384 * @param int $limitfrom
385 * @param int $limitnum
387 function wiki_get_wiki_page_versions($pageid, $limitfrom, $limitnum) {
389 return $DB->get_records('wiki_versions', array('pageid' => $pageid), 'version DESC', '*', $limitfrom, $limitnum);
393 * Count the number of page version
396 function wiki_count_wiki_page_versions($pageid) {
398 return $DB->count_records('wiki_versions', array('pageid' => $pageid));
402 * Get linked from page
405 function wiki_get_linked_to_pages($pageid) {
407 return $DB->get_records('wiki_links', array('frompageid' => $pageid));
411 * Get linked from page
414 function wiki_get_linked_from_pages($pageid) {
416 return $DB->get_records('wiki_links', array('topageid' => $pageid));
420 * Get pages which user have been edited
424 function wiki_get_contributions($swid, $userid) {
428 FROM {wiki_versions} v, {wiki_pages} p
429 WHERE p.subwikiid = ? AND
433 return $DB->get_records_sql($sql, array($swid, $userid));
437 * Get missing or empty pages in wiki
438 * @param int $swid sub wiki id
440 function wiki_get_missing_or_empty_pages($swid) {
443 $sql = "SELECT DISTINCT p.title, p.id, p.subwikiid
444 FROM {wiki} w, {wiki_subwikis} s, {wiki_pages} p
445 WHERE s.wikiid = w.id and
447 w.firstpagetitle != p.title and
450 FROM {wiki_versions} v
451 WHERE v.pageid = p.id)
453 SELECT DISTINCT l.tomissingpage as title, 0 as id, l.subwikiid
455 WHERE l.subwikiid = ? and
458 return $DB->get_records_sql($sql, array($swid, $swid, $swid));
462 * Get pages list in wiki
463 * @param int $swid sub wiki id
465 function wiki_get_page_list($swid) {
467 $records = $DB->get_records('wiki_pages', array('subwikiid' => $swid), 'title ASC');
472 * Return a list of orphaned wikis for one specific subwiki
474 * @param int $swid sub wiki id
476 function wiki_get_orphaned_pages($swid) {
479 $sql = "SELECT p.id, p.title
480 FROM {wiki_pages} p, {wiki} w , {wiki_subwikis} s
481 WHERE p.subwikiid = ?
484 AND p.title != w.firstpagetitle
485 AND p.id NOT IN (SELECT topageid FROM {wiki_links} WHERE subwikiid = ?);";
487 return $DB->get_records_sql($sql, array($swid, $swid, $swid));
492 * @param int $swid sub wiki id
493 * @param string $search
495 function wiki_search_title($swid, $search) {
498 return $DB->get_records_select('wiki_pages', "subwikiid = ? AND title LIKE ?", array($swid, '%'.$search.'%'));
502 * Search wiki content
503 * @param int $swid sub wiki id
504 * @param string $search
506 function wiki_search_content($swid, $search) {
509 return $DB->get_records_select('wiki_pages', "subwikiid = ? AND cachedcontent LIKE ?", array($swid, '%'.$search.'%'));
513 * Search wiki title and content
514 * @param int $swid sub wiki id
515 * @param string $search
517 function wiki_search_all($swid, $search) {
520 return $DB->get_records_select('wiki_pages', "subwikiid = ? AND (cachedcontent LIKE ? OR title LIKE ?)", array($swid, '%'.$search.'%', '%'.$search.'%'));
526 function wiki_get_user_info($userid) {
528 return $DB->get_record('user', array('id' => $userid));
532 * Increase page view nubmer
533 * @param int $page, database record
535 function wiki_increment_pageviews($page) {
539 $DB->update_record('wiki_pages', $page);
542 //----------------------------------------------------------
543 //----------------------------------------------------------
546 * Text format supported by wiki module
548 function wiki_get_formats() {
549 return array('html', 'creole', 'nwiki');
553 * Parses a string with the wiki markup language in $markup.
555 * @return Array or false when something wrong has happened.
557 * Returned array contains the following fields:
558 * 'parsed_text' => String. Contains the parsed wiki content.
559 * 'unparsed_text' => String. Constains the original wiki content.
560 * 'link_count' => Array of array('destination' => ..., 'new' => "is new?"). Contains the internal wiki links found in the wiki content.
561 * 'deleted_sections' => the list of deleted sections.
564 * @author Josep Arús Pous
566 function wiki_parse_content($markup, $pagecontent, $options = array()) {
569 $subwiki = wiki_get_subwiki($options['swid']);
570 $cm = get_coursemodule_from_instance("wiki", $subwiki->wikiid);
571 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
573 $parser_options = array('link_callback' => '/mod/wiki/locallib.php:wiki_parser_link', 'link_callback_args' => array('swid' => $options['swid']), 'table_callback' => '/mod/wiki/locallib.php:wiki_parser_table', 'real_path_callback' => '/mod/wiki/locallib.php:wiki_parser_real_path', 'real_path_callback_args' => array('context' => $context, 'component' => 'mod_wiki', 'filearea' => 'attachments', 'pageid' => $options['pageid']), 'pageid' => $options['pageid'], 'pretty_print' => (isset($options['pretty_print']) && $options['pretty_print']), 'printable' => (isset($options['printable']) && $options['printable']));
575 return wiki_parser_proxy::parse($pagecontent, $markup, $parser_options);
579 * This function is the parser callback to parse wiki links.
581 * It returns the necesary information to print a link.
583 * NOTE: Empty pages and non-existent pages must be print in red color.
585 * @param link name of a page
590 * @TODO Doc return and options
592 function wiki_parser_link($link, $options = null) {
595 if (is_object($link)) {
596 $parsedlink = array('content' => $link->title, 'url' => $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $link->id, 'new' => false, 'link_info' => array('link' => $link->title, 'pageid' => $link->id, 'new' => false));
598 $version = wiki_get_current_version($link->id);
599 if ($version->version == 0) {
600 $parsedlink['new'] = true;
604 $swid = $options['swid'];
606 if ($page = wiki_get_page_by_title($swid, $link)) {
607 $parsedlink = array('content' => $link, 'url' => $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $page->id, 'new' => false, 'link_info' => array('link' => $link, 'pageid' => $page->id, 'new' => false));
609 $version = wiki_get_current_version($page->id);
610 if ($version->version == 0) {
611 $parsedlink['new'] = true;
617 return array('content' => $link, 'url' => $CFG->wwwroot . '/mod/wiki/create.php?swid=' . $swid . '&title=' . urlencode($link) . '&action=new', 'new' => true, 'link_info' => array('link' => $link, 'new' => true, 'pageid' => 0));
623 * Returns the table fully parsed (HTML)
625 * @return HTML for the table $table
626 * @author Josep Arús Pous
629 function wiki_parser_table($table) {
632 $htmltable = new html_table();
634 $headers = $table[0];
635 $htmltable->head = array();
636 foreach ($headers as $h) {
637 $htmltable->head[] = $h[1];
641 $htmltable->data = array();
642 foreach ($table as $row) {
644 foreach ($row as $r) {
647 $htmltable->data[] = $row_data;
650 return html_writer::table($htmltable);
654 * Returns an absolute path link, unless there is no such link.
656 * @param string url Link's URL
657 * @param stdClass context filearea params
658 * @param string filearea
659 * @param int fileareaid
661 * @return File full path
664 function wiki_parser_real_path($url, $context, $filearea, $fileareaid) {
667 if (preg_match("/^(?:http|ftp)s?\:\/\//", $url)) {
670 return "{$CFG->wwwroot}/pluginfile.php/{$context->id}/$filearea/$fileareaid/$url";
675 * Returns the token used by a wiki language to represent a given tag or "object" (bold -> **)
677 * @return A string when it has only one token at the beginning (f. ex. lists). An array composed by 2 strings when it has 2 tokens, one at the beginning and one at the end (f. ex. italics). Returns false otherwise.
678 * @author Josep Arús Pous
680 function wiki_parser_get_token($markup, $name) {
682 return wiki_parser_proxy::get_token($name, $markup);
686 * Checks if current user can view a subwiki
690 function wiki_user_can_view($subwiki) {
693 $wiki = wiki_get_wiki($subwiki->wikiid);
694 $cm = get_coursemodule_from_instance('wiki', $wiki->id);
695 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
697 // Working depending on activity groupmode
698 switch (groups_get_activity_groupmode($cm)) {
701 if ($wiki->wikimode == 'collaborative') {
702 // Collaborative Mode:
703 // There is one wiki for all the class.
705 // Only view capbility needed
706 return has_capability('mod/wiki:viewpage', $context);
707 } else if ($wiki->wikimode == 'individual') {
709 // Each person owns a wiki.
710 if ($subwiki->userid == $USER->id) {
711 // Only the owner of the wiki can view it
712 return has_capability('mod/wiki:viewpage', $context);
713 } else { // User has special capabilities
715 // mod/wiki:viewpage capability
717 // mod/wiki:managewiki capability
718 $view = has_capability('mod/wiki:viewpage', $context);
719 $manage = has_capability('mod/wiki:managewiki', $context);
721 return $view && $manage;
728 // Collaborative and Individual Mode
730 // Collaborative Mode:
731 // There is one wiki per group.
733 // Each person owns a wiki.
734 if ($wiki->wikimode == 'collaborative' || $wiki->wikimode == 'individual') {
735 // Only members of subwiki group could view that wiki
736 if ($subwiki->groupid == groups_get_activity_group($cm)) {
737 // Only view capability needed
738 return has_capability('mod/wiki:viewpage', $context);
740 } else { // User is not part of that group
742 // mod/wiki:managewiki capability
744 // moodle/site:accessallgroups capability
746 // mod/wiki:viewpage capability
747 $view = has_capability('mod/wiki:viewpage', $context);
748 $manage = has_capability('mod/wiki:managewiki', $context);
749 $access = has_capability('moodle/site:accessallgroups', $context);
750 return ($manage || $access) && $view;
757 // Collaborative and Individual Mode
759 // Collaborative Mode:
760 // There is one wiki per group.
762 // Each person owns a wiki.
763 if ($wiki->wikimode == 'collaborative' || $wiki->wikimode == 'individual') {
764 // Everybody can read all wikis
766 // Only view capability needed
767 return has_capability('mod/wiki:viewpage', $context);
778 * Checks if current user can edit a subwiki
782 function wiki_user_can_edit($subwiki) {
785 $wiki = wiki_get_wiki($subwiki->wikiid);
786 $cm = get_coursemodule_from_instance('wiki', $wiki->id);
787 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
789 // Working depending on activity groupmode
790 switch (groups_get_activity_groupmode($cm)) {
793 if ($wiki->wikimode == 'collaborative') {
794 // Collaborative Mode:
795 // There is a wiki for all the class.
797 // Only edit capbility needed
798 return has_capability('mod/wiki:editpage', $context);
799 } else if ($wiki->wikimode == 'individual') {
801 // There is a wiki per user
803 // Only the owner of that wiki can edit it
804 if ($subwiki->userid == $USER->id) {
805 return has_capability('mod/wiki:editpage', $context);
806 } else { // Current user is not the owner of that wiki.
809 // mod/wiki:editpage capability
811 // mod/wiki:managewiki capability
812 $edit = has_capability('mod/wiki:editpage', $context);
813 $manage = has_capability('mod/wiki:managewiki', $context);
815 return $edit && $manage;
822 if ($wiki->wikimode == 'collaborative') {
823 // Collaborative Mode:
824 // There is one wiki per group.
826 // Only members of subwiki group could edit that wiki
827 if ($subwiki->groupid == groups_get_activity_group($cm)) {
828 // Only edit capability needed
829 return has_capability('mod/wiki:editpage', $context);
830 } else { // User is not part of that group
832 // mod/wiki:managewiki capability
834 // moodle/site:accessallgroups capability
836 // mod/wiki:editpage capability
837 $manage = has_capability('mod/wiki:managewiki', $context);
838 $access = has_capability('moodle/site:accessallgroups', $context);
839 $edit = has_capability('mod/wiki:editpage', $context);
840 return $manage && $access && $edit;
842 } else if ($wiki->wikimode == 'individual') {
844 // Each person owns a wiki.
846 // Only the owner of that wiki can edit it
847 if ($subwiki->userid == $USER->id) {
848 return has_capability('mod/wiki:editpage', $context);
849 } else { // Current user is not the owner of that wiki.
851 // mod/wiki:managewiki capability
853 // moodle/site:accessallgroups capability
855 // mod/wiki:editpage capability
856 $manage = has_capability('mod/wiki:managewiki', $context);
857 $access = has_capability('moodle/site:accessallgroups', $context);
858 $edit = has_capability('mod/wiki:editpage', $context);
859 return $manage && $access && $edit;
866 if ($wiki->wikimode == 'collaborative') {
867 // Collaborative Mode:
868 // There is one wiki per group.
870 // Only members of subwiki group could edit that wiki
871 if ($subwiki->groupid == groups_get_activity_group($cm)) {
872 // Only edit capability needed
873 return has_capability('mod/wiki:editpage', $context);
874 } else { // User is not part of that group
876 // mod/wiki:managewiki capability
878 // mod/wiki:editpage capability
879 $manage = has_capability('mod/wiki:managewiki', $context);
880 $edit = has_capability('mod/wiki:editpage', $context);
881 return $manage && $edit;
883 } else if ($wiki->wikimode == 'individual') {
885 // Each person owns a wiki.
887 // Only the owner of that wiki can edit it
888 if ($subwiki->userid == $USER->id) {
889 return has_capability('mod/wiki:editpage', $context);
890 } else { // Current user is not the owner of that wiki.
892 // mod/wiki:managewiki capability
894 // mod/wiki:editpage capability
895 $manage = has_capability('mod/wiki:managewiki', $context);
896 $edit = has_capability('mod/wiki:editpage', $context);
897 return $manage && $edit;
913 * Checks if a page-section is locked.
915 * @return true if the combination of section and page is locked, FALSE otherwise.
917 function wiki_is_page_section_locked($pageid, $userid, $section = null) {
920 $sql = "pageid = ? AND lockedat > ? AND userid != ?";
921 $params = array($pageid, time(), $userid);
923 if (!empty($section)) {
924 $sql .= " AND (sectionname = ? OR sectionname IS null)";
925 $params[] = $section;
928 return $DB->record_exists_select('wiki_locks', $sql, $params);
932 * Inserts or updates a wiki_locks record.
934 function wiki_set_lock($pageid, $userid, $section = null, $insert = false) {
937 if (wiki_is_page_section_locked($pageid, $userid, $section)) {
941 $params = array('pageid' => $pageid, 'userid' => $userid, 'sectionname' => $section);
943 $lock = $DB->get_record('wiki_locks', $params);
946 $DB->update_record('wiki_locks', array('id' => $lock->id, 'lockedat' => time() + LOCK_TIMEOUT));
947 } else if ($insert) {
948 $DB->insert_record('wiki_locks', array('pageid' => $pageid, 'sectionname' => $section, 'userid' => $userid, 'lockedat' => time() + 30));
955 * Deletes wiki_locks that are not in use. (F.Ex. after submitting the changes). If no userid is present, it deletes ALL the wiki_locks of a specific page.
957 function wiki_delete_locks($pageid, $userid = null, $section = null, $delete_from_db = true, $delete_section_and_page = false) {
960 $params = array('pageid' => $pageid);
962 if (!empty($userid)) {
963 $params['userid'] = $userid;
966 if (!empty($section)) {
967 $params['sectionname'] = $section;
970 if ($delete_from_db) {
971 $DB->delete_records('wiki_locks', $params);
972 if ($delete_section_and_page && !empty($section)) {
973 $params['sectionname'] = null;
974 $DB->delete_records('wiki_locks', $params);
977 $DB->set_field('wiki_locks', 'lockedat', time(), $params);
982 * Deletes wiki_locks that expired 1 hour ago.
984 function wiki_delete_old_locks() {
987 $DB->delete_records_select('wiki_locks', "lockedat < ?", array(time() - 3600));
995 * Uploads files to permanent disk space.
997 * @param int draftitemid Draft space ID
998 * @param int contextid
1000 * @return array of files that have not been inserted.
1003 function wiki_process_attachments($draftitemid, $deleteuploads, $contextid, $filearea, $itemid, $options = null) {
1006 if (empty($options)) {
1007 $options = page_wiki_edit::$attachmentoptions;
1012 $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
1013 $fs = get_file_storage();
1015 $oldfiles = $fs->get_area_files($contextid, 'mod_wiki', 'attachments', $itemid, 'id');
1017 foreach ($oldfiles as $file) {
1018 if (in_array($file->get_pathnamehash(), $deleteuploads)) {
1023 $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id');
1024 $oldfiles = $fs->get_area_files($contextid, 'mod_wiki', 'attachments', $itemid, 'id');
1026 $file_record = array('contextid' => $contextid, 'component' => 'mod_wiki', 'filearea' => 'attachments', 'itemid' => $itemid);
1027 //more or less a merge...
1028 $newhashes = array();
1029 foreach ($draftfiles as $file) {
1030 $newhash = sha1("/$contextid/mod_wiki/attachments/$itemid" . $file->get_filepath() . $file->get_filename());
1031 $newhashes[$newhash] = $file;
1035 foreach ($oldfiles as $file) {
1036 $oldhash = $file->get_pathnamehash();
1037 if (!$file->is_directory() && isset($newhashes[$oldhash])) {
1038 //repeated file: ERROR!!!
1039 unset($newhashes[$oldhash]);
1043 if (!$file->is_directory()) {
1048 foreach ($newhashes as $file) {
1049 if ($file->get_filepath() !== '/' or $file->is_directory()) {
1053 if ($options['maxfiles'] and $options['maxfiles'] <= $filecount) {
1057 if (!$file->is_directory()) {
1059 $fs->create_file_from_storedfile($file_record, $file);
1063 //delete all draft files
1064 $fs->delete_area_files($usercontext->id, 'user', 'draft', $draftitemid);
1069 function wiki_get_comment($commentid){
1071 return $DB->get_record('comments', array('id' => $commentid));
1075 * Returns all comments by context and pageid
1077 * @param $context. Current context
1078 * @param $pageid. Current pageid
1080 function wiki_get_comments($contextid, $pageid) {
1083 return $DB->get_records('comments', array('contextid' => $contextid, 'itemid' => $pageid, 'commentarea' => 'wiki_page'));
1087 * Add comments ro database
1089 * @param object $context. Current context
1090 * @param int $pageid. Current pageid
1091 * @param string $content. Content of the comment
1092 * @param string editor. Version of editor we are using.
1094 function wiki_add_comment($context, $pageid, $content, $editor) {
1096 require_once($CFG->dirroot . '/comment/lib.php');
1098 list($context, $course, $cm) = get_context_info_array($context->id);
1099 $cmt = new stdclass();
1100 $cmt->context = $context;
1101 $cmt->itemid = $pageid;
1102 $cmt->area = 'wiki_page';
1103 $cmt->course = $course;
1104 $cmt->component = 'mod_wiki';
1106 $manager = new comment($cmt);
1108 if ($editor == 'creole') {
1109 $manager->add($content, FORMAT_CREOLE);
1110 } else if ($editor == 'html') {
1111 $manager->add($content, FORMAT_HTML);
1112 } else if ($editor == 'nwiki') {
1113 $manager->add($content, FORMAT_NWIKI);
1119 * Delete comments from database
1121 * @param $idcomment. Id of comment which will be deleted
1122 * @param $context. Current context
1123 * @param $pageid. Current pageid
1125 function wiki_delete_comment($idcomment, $context, $pageid) {
1127 require_once($CFG->dirroot . '/comment/lib.php');
1129 list($context, $course, $cm) = get_context_info_array($context->id);
1130 $cmt = new stdClass();
1131 $cmt->context = $context;
1132 $cmt->itemid = $pageid;
1133 $cmt->area = 'wiki_page';
1134 $cmt->course = $course;
1135 $cmt->component = 'mod_wiki';
1137 $manager = new comment($cmt);
1138 $manager->delete($idcomment);
1143 * Delete al comments from wiki
1146 function wiki_delete_comments_wiki() {
1150 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1152 $table = 'comments';
1153 $select = 'contextid = ?';
1155 $DB->delete_records_select($table, $select, array($context->id));
1159 function wiki_add_progress($pageid, $oldversionid, $versionid, $progress) {
1161 for ($v = $oldversionid + 1; $v <= $versionid; $v++) {
1162 $user = wiki_get_wiki_page_id($pageid, $v);
1164 $DB->insert_record('wiki_progress', array('userid' => $user->userid, 'pageid' => $pageid, 'versionid' => $v, 'progress' => $progress));
1168 function wiki_get_wiki_page_id($pageid, $id) {
1170 return $DB->get_record('wiki_versions', array('pageid' => $pageid, 'id' => $id));
1173 function wiki_print_page_content($page, $context, $subwikiid) {
1174 global $OUTPUT, $CFG;
1176 if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) {
1177 $content = wiki_refresh_cachedcontent($page);
1178 $page = $content['page'];
1181 if (isset($content)) {
1183 foreach ($content['sections'] as $s) {
1184 $box .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>';
1188 echo $OUTPUT->box($box);
1191 $html = file_rewrite_pluginfile_urls($page->cachedcontent, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $subwikiid);
1192 $html = format_text($html, FORMAT_MOODLE, array('overflowdiv'=>true));
1193 echo $OUTPUT->box($html);
1195 if (!empty($CFG->usetags)) {
1196 $tags = tag_get_tags_array('wiki_pages', $page->id);
1197 echo $OUTPUT->container_start('wiki-tags');
1198 echo '<span class="wiki-tags-title">'.get_string('tags').': </span>';
1200 foreach ($tags as $tagid=>$tag) {
1201 $url = new moodle_url('/tag/index.php', array('tag'=>$tag));
1202 $links[] = html_writer::link($url, $tag, array('title'=>get_string('tagtitle', 'wiki', $tag)));
1204 echo join($links, ", ");
1205 echo $OUTPUT->container_end();
1208 wiki_increment_pageviews($page);
1212 * This function trims any given text and returns it with some dots at the end
1214 * @param string $text
1215 * @param string $limit
1219 function wiki_trim_string($text, $limit = 25) {
1221 if (strlen($text) > $limit) {
1222 $text = substr($text, 0, $limit) . '...';
1229 * Prints default edit form fields and buttons
1231 * @param string $format Edit form format (html, creole...)
1232 * @param integer $version Version number. A negative number means no versioning.
1235 function wiki_print_edit_form_default_fields($format, $pageid, $version = -1, $upload = false, $deleteuploads = array()) {
1236 global $CFG, $PAGE, $OUTPUT;
1238 echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
1240 if ($version >= 0) {
1241 echo '<input type="hidden" name="version" value="' . $version . '" />';
1244 echo '<input type="hidden" name="format" value="' . $format . '"/>';
1247 require_once($CFG->dirroot . '/lib/form/filemanager.php');
1249 $filemanager = new MoodleQuickForm_filemanager('attachments', get_string('wikiattachments', 'wiki'), array('id' => 'attachments'), array('subdirs' => false, 'maxfiles' => 99, 'maxbytes' => $CFG->maxbytes));
1251 $value = file_get_submitted_draft_itemid('attachments');
1252 if (!empty($value) && !$upload) {
1253 $filemanager->setValue($value);
1256 echo "<fieldset class=\"wiki-upload-section clearfix\"><legend class=\"ftoggler\">" . get_string("uploadtitle", 'wiki') . "</legend>";
1258 echo $OUTPUT->container_start('mdl-align wiki-form-center aaaaa');
1259 print $filemanager->toHtml();
1260 echo $OUTPUT->container_end();
1263 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1265 echo $OUTPUT->container_start('mdl-align wiki-form-center wiki-upload-table');
1266 wiki_print_upload_table($context, 'wiki_upload', $pageid, $deleteuploads);
1267 echo $OUTPUT->container_end();
1271 echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('save', 'wiki') . '"/>';
1272 echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('upload', 'wiki') . '"/>';
1273 echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('preview') . '"/>';
1274 echo '<input class="wiki_button" type="submit" name="editoption" value="' . get_string('cancel') . '" />';
1278 * Prints a table with the files attached to a wiki page
1279 * @param object $context
1280 * @param string $filearea
1281 * @param int $fileitemid
1282 * @param array deleteuploads
1284 function wiki_print_upload_table($context, $filearea, $fileitemid, $deleteuploads = array()) {
1285 global $CFG, $OUTPUT;
1287 $htmltable = new html_table();
1289 $htmltable->head = array(get_string('deleteupload', 'wiki'), get_string('uploadname', 'wiki'), get_string('uploadactions', 'wiki'));
1291 $fs = get_file_storage();
1292 $files = $fs->get_area_files($context->id, 'mod_wiki', $filearea, $fileitemid); //TODO: this is weird (skodak)
1294 foreach ($files as $file) {
1295 if (!$file->is_directory()) {
1296 $checkbox = '<input type="checkbox" name="deleteupload[]", value="' . $file->get_pathnamehash() . '"';
1298 if (in_array($file->get_pathnamehash(), $deleteuploads)) {
1299 $checkbox .= ' checked="checked"';
1304 $htmltable->data[] = array($checkbox, '<a href="' . file_encode_url($CFG->wwwroot . '/pluginfile.php', '/' . $context->id . '/wiki_upload/' . $fileitemid . '/' . $file->get_filename()) . '">' . $file->get_filename() . '</a>', "");
1308 print '<h3 class="upload-table-title">' . get_string('uploadfiletitle', 'wiki') . "</h3>";
1309 print html_writer::table($htmltable);
1313 * Generate wiki's page tree
1315 * @param $page. A wiki page object
1316 * @param $node. Starting navigation_node
1317 * @param $keys. An array to store keys
1318 * @return an array with all tree nodes
1320 function wiki_build_tree($page, $node, &$keys) {
1323 $icon = new pix_icon('f/odt', '');
1324 $pages = wiki_get_linked_pages($page->id);
1325 foreach ($pages as $p) {
1326 $key = $page->id . ':' . $p->id;
1327 if (in_array($key, $keys)) {
1330 array_push($keys, $key);
1331 $l = wiki_parser_link($p);
1332 $link = new moodle_url('/mod/wiki/view.php', array('pageid' => $p->id));
1333 $nodeaux = $node->add($p->title, $link, null, null, null, $icon);
1335 $nodeaux->add_class('wiki_newentry');
1337 wiki_build_tree($p, $nodeaux, $keys);
1344 * Get linked pages from page
1345 * @param int $pageid
1347 function wiki_get_linked_pages($pageid) {
1350 $sql = "SELECT p.id, p.title
1352 JOIN {wiki_links} l ON l.topageid = p.id
1353 WHERE l.frompageid = ?
1354 ORDER BY p.title ASC";
1355 return $DB->get_records_sql($sql, array($pageid));
1359 * Get updated pages from wiki
1360 * @param int $pageid
1362 function wiki_get_updated_pages_by_subwiki($swid) {
1367 WHERE subwikiid = ? AND timemodified > ?
1368 ORDER BY timemodified DESC";
1369 return $DB->get_records_sql($sql, array($swid, $USER->lastlogin));