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