getOne($query, [$page, $version]); } $contributionlib->remove_history($historyId); } $query = "delete from `tiki_history` where `pageName`=? and `version`=?"; $result = $this->query($query, [$page,$version]); $res = $this->version_exists($page, $version); if (! $res) { $logslib = TikiLib::lib('logs'); $logslib->add_action("Removed version", $page, 'wiki page', "version=$version"); //get_strings tra("Removed version $version") return true; } else { return false; } } public function use_version($page, $version, $comment = '') { $this->invalidate_cache($page); $query = "select * from `tiki_history` where `pageName`=? and `version`=?"; $result = $this->query($query, [$page,$version]); if (! $result->numRows()) { return false; } $res = $result->fetchRow(); global $prefs; // add both an optional, manual comment, and an automatic comment to existing one (after truncating if needed) if (trim($comment) <> '') { $comment = ". " . trim($comment); } $ver_comment = " [" . tr('Rollback by %0 to version %1', $GLOBALS['user'], $version) . $comment . "]"; $too_long = 200 - strlen($res["comment"] . $ver_comment); if ($too_long < 0) { $too_long -= 4; $res["comment"] = substr($res["comment"], 0, $too_long) . '...'; } $res["comment"] = $res["comment"] . $ver_comment; $query = "update `tiki_pages` set `data`=?,`lastModif`=?,`user`=?,`comment`=?,`version`=`version`+1,`ip`=?, `description`=?, `is_html`=?"; $bindvars = [$res['data'], $res['lastModif'], $res['user'], $res['comment'], $res['ip'], $res['description'], $res['is_html']]; // handle rolling back once page has been edited in a different editor (wiki or wysiwyg) based on is_html in history if ($prefs['feature_wysiwyg'] == 'y' && $prefs['wysiwyg_optional'] == 'y' && $prefs['wysiwyg_memo'] == 'y') { if ($res['is_html'] == 1) { // big hack: when you move to wysiwyg you do not come back usually -> wysiwyg should be a column in tiki_history $info = $this->get_hist_page_info($page); $bindvars[] = $info['wysiwyg']; } else { $bindvars[] = 'n'; } $query .= ', `wysiwyg`=?'; } $query .= ' where `pageName`=?'; $bindvars[] = $page; $result = $this->query($query, $bindvars); $query = "delete from `tiki_links` where `fromPage` = ?"; $result = $this->query($query, [$page]); $this->clear_links($page); $pages = TikiLib::lib('parser')->get_pages($res["data"], true); foreach ($pages as $a_page => $types) { $this->replace_link($page, $a_page, $types); } $this->replicate_page_to_history($page); global $prefs; if ($prefs['feature_actionlog'] == 'y') { $logslib = TikiLib::lib('logs'); $logslib->add_action("Rollback", $page, 'wiki page', "version=$version"); } //get_strings tra("Changed actual version to $version"); return true; } // Used to see a specific version of the page public function get_view_date($date_str) { global $tikilib; if (! $date_str) { // Date is undefined throw new Exception(); } $view_date = $date_str; $tsp = explode('-', $date_str); if (count($tsp) == 3) { // Date in YYYY-MM-DD format $view_date = $tikilib->make_time(23, 59, 59, $tsp[1] + 1, $tsp[2], $tsp[0] + 1900); } return $view_date; } public function get_user_versions($user) { $query = "select `pageName`,`version`, `lastModif`, `user`, `ip`, `comment` from `tiki_history` where `user`=? order by `lastModif` desc"; $result = $this->query($query, [$user]); $ret = []; while ($res = $result->fetchRow()) { $aux = []; $aux["pageName"] = $res["pageName"]; $aux["version"] = $res["version"]; $aux["lastModif"] = $res["lastModif"]; $aux["ip"] = $res["ip"]; $aux["comment"] = $res["comment"]; $ret[] = $aux; } return $ret; } // Returns information about a specific version of a page public function get_version($page, $version) { //fix for encoded slowly without doing it all at once in the installer upgrade script $wikilib = TikiLib::lib('wiki'); $converter = new convertToTiki9(); $converter->convertPageHistoryFromPageAndVersion($page, $version); $query = "select * from `tiki_history` where `pageName`=? and `version`=?"; $result = $this->query($query, [$page,$version]); $res = $result->fetchRow(); return $res; } // Get page info for a specified version public function get_hist_page_info($pageName, $version = null) { $info = parent::get_page_info($pageName); if (empty($version)) { // No version = last version return $info; } if (! $info) { // Page does not exist return false; } $old_info = $this->get_version($pageName, $version); if ($old_info == null) { // History does not exist if ($version == $this->get_page_latest_version($pageName) + 1) { // Last version return $info; } throw new Exception(); } // Override parameters with versioned data $info['data'] = $old_info['data']; $info['version'] = $old_info['version']; $info['last_version'] = $info['version']; $info["user"] = $old_info["user"]; $info["ip"] = $old_info["ip"]; $info["description"] = $old_info["description"]; $info["comment"] = $old_info["comment"]; $info["is_html"] = $old_info["is_html"]; $info['lastModif'] = $old_info["lastModif"]; $info['page_size'] = strlen($old_info['data']); return $info; } // Returns all the versions for this page // without the data itself public function get_page_history($page, $fetchdata = true, $offset = 0, $limit = -1) { global $prefs; $query = "select * from `tiki_history` where `pageName`=? order by `version` desc"; $result = $this->query($query, [$page], $limit, $offset); $ret = []; while ($res = $result->fetchRow()) { $aux = []; $aux["version"] = $res["version"]; $aux["lastModif"] = $res["lastModif"]; $aux["user"] = $res["user"]; $aux["ip"] = $res["ip"]; if ($fetchdata == true) { $aux["data"] = $res["data"]; } $aux["pageName"] = $res["pageName"]; $aux["description"] = $res["description"]; $aux["comment"] = $res["comment"]; $aux["is_html"] = $res["is_html"]; //$aux["percent"] = levenshtein($res["data"],$actual); if ($prefs['feature_contribution'] == 'y') { $contributionlib = TikiLib::lib('contribution'); $aux['contributions'] = $contributionlib->get_assigned_contributions($res['historyId'], 'history'); $logslib = TikiLib::lib('logs'); $aux['contributors'] = $logslib->get_wiki_contributors($aux); } $ret[] = $aux; } return $ret; } // Returns one version of the page from the history // without the data itself (version = 0 now returns data from current version) public function get_page_from_history($page, $version, $fetchdata = false) { $wikilib = TikiLib::lib('wiki'); $converter = new convertToTiki9(); $converter->convertPageHistoryFromPageAndVersion($page, $version); if ($fetchdata == true) { if ($version > 0) { $query = "select `pageName`, `description`, `version`, `lastModif`, `user`, `ip`, `data`, `comment`, `is_html` from `tiki_history` where `pageName`=? and `version`=?"; } else { $query = "select `pageName`, `description`, `version`, `lastModif`, `user`, `ip`, `data`, `comment`, `is_html` from `tiki_pages` where `pageName`=?"; } } else { if ($version > 0) { $query = "select `pageName`, `description`, `version`, `lastModif`, `user`, `ip`, `comment`, `is_html` from `tiki_history` where `pageName`=? and `version`=?"; } else { $query = "select `pageName`, `description`, `version`, `lastModif`, `user`, `ip`, `comment`, `is_html` from `tiki_pages` where `pageName`=?"; } } if ($version > 0) { $result = $this->query($query, [$page,$version]); } else { $result = $this->query($query, [$page]); } $ret = []; while ($res = $result->fetchRow()) { $aux = []; $aux["version"] = $res["version"]; $aux["lastModif"] = $res["lastModif"]; $aux["user"] = $res["user"]; $aux["ip"] = $res["ip"]; if ($fetchdata == true) { $aux["data"] = $res["data"]; } $aux["pageName"] = $res["pageName"]; $aux["description"] = $res["description"]; $aux["comment"] = $res["comment"]; $aux["is_html"] = $res["is_html"]; //$aux["percent"] = levenshtein($res["data"],$actual); $ret[] = $aux; } return empty($ret) ? $ret : $ret[0]; } /** * note that this function returns the latest but one version in the * history db table, which is one less than the current version * * @param string $page page name * @param string $sort_mode default version_desc * @return bool int */ public function get_page_latest_version($page, $sort_mode = 'version_desc') { $query = "select `version` from `tiki_history` where `pageName`=? order by " . $this->convertSortMode($sort_mode); $result = $this->query($query, [$page], 2); $ret = false; if ($res = $result->fetchRow()) { if ($res = $result->fetchRow()) { $ret = $res['version']; } } return $ret; } // Use largest version +1 in history table rather than tiki_page because versions used to be bugged // tiki_history is also bugged as not all changes get stored in the history, like minor changes // and changes that do not modify the body of the page. Both numbers are wrong, but the largest of // them both is right. // Also, it's possible that latest version in history has been rejected (with Flagged Revisions), // so the current version is not the biggest number. public function get_page_next_version($page, $willDoHistory = true) { $query = "select `version` from `tiki_history` where `pageName`=? order by `version` desc"; $result = $this->query($query, [$page], 1); $version = 0; if ($res = $result->fetchRow()) { $version = $res['version']; } $query = "select `version` from `tiki_pages` where `pageName`=?"; $result = $this->query($query, [$page], 1); if ($res = $result->fetchRow()) { $version = max($res['version'], $version); } return $version + ($willDoHistory ? 1 : 0); } public function version_exists($pageName, $version) { $query = "select `pageName` from `tiki_history` where `pageName` = ? and `version`=?"; $result = $this->query($query, [$pageName,$version]); return $result->numRows(); } // This function get the last changes from pages from the last $days days // if days is 0 this gets all the registers public function get_last_changes($days, $offset = 0, $limit = -1, $sort_mode = 'lastModif_desc', $findwhat = '', $repeat = false) { global $user; $bindvars = []; $categories = $this->get_jail(); if (! isset($categjoin)) { $categjoin = ''; } if ($categories) { $categjoin .= "inner join `tiki_objects` as tob on (tob.`itemId`= ta.`object` and tob.`type`= ?) inner join `tiki_category_objects` as tc on (tc.`catObjectId`=tob.`objectId` and tc.`categId` IN(" . implode(', ', array_fill(0, count($categories), '?')) . ")) "; $bindvars = array_merge(['wiki page'], $categories); } $where = "where true "; if ($findwhat) { $findstr = '%' . $findwhat . '%'; $where .= " and ta.`object` like ? or ta.`user` like ? or ta.`comment` like ?"; $bindvars = array_merge($bindvars, [$findstr,$findstr,$findstr]); } if ($days) { $toTime = $this->make_time(23, 59, 59, $this->date_format("%m"), $this->date_format("%d"), $this->date_format("%Y")); $fromTime = $toTime - (24 * 60 * 60 * $days); $where .= " and ta.`lastModif`>=? and ta.`lastModif`<=? "; $bindvars[] = $fromTime; $bindvars[] = $toTime; } $group_by = ""; if ($repeat) { $group_by = "group by thf.`page_id`"; } // WARNING: This assumes the current version of each page will be found in tiki_history $query = "select distinct ta.`action`, ta.`lastModif`, ta.`user`, ta.`ip`, ta.`object`, thf.`comment`, thf.`version`, thf.`page_id` from `tiki_actionlog` ta inner join (select th.`version`, th.`comment`, th.`pageName`, th.`lastModif`, tp.`page_id` from `tiki_history` as th LEFT OUTER JOIN `tiki_pages` tp ON tp.`pageName` = th.`pageName` AND tp.`version` = th.`version`) as thf on ta.`object`=thf.`pageName` and ta.`lastModif`=thf.`lastModif` and ta.`objectType`='wiki page' and ta.`action` <> 'Removed version' " . $categjoin . $where . $group_by . " order by ta." . $this->convertSortMode($sort_mode); // TODO: Optimize. This fetches all records just to be able to give a count. $result = Perms::filter([ 'type' => 'wiki page' ], 'object', $this->fetchAll($query, $bindvars), [ 'object' => 'object' ], 'view'); $cant = count($result); $ret = []; if ($limit == -1) { $result = array_slice($result, $offset); } else { $result = array_slice($result, $offset, $limit); } foreach ($result as $res) { $res['current'] = isset($res['page_id']); $res['pageName'] = $res['object']; $ret[] = $res; } return ['data' => $ret, 'cant' => $cant]; } public function get_nb_history($page) { $query_cant = "select count(*) from `tiki_history` where `pageName` = ?"; $cant = $this->getOne($query_cant, [$page]); return $cant; } // This function gets the version number of the version before or after the time specified // (note that current version is not included in search) public function get_version_by_time($page, $unixtimestamp, $before_or_after = 'before', $include_minor = true) { $query = "select `version`, `version_minor`, `lastModif` from `tiki_history` where `pageName`=? order by `version` desc"; $result = $this->query($query, [$page]); $ret = []; $version = 0; while ($res = $result->fetchRow()) { $aux = []; $aux["version"] = $res["version"]; $aux["version_minor"] = $res["version_minor"]; $aux["lastModif"] = $res["lastModif"]; $ret[] = $aux; } foreach ($ret as $ver) { if ($ver["lastModif"] <= $unixtimestamp && ($include_minor || $ver["version_minor"] == 0)) { if ($before_or_after == 'before') { $version = (int) $ver["version"]; break; } elseif ($before_or_after == 'after') { break; } } if ($before_or_after == 'after' && ($include_minor || $ver["version_minor"] == 0)) { $version = (int) $ver["version"]; } } return max(0, $version); } } /** * * This class represents a structured view (per word) on a document. Feeding it with additional references, it can be used to generate a * complete view of the document including changes made over time (like the "Track changes" in some word processing programs). A statistics * of the different authors contributions can be generated as well * * @author cdrwhite * @since 6.0 */ class Document { /** * @var array a list of words and whitespaces represented by an array(word,author,deleted,diffid,[deleted_by]) */ private $_document; /** * @var array array of statistical data grouped by author each represented by an array(words,deleted_words,whitespaces,deleted_whitespaces,characters,deleted_characters,printables,deleted_printables) * @see getStatistics */ private $_statistics; /** * @var array sum of all statistics for all authors, generated by getStatistics, retrieved by getTotal() * @see getTotal; */ private $_total; /** * @var string filter used in getStatistics to distinguish between characters and printable characters * @see getStatistics */ private $_filter; /** * @var int processing settings */ private $_process = 1; /** * @var bool should the page contents be parsed (HTML instead of WIKI text) */ private $_parsed; /** * @var bool should the html tags be stripped from the parsed contents */ private $_nohtml; /** * @var string start marker. If set, text before this marker (including the marker itself) will be removed */ public $startmarker = ''; /** * @var string end marker. If set, text after this marker (including the marker itself) will be removed */ public $endmarker = ''; /** * @var string regex for splitting page text into an array of words; */ private $_search = "#(\[[^\[].*?\]|\(\(.*?\)\)|(~np~\{.*?\}~/np~)|<[^>]+>|[,\"':\s]+|[^\s,\"':<]+|[^>]+>)#"; /** * @var array Page info */ private $_info; /** * @var array complete page history */ private $_data; /** * * Initializing Internal variables for getStatistics and getTotals and adding the first page to the document * @param string $page Name of the page to include * @param int $lastversion >0 uses the version specified (or last page, if this is greater than the version of the last page) =0 uses the latest(current) version, <0 means a timestamp (lastModif has to be before that) * @param int $process 0 = don't parse (take original wiki text and count wiki tags/plugins), 1 = parse (take html as base), 2 = parse and strip html tags * @param string $start start marker (all text will be skipped, including this marker which must be at the beginning of a line) * @param string $end end marker (all text will be skipped from this marker on, including this marker which must be at the beginning of a line) */ public function __construct($page, $lastversion = 0, $process = 1, $showpopups = true, $startmarker = '', $endmarker = '') { $histlib = TikiLib::lib('hist'); $this->_document = []; $this->_history = false; $this->_filter = '/([[:blank:]]|[[:cntrl:]]|[[:punct:]]|[[:space:]])/'; $this->_parsed = true; $this->_nohtml = false; $this->_showpopups = $showpopups; switch ($process) { case 0: $this->_parsed = false; $this->_process = 0; break; case 2: $this->_nohtml = true; $this->_process = 2; break; } $this->startmarker = $startmarker; $this->endmarker = $endmarker; $this->_info = $histlib->get_hist_page_info($page, true); if ($lastversion == 0) { $lastversion = $this->_info['version']; } $this->_data = []; $this->_data = [[ 'version' => $this->_info['version'], 'lastModif' => $this->_info['lastModif'], 'user' => $this->_info['user'], 'ip' => $this->_info['ip'], 'pageName' => $page, 'description' => $this->_info['description'], 'comment' => $this->_info['comment'], 'data' => $this->_info['data'], ]]; $this->_data = array_merge($this->_data, $histlib->get_page_history($page, true, 0, -1)); $next = count($this->_data) - 1; $author = $this->_data[$next]['user']; $next = $this->getLastAuthorText($author, $next, $lastversion); if ($next == -1) { // all pages from the same author, no need to diff $index = $this->getIndex($lastversion); } else { $index = $next; } $source = $this->removeText($this->_data[$index]['data']); $source = preg_replace(['/\{AUTHOR\(.+?\)\}/','/{AUTHOR\}/','/\{INCLUDE\(.+?\)\}\{INCLUDE\}/'], ' ~np~$0~/np~', $source); if ($this->_parsed) { $source = TikiLib::lib('parser')->parse_data($source, ['suppress_icons' => true]); } if ($this->_nohtml) { $source = strip_tags($source); } preg_match_all($this->_search, $source, $out, PREG_PATTERN_ORDER); $words = $out[0]; $this->_document = $this->addWords($this->_document, $words, $author); if ($next == -1) { return; } do { $author = $this->_data[$next - 1]['user']; $next = $this->getLastAuthorText($author, $next - 1, $lastversion); if ($next == -1) { $index = $this->getIndex($lastversion); } else { $index = $next; } $newpage = $this->removeText($this->_data[$index]['data']); $this->mergeDiff($newpage, $author); } while ($next > 0); $this->parseAuthorAndInclude(); } /** * * Removes all text before the first occurrence of start marker and after the last occurrence of the end marker * This copies the original behaviour of the wikiplugin_include even though it could be done with a regex in fewer lines * @param string $text contains the whole text * @return string returns the text inside the markers */ private function removeText($text) { $start = ($this->startmarker != ''); $stop = ($this->endmarker != ''); if ($start || $stop) { $explText = explode("\n", $text); if ($start && $stop) { $state = 0; foreach ($explText as $i => $line) { if ($state == 0) { // Searching for start marker, dropping lines until found unset($explText[$i]); // Drop the line if (0 == strcmp($this->startmarker, trim($line))) { $state = 1; // Start retaining lines and searching for stop marker } } else { // Searching for stop marker, retaining lines until found if (0 == strcmp($this->endmarker, trim($line))) { unset($explText[$i]); // Stop marker, drop the line $state = 0; // Go back to looking for start marker } } } } elseif ($start) { // Only start marker is set. Search for it, dropping all lines until it is found. foreach ($explText as $i => $line) { unset($explText[$i]); // Drop the line if (0 == strcmp($this->startmarker, trim($line))) { break; } } } else { // Only stop marker is set. Search for it, dropping all lines after it is found. $state = 1; foreach ($explText as $i => $line) { if ($state == 0) { // Dropping lines unset($explText[$i]); } else { // Searching for stop marker, retaining lines until found if (0 == strcmp($this->endmarker, trim($line))) { unset($explText[$i]); // Stop marker, drop the line $state = 0; // Start dropping lines } } } } $text = implode("\n", $explText); } return $text; } /** * * get the id of the last text of the given author * @param string $author name of the current author * @param int $start start index * @param int $lastversion last version to check, assuming all versions, if none is provided * @return int id of the first text of a different author or -1 if there is none * @see get_page_history_all */ private function getLastAuthorText($author, $start = -1, $lastversion = -1) { if ($start == -1) { return $start; } if ($start < 0) { $start = count($this->_data) - 1; } if ($lastversion == -1) { $lastversion = $this->_data[0]['version']; } $i = $start; while ($i >= 0 and $this->_data[$i]['user'] == $author and $this->_data[$i]['version'] <= $lastversion) { $i--; } $i++; if ($this->_data[$i]['version'] >= $lastversion) { $i = -1; } return $i; } /** * * gets the index position of the requested version in the data array * @param int $version */ private function getIndex($version) { for ($i = count($this->_data) - 1; $i >= 0; $i--) { if ($this->_data[$i]['version'] == $version) { return $i; } } return -1; } /** * * returns the history (identical to $histlib->get_page_history, but saves another fetch from database as we already have the info */ public function getHistory() { return array_slice($this->_data, 1); } /** * * returns the page info history (identical to $tikilib->get_page_info, but saves another fetch from database as we already have the info */ public function getInfo() { return $this->_info; } /** * * Generates an array of words from the internal document structure, which can be used by the diff class. * The internal document structure will be modified to allow mergeDiff to integrate a new page with the current page without losing any information * @see mergeDiff * @return array list of words in the document (no author etc.) */ public function getDiffArray() { $diffarray = []; foreach ($this->_document as &$word) { if (! $word['deleted']) { $word['diffid'] = count($diffarray); $diffarray[] = $word['word']; } else { $word['diffid'] = -1; } } return $diffarray; } /** * * Generates a statistics per author, the totals can be retrieved via getTotal * @see getTotal * @param string $filter regex to filter out non printable characters (difference between characters and printables) * @return array array indexed by author containing arrays with statistics (words, deleted_words, whitespaces, deleted_whitespaces, characters, deleted_characters, printables, deleted_printables) */ public function getStatistics($filter = '/([[:blank:]]|[[:cntrl:]]|[[:punct:]]|[[:space:]])/') { $style = 0; if ($this->_filter != $filter) { //a new filter invalidates the statistics $this->_statistics = false; $this->_filter = $filter; } if ($this->_statistics != false) { return $this->_statistics; //there is already a history for the current state } $this->_statistics = []; $this->_total = [ 'words' => 0, 'deleted_words' => 0, 'whitespaces' => 0, 'deleted_whitespaces' => 0, 'characters' => 0, 'deleted_characters' => 0, 'printables' => 0, 'deleted_printables' => 0, ]; foreach ($this->_document as $word) { $author = $word['author']; if (! isset($this->_statistics[$author])) { $this->_statistics[$author] = [ 'words' => 0, 'words_percent' => 0, 'deleted_words' => 0, 'deleted_words_percent' => 0, 'whitespaces' => 0, 'whitespaces_percent' => 0, 'deleted_whitespaces' => 0, 'deleted_whitespaces_percent' => 0, 'characters' => 0, 'characters_percent' => 0, 'deleted_characters' => 0, 'deleted_characters_percent' => 0, 'printables' => 0, 'printables_percent' => 0, 'deleted_printables' => 0, 'deleted_printables_percent' => 0, 'style' => "author$style", ]; $style++; if ($style > 15) { $style = 0; } } //isset author if ($word['deleted']) { $prefix = 'deleted_'; } else { $prefix = ''; } $w = $word['word']; if ($this->_nohtml) { $w = strip_tags($w); } if (trim($w) == '') { $this->_statistics[$author][$prefix . 'whitespaces']++; $this->_total[$prefix . 'whitespaces']++; } else { $this->_statistics[$author][$prefix . 'words']++; $this->_total[$prefix . 'words']++; } $l = mb_strlen($w); $this->_statistics[$author][$prefix . 'characters'] += $l; $this->_total[$prefix . 'characters'] += $l; $l = mb_strlen(preg_replace($this->_filter, '', $w)); $this->_statistics[$author][$prefix . 'printables'] += $l; $this->_total[$prefix . 'printables'] += $l; } //foreach //calculate percentages foreach ($this->_statistics as &$author) { $author['words_percent'] = $author['words'] / $this->_total['words']; $author['deleted_words_percent'] = ($this->_total['deleted_words'] != 0 ? $author['deleted_words'] / $this->_total['deleted_words'] : 0); $author['whitespaces_percent'] = $author['whitespaces'] / $this->_total['whitespaces']; $author['deleted_whitespaces_percent'] = ($this->_total['deleted_whitespaces'] != 0 ? $author['deleted_whitespaces'] / $this->_total['deleted_whitespaces'] : 0); $author['characters_percent'] = $author['characters'] / $this->_total['characters']; $author['deleted_characters_percent'] = ($this->_total['deleted_characters'] != 0 ? $author['deleted_characters'] / $this->_total['deleted_characters'] : 0); $author['printables_percent'] = $author['printables'] / $this->_total['printables']; $author['deleted_printables_percent'] = ($this->_total['deleted_printables'] != 0 ? $author['deleted_printables'] / $this->_total['deleted_printables'] : 0); } return $this->_statistics; } /** * * gets the totals from a previous getStatistics call * @see getStatistics * @return array with statistics (words, deleted_words, whitespaces, deleted_whitespaces, characters, deleted_characters, printables, deleted_printables) */ public function getTotal() { return $this->_total; } /** * * Retrieves the document data in different formats, * @param string $type can be one of 'words' (array of words/whitespaces), 'text' (unformatted string), 'wiki' (string with wikiplugin AUTHOR tags to show the authors) or the default empty string '' (returns the internal document structure) * @param array $options array containing the filter specific options: *
| Type | Name | Applicable for | Purpose |
|---|---|---|---|
| bool | showpopups | wiki | renders popups, defaults to true |
| bool | escape | text/wiki | Escapes brackets and htmlspecialchars |