1<?php 2 3// must be run within Dokuwiki 4if (!defined('DOKU_INC')) die(); 5 6/** 7 * Add-New-Page Plugin: a simple form for adding new pages. 8 * 9 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 10 * @author iDO <ido@idotech.info> 11 * @author Sam Wilson <sam@samwilson.id.au> 12 */ 13class syntax_plugin_addnewpage extends DokuWiki_Syntax_Plugin { 14 15 /** 16 * Syntax Type 17 */ 18 function getType() { return 'substition'; } 19 20 /** 21 * Paragraph Type 22 */ 23 function getPType() { return 'block'; } 24 25 /** 26 * @return int 27 */ 28 function getSort() { return 199; } 29 30 /** 31 * @param string $mode 32 */ 33 function connectTo($mode) { 34 $this->Lexer->addSpecialPattern('\{\{NEWPAGE[^\}]*\}\}', $mode, 'plugin_addnewpage'); 35 } 36 37 /** 38 * Handler to prepare matched data for the rendering process 39 * 40 * @param string $match The text matched by the patterns 41 * @param int $state The lexer state for the match 42 * @param int $pos The character position of the matched text 43 * @param Doku_Handler $handler The Doku_Handler object 44 * @return array Return an array with all data you want to use in render 45 */ 46 function handle($match, $state, $pos, Doku_Handler $handler) { 47 $ns = substr($match, 10, -2); // strip markup 48 return array($ns); 49 } 50 51 /** 52 * Create the new-page form. 53 * 54 * @param $mode string output format being rendered 55 * @param $renderer Doku_Renderer the current renderer object 56 * @param $data array data created by handler() 57 * @return boolean rendered correctly? 58 */ 59 function render($mode, Doku_Renderer $renderer, $data) { 60 global $lang; 61 $renderer->info['cache'] = false; 62 $data = $data[0]; // get data back from the array 63 64 if ($mode == 'xhtml') { 65 $ns_select = $this->_makecombo($data); 66 if ($ns_select == $this->getLang('nooption')) { 67 $renderer->doc .= (!$this->getConf('addpage_hideACL')) ? $ns_select : ''; 68 return true; 69 } 70 71 $button_val = ((@$this->getLang('okbutton')) ? $this->getLang('okbutton') : 'ok'); 72 $form = '<div class="addnewpage">'.DOKU_LF 73 .DOKU_TAB.'<form name="addnewpage" method="get" action="'.DOKU_BASE.DOKU_SCRIPT.'" accept-charset="'.$lang['encoding'].'">'.DOKU_LF 74 .DOKU_TAB.DOKU_TAB.$ns_select.DOKU_LF 75 .DOKU_TAB.DOKU_TAB.'<input class="edit" type="text" name="title" size="20" maxlength="255" tabindex="2" />'.DOKU_LF 76 .DOKU_TAB.DOKU_TAB.'<input type="hidden" name="do" value="edit" />'.DOKU_LF 77 .DOKU_TAB.DOKU_TAB.'<input type="hidden" name="id" />'.DOKU_LF 78 .DOKU_TAB.DOKU_TAB.'<input class="button" type="submit" value="'.$button_val.'" tabindex="3" />'.DOKU_LF 79 .DOKU_TAB.'</form>'.DOKU_LF 80 .'</div>'; 81 $renderer->doc .= $form; 82 83 return true; 84 } 85 return false; 86 } 87 88 /** 89 * Parse namespace request 90 * 91 * @author Samuele Tognini <samuele@cli.di.unipi.it> 92 * @author Michael Braun <michael-dev@fami-braun.de> 93 */ 94 function _parse_ns($ns) { 95 global $ID; 96 if ($ns == "@PAGE@") return $ID; 97 if ($ns == "@NS@") return getNS($ID); 98 $ns = preg_replace("/^\.(:|$)/", dirname(str_replace(':', '/', $ID)) . "$1", $ns); 99 $ns = str_replace("/", ":", $ns); 100 $ns = cleanID($ns); 101 return $ns; 102 } 103 104 /** 105 * Create the HTML Select element for namespace selection. 106 * 107 * @global string $ID The page ID 108 * @param string|false $dest_ns The destination namespace, or false if none provided. 109 * @return string Select element with appropriate NS selected. 110 */ 111 function _makecombo($dest_ns) { 112 global $ID; 113 114 // If a NS has been provided: 115 // Whether to hide the NS selection (otherwise, show only subnamespaces). 116 $hide = $this->getConf('addpage_hide'); 117 118 // Whether the user can create pages in the provided NS (or root, if no 119 // destination NS has been set. 120 $can_create = (auth_quickaclcheck($dest_ns.":") >= AUTH_CREATE); 121 122 if (!empty($dest_ns) && $hide) { 123 if ($can_create) { 124 return '<input type="hidden" name="np_cat" id="np_cat" value="'.$this->_parse_ns($dest_ns).'"/>'; 125 } else { 126 return $this->getLang('nooption'); 127 } 128 } 129 130 $ns = explode(':', $ID); 131 array_pop($ns); 132 $ns = implode(':', $ns); 133 134 $subnamespaces = $this->_getnslist(""); 135 $ret = '<select class="edit" id="np_cat" name="np_cat" tabindex="1">'; 136 137 // Whether the NS select element has any options 138 $someopt=false; 139 140 // Show root namespace if requested and allowed 141 if ($this->getConf('addpage_showroot') && $can_create) { 142 if (empty($dest_ns)) { 143 // If no namespace has been provided, add an option for the root NS. 144 $option_text = ((@$this->getLang('namespaceRoot'))?$this->getLang('namespaceRoot'):'top'); 145 $ret.='<option '.(($ns=='')?'selected ':'').'value="">'.$option_text.'</option>'; 146 $someopt=true; 147 } else { 148 // If a namespace has been provided, add an option for it. 149 $ret.='<option '.(($ns==$dest_ns)?'selected ':'').'value="'.$dest_ns.'">'.$dest_ns.'</option>'; 150 $someopt=true; 151 } 152 } 153 154 foreach ($subnamespaces as $v) { 155 if ($dest_ns != '') { 156 if (strpos(":" . $v, ":" . $dest_ns . ":") === false) { 157 continue; 158 } 159 } 160 if (auth_quickaclcheck($v . ":") < AUTH_CREATE) continue; 161 $vv = explode(':', $v); 162 $vv = str_repeat(' ', substr_count($v, ':')) . $vv[count($vv) - 1]; 163 $ret.='<option '.(($ns == $v) ? 'selected ' : '').'value="'.$v.'">'.$vv.'</option>'; 164 $someopt = true; 165 } 166 $ret.='</select>'; 167 if (!$someopt) $ret = $this->getLang('nooption'); 168 169 return $ret; 170 } 171 172 /** 173 * Get a list of namespaces below the given namespace. 174 * Recursively fetches subnamespaces. 175 * 176 * @param string $tns The top namespace 177 * @return array Multi-dimensional array of all namespaces below $tns 178 */ 179 function _getnslist($tns = '') { 180 global $conf; 181 182 if ($tns == '') $tns = $conf['datadir']; 183 if (!is_dir($tns)) $tns = utf8_encodeFN(str_replace(':', '/', $tns)); 184 $data = array(); 185 $exclude = $this->getConf('addpage_exclude'); 186 187 if ($exclude == "") $exclude = array(); 188 else $exclude = @explode(';', strtolower($exclude)); 189 190 search($data, $tns, 'search_index', array('ns' => '')); 191 192 $data2 = array(); 193 foreach ($data as $v) { 194 if ($v['type'] == 'd') { 195 if (!in_array(strtolower($v['id']), $exclude)) { 196 array_push($data2, $v['id']); 197 $r = $this->_getnslist($tns . '/' . $v['id']); 198 foreach ($r as $vv) { 199 if (!in_array(strtolower($vv), $exclude)) { 200 array_push($data2, $v['id'] . ':' . $vv); 201 } 202 } 203 } 204 } 205 } 206 return $data2; 207 } 208 209} 210