1<?php 2/** 3 * Plugin nspages : Displays nicely a list of the pages of a namespace 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Guillaume Turri <guillaume.turri@gmail.com> 7 * @author Daniel Schranz <xla@gmx.at> 8 * @author Ignacio Bergmann 9 * @author Andreas Gohr <gohr@cosmocode.de> 10 * @author Ghassem Tofighi <ghassem@gmail.com> 11 */ 12 13use dokuwiki\Utf8\PhpString; 14 15if(!defined('DOKU_INC')) die(); 16require_once 'printers/printerLineBreak.php'; 17require_once 'printers/printerOneLine.php'; 18require_once 'printers/printerSimpleList.php'; 19require_once 'printers/printerNice.php'; 20require_once 'printers/printerPictures.php'; 21require_once 'printers/printerTree.php'; 22require_once 'fileHelper/fileHelper.php'; 23require_once 'optionParser.php'; 24require_once 'namespaceFinder.php'; 25 26/** 27 * All DokuWiki plugins to extend the parser/rendering mechanism 28 * need to inherit from this class 29 */ 30class syntax_plugin_nspages extends DokuWiki_Syntax_Plugin { 31 function connectTo($aMode) { 32 $this->Lexer->addSpecialPattern('<nspages[^>]*>', $aMode, 'plugin_nspages'); 33 } 34 35 function getSort() { 36 //Execute before html mode 37 return 189; 38 } 39 40 function getType() { 41 return 'substition'; 42 } 43 44 function handle($match, $state, $pos, Doku_Handler $handler) { 45 $return = $this->_getDefaultOptions(); 46 $return['pos'] = $pos; 47 48 $match = PhpString::substr($match, 8, -1); //9 = strlen("<nspages") 49 $match .= ' '; 50 51 optionParser::checkOption($match, "subns", $return['subns'], true); 52 optionParser::checkOption($match, "nopages", $return['nopages'], true); 53 optionParser::checkOption($match, "simpleListe?", $return['simpleList'], true); 54 optionParser::checkOption($match, "tree", $return['tree'], true); 55 optionParser::checkOption($match, "numberedListe?", $return['numberedList'], true); 56 optionParser::checkOption($match, "simpleLineBreak", $return['lineBreak'], true); 57 optionParser::checkOption($match, "title", $return['title'], true); 58 optionParser::checkOption($match, "idAndTitle", $return['idAndTitle'], true); 59 optionParser::checkOption($match, "h1", $return['title'], true); 60 optionParser::checkOption($match, "simpleLine", $return['simpleLine'], true); 61 optionParser::checkOption($match, "sort(By)?Id", $return['sortid'], true); 62 optionParser::checkOption($match, "reverse", $return['reverse'], true); 63 optionParser::checkOption($match, "pagesinns", $return['pagesinns'], true); 64 optionParser::checkOption($match, "nat(ural)?Order", $return['natOrder'], true); 65 optionParser::checkOption($match, "sort(By)?Date", $return['sortDate'], true); 66 optionParser::checkOption($match, "sort(By)?CreationDate", $return['sortByCreationDate'], true); 67 optionParser::checkOption($match, "hidenopages", $return['hidenopages'], true); 68 optionParser::checkOption($match, "hidenons", $return['hidenons'], true); 69 optionParser::checkOption($match, "hidenosubns", $return['hidenosubns'], true); 70 optionParser::checkOption($match, "showhidden", $return['showhidden'], true); 71 optionParser::checkOption($match, "(use)?Pictures?", $return['usePictures'], true); 72 optionParser::checkOption($match, "(modification)?Dates?OnPictures?", $return['modificationDateOnPictures'], true); 73 optionParser::checkOption($match, "displayModificationDates?", $return["displayModificationDate"], true); 74 optionParser::checkOption($match, "includeItemsInTOC", $return["includeItemsInTOC"], true); 75 optionParser::checkOption($match, "sidebar", $return["sidebar"], true); 76 optionParser::checkRecurse($match, $return['maxDepth']); 77 optionParser::checkNbColumns($match, $return['nbCol']); 78 optionParser::checkSimpleStringArgument($match, $return['textPages'], $this, 'textPages'); 79 optionParser::checkSimpleStringArgument($match, $return['customTitle'], $this, 'customTitle'); 80 optionParser::checkSimpleStringArgument($match, $return['sortByMetadata'], $this, 'sortByMetadata'); 81 optionParser::checkSimpleStringArgument($match, $return['textNS'], $this, 'textNS'); 82 optionParser::checkDictOrder($match, $return['dictOrder'], $this); 83 optionParser::checkRegEx($match, "pregPages?On=\"([^\"]*)\"", $return['pregPagesOn']); 84 optionParser::checkRegEx($match, "pregPages?Off=\"([^\"]*)\"", $return['pregPagesOff']); 85 optionParser::checkRegEx($match, "pregPages?TitleOn=\"([^\"]*)\"", $return['pregPagesTitleOn']); 86 optionParser::checkRegEx($match, "pregPages?TitleOff=\"([^\"]*)\"", $return['pregPagesTitleOff']); 87 optionParser::checkRegEx($match, "pregNSOn=\"([^\"]*)\"", $return['pregNSOn']); 88 optionParser::checkRegEx($match, "pregNSOff=\"([^\"]*)\"", $return['pregNSOff']); 89 optionParser::checkRegEx($match, "pregNSTitleOn=\"([^\"]*)\"", $return['pregNSTitleOn']); 90 optionParser::checkRegEx($match, "pregNSTitleOff=\"([^\"]*)\"", $return['pregNSTitleOff']); 91 optionParser::checkNbItemsMax($match, $return['nbItemsMax']); 92 optionParser::checkGlobalExclude($this->getConf('global_exclude'), $return['excludedPages'], $return['excludedNS']); 93 optionParser::checkExclude($match, $return['excludedPages'], $return['excludedNS'], $return['excludeSelfPage']); 94 optionParser::checkAnchorName($match, $return['anchorName']); 95 optionParser::checkActualTitle($match, $return['actualTitleLevel']); 96 optionParser::checkSimpleStringArgument($match, $return['defaultPicture'], $this, 'defaultPicture'); 97 98 //Now, only the wanted namespace remains in $match 99 $match = strtolower(trim($match)); 100 if ($return["sidebar"]) { 101 // Don't bother resolving or sanitizing now: it will be done at render-time in this mode 102 $return['wantedNS'] = $match; 103 } else { 104 $nsFinder = new namespaceFinder($match); 105 $return['wantedNS'] = $nsFinder->getWantedNs(); 106 $return['safe'] = $nsFinder->isNsSafe(); 107 $return['wantedDir'] = $nsFinder->getWantedDirectory(); 108 } 109 110 return $return; 111 } 112 113 private function _getDefaultOptions(){ 114 return array( 115 'subns' => false, 'nopages' => false, 'simpleList' => false, 'lineBreak' => false, 116 'excludedPages' => array(), 'excludedNS' => array(), 'excludeSelfPage' => false, 117 'title' => false, 'wantedNS' => '', 'wantedDir' => '', 'safe' => true, 118 'textNS' => '', 'textPages' => '', 'pregPagesOn' => array(), 119 'customTitle' => null, 120 'pregPagesOff' => array(), 'pregNSOn' => array(), 'pregNSOff' => array(), 121 'pregPagesTitleOn' => array(), 'pregPagesTitleOff' => array(), 122 'pregNSTitleOn' => array(), 'pregNSTitleOff' => array(), 123 'maxDepth' => (int) 1, 'nbCol' => 3, 'simpleLine' => false, 124 'sortid' => false, 'reverse' => false, 125 'pagesinns' => false, 'anchorName' => null, 'actualTitleLevel' => false, 126 'idAndTitle' => false, 'nbItemsMax' => 0, 'numberedList' => false, 127 'natOrder' => false, 'sortDate' => false, 128 'hidenopages' => false, 'hidenons' => false, 'hidenosubns' => false, 'usePictures' => false, 129 'showhidden' => false, 'dictOrder' => false, 130 'modificationDateOnPictures' => false, 131 'displayModificationDate' => false, 132 'sortByCreationDate' => false, 'defaultPicture' => null, 'tree' => false, 133 'includeItemsInTOC' => false, 'sidebar' => false, 134 ); 135 } 136 137 function render($mode, Doku_Renderer $renderer, $data) { 138 $this->_deactivateTheCacheIfNeeded($renderer); 139 140 if ($data['modificationDateOnPictures']){ 141 action_plugin_nspages::logUseLegacySyntax(); 142 } 143 144 //Load lang now rather than at handle-time, otherwise it doesn't 145 //behave well with the translation plugin (it seems like we cache strings 146 //even if the lang doesn't match) 147 $this->_denullifyLangOptions($data); 148 $this->_denullifyPictureOptions($data); 149 $printer = $this->_selectPrinter($mode, $renderer, $data); 150 151 if ($data['sidebar']) { 152 if ($data['wantedNS'] !== '') { 153 $printer->printErrorSidebarDoestAcceptNamespace($data['wantedNS']); 154 return TRUE; 155 } 156 if ($mode === "metadata") { 157 // In this case $INFO is null so there is not much we can do, 158 // but anyway in "sidebar" mode we're not really going to generate metadata of the current page 159 // so it rather makes sense to exiting without printing anything. 160 return TRUE; 161 } 162 global $INFO; 163 $data['wantedNS'] = $INFO['namespace']; 164 $data['safe'] = true; 165 $data['wantedDir'] = namespaceFinder::namespaceToDirectory($data['wantedNS']); 166 } 167 168 169 if( ! $this->_isNamespaceUsable($data)) 170 { 171 if( ! $data['hidenons']) { 172 $printer->printUnusableNamespace($data['wantedNS']); 173 } 174 return TRUE; 175 } 176 177 $fileHelper = new fileHelper($data, $this->getConf('custom_title_allow_list_metadata')); 178 $pages = $fileHelper->getPages(); 179 $subnamespaces = $fileHelper->getSubnamespaces(); 180 if ( $this->_shouldPrintPagesAmongNamespaces($data) ){ 181 $subnamespaces = array_merge($subnamespaces, $pages); 182 } 183 184 $printer->printBeginning(); 185 $this->_print($printer, $data, $subnamespaces, $pages); 186 $printer->printEnd(); 187 return TRUE; 188 } 189 190 function _denullifyLangOptions(&$data){ 191 if ( is_null($data['textNS']) ){ 192 $data['textNS'] = $this->getLang('subcats'); 193 } 194 195 if ( is_null($data['textPages']) ){ 196 $data['textPages'] = $this->getLang('pagesinthiscat'); 197 } 198 } 199 200 function _denullifyPictureOptions(&$data){ 201 if ( is_null($data['defaultPicture']) ){ 202 $data['defaultPicture'] = $this->getConf('default_picture'); 203 } 204 } 205 206 private function _shouldPrintPagesAmongNamespaces($data){ 207 return $data['pagesinns']; 208 } 209 210 private function _print($printer, $data, $subnamespaces, $pages){ 211 if($data['subns']) { 212 $printer->printTOC($subnamespaces, 'subns', $data['textNS'], $data['hidenosubns']); 213 } 214 215 if(!$this->_shouldPrintPagesAmongNamespaces($data)) { 216 217 if ( $this->_shouldPrintTransition($data) ){ 218 $printer->printTransition(); 219 } 220 221 if(!$data['nopages']) { 222 $printer->printTOC($pages, 'page', $data['textPages'], $data['hidenopages']); 223 } 224 } 225 } 226 227 private function _shouldPrintTransition($data){ 228 return $data['textPages'] === '' && !$data['nopages'] && $data['subns']; 229 } 230 231 private function _isNamespaceUsable($data){ 232 global $conf; 233 return @opendir($conf['datadir'] . '/' . $data['wantedDir']) !== false && $data['safe']; 234 } 235 236 private function _selectPrinter($mode, &$renderer, $data){ 237 if($data['simpleList']) { 238 return new nspages_printerSimpleList($this, $mode, $renderer, $data); 239 } else if($data['numberedList']){ 240 return new nspages_printerSimpleList($this, $mode, $renderer, $data, true); 241 } else if($data['simpleLine']) { 242 return new nspages_printerOneLine($this, $mode, $renderer, $data); 243 } else if ($data['lineBreak']){ 244 return new nspages_printerLineBreak($this, $mode, $renderer, $data); 245 } else if ($data['usePictures'] && $mode == 'xhtml') { //This printer doesn't support non html mode yet 246 return new nspages_printerPictures($this, $mode, $renderer, $data); 247 } else if ($data['tree']) { 248 return new nspages_printerTree($this, $mode, $renderer, $data); 249 } else if($mode == 'xhtml') { 250 return new nspages_printerNice($this, $mode, $renderer, $data['nbCol'], $data['anchorName'], $data); 251 } 252 return new nspages_printerSimpleList($this, $mode, $renderer, $data); 253 } 254 255 private function _deactivateTheCacheIfNeeded(&$renderer) { 256 if ($this->getConf('cache') == 1){ 257 $renderer->nocache(); //disable cache 258 } 259 } 260} 261