xref: /plugin/menu/syntax.php (revision 7662d4851d2c3a43f9171d18e27d437f0027a616)
1dad308ecSroot<?php
2dad308ecSroot/**
3dad308ecSroot * Plugin: Displays a link list in a nice way
4dad308ecSroot *
5dad308ecSroot * Syntax: <menu col=2,align=center,caption="headline">
6dad308ecSroot *           <item>name|description|link|image</item>
7dad308ecSroot *         </menu>
8dad308ecSroot *
9dad308ecSroot * Options have to be separated by comma.
10dad308ecSroot * col (opt)     The number of columns of the menu. Allowed are 1-4, default is 1
11dad308ecSroot * align (opt)   Alignment of the menu. Allowed are "left", "center" or "right",
12dad308ecSroot *               default is "left"
13dad308ecSroot * caption (opt) Headline of the menu, default is none
14dad308ecSroot *
15dad308ecSroot * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
16dad308ecSroot * @author     Matthias Grimm <matthiasgrimm@users.sourceforge.net>
17dad308ecSroot * @author     Frank Schiebel <frank@linuxmuster.net>
18dad308ecSroot */
19dad308ecSroot
20dad308ecSrootif(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
21dad308ecSrootif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
22dad308ecSrootrequire_once(DOKU_PLUGIN.'syntax.php');
23dad308ecSroot
24dad308ecSroot/**
25dad308ecSroot * All DokuWiki plugins to extend the parser/rendering mechanism
26dad308ecSroot * need to inherit from this class
27dad308ecSroot */
28dad308ecSrootclass syntax_plugin_menu extends DokuWiki_Syntax_Plugin {
29dad308ecSroot
30dad308ecSroot    var $rcmd = array();  /**< Command array for the renderer */
31dad308ecSroot
32dad308ecSroot    function __construct() {
33dad308ecSroot    }
34dad308ecSroot
35dad308ecSroot
36dad308ecSroot   /**
37dad308ecSroot    * Get the type of syntax this plugin defines.
38dad308ecSroot    *
39dad308ecSroot    * The type of this plugin is "protected". It has a start and an end
40dad308ecSroot    * token and no other wiki commands shall be parsed between them.
41dad308ecSroot    *
42dad308ecSroot    * @param none
43dad308ecSroot    * @return String <tt>'protected'</tt>.
44dad308ecSroot    * @public
45dad308ecSroot    * @static
46dad308ecSroot    */
47dad308ecSroot    function getType(){
48dad308ecSroot        return 'protected';
49dad308ecSroot    }
50dad308ecSroot
51dad308ecSroot   /**
52dad308ecSroot    * Define how this plugin is handled regarding paragraphs.
53dad308ecSroot    *
54dad308ecSroot    * <p>
55dad308ecSroot    * This method is important for correct XHTML nesting. It returns
56dad308ecSroot    * one of the following values:
57dad308ecSroot    * </p>
58dad308ecSroot    * <dl>
59dad308ecSroot    * <dt>normal</dt><dd>The plugin can be used inside paragraphs.</dd>
60dad308ecSroot    * <dt>block</dt><dd>Open paragraphs need to be closed before
61dad308ecSroot    * plugin output.</dd>
62dad308ecSroot    * <dt>stack</dt><dd>Special case: Plugin wraps other paragraphs.</dd>
63dad308ecSroot    * </dl>
64dad308ecSroot    * @param none
65dad308ecSroot    * @return String <tt>'block'</tt>.
66dad308ecSroot    * @public
67dad308ecSroot    * @static
68dad308ecSroot    */
69dad308ecSroot    function getPType(){
70dad308ecSroot        return 'block';
71dad308ecSroot    }
72dad308ecSroot
73dad308ecSroot   /**
74dad308ecSroot    * Where to sort in?
75dad308ecSroot    *
76dad308ecSroot    * Sort the plugin in just behind the formating tokens
77dad308ecSroot    *
78dad308ecSroot    * @param none
79dad308ecSroot    * @return Integer <tt>135</tt>.
80dad308ecSroot    * @public
81dad308ecSroot    * @static
82dad308ecSroot    */
83dad308ecSroot    function getSort(){
84dad308ecSroot        return 135;
85dad308ecSroot    }
86dad308ecSroot
87dad308ecSroot   /**
88dad308ecSroot    * Connect lookup pattern to lexer.
89dad308ecSroot    *
90dad308ecSroot    * @param $aMode String The desired rendermode.
91dad308ecSroot    * @return none
92dad308ecSroot    * @public
93dad308ecSroot    * @see render()
94dad308ecSroot    */
95dad308ecSroot    function connectTo($mode) {
96dad308ecSroot       $this->Lexer->addEntryPattern('<menu>(?=.*?</menu.*?>)',$mode,'plugin_menu');
97dad308ecSroot       $this->Lexer->addEntryPattern('<menu\s[^\r\n\|]*?>(?=.*?</menu.*?>)',$mode,'plugin_menu');
98dad308ecSroot    }
99dad308ecSroot
100dad308ecSroot    function postConnect() {
101dad308ecSroot      $this->Lexer->addPattern('<item>.+?</item>','plugin_menu');
102dad308ecSroot      $this->Lexer->addExitPattern('</menu>','plugin_menu');
103dad308ecSroot    }
104dad308ecSroot
105dad308ecSroot   /**
106dad308ecSroot    * Handler to prepare matched data for the rendering process.
107dad308ecSroot    *
108dad308ecSroot    * <p>
109dad308ecSroot    * The <tt>$aState</tt> parameter gives the type of pattern
110dad308ecSroot    * which triggered the call to this method:
111dad308ecSroot    * </p>
112dad308ecSroot    * <dl>
113dad308ecSroot    * <dt>DOKU_LEXER_ENTER</dt>
114dad308ecSroot    * <dd>a pattern set by <tt>addEntryPattern()</tt></dd>
115dad308ecSroot    * <dt>DOKU_LEXER_MATCHED</dt>
116dad308ecSroot    * <dd>a pattern set by <tt>addPattern()</tt></dd>
117dad308ecSroot    * <dt>DOKU_LEXER_EXIT</dt>
118dad308ecSroot    * <dd> a pattern set by <tt>addExitPattern()</tt></dd>
119dad308ecSroot    * <dt>DOKU_LEXER_SPECIAL</dt>
120dad308ecSroot    * <dd>a pattern set by <tt>addSpecialPattern()</tt></dd>
121dad308ecSroot    * <dt>DOKU_LEXER_UNMATCHED</dt>
122dad308ecSroot    * <dd>ordinary text encountered within the plugin's syntax mode
123dad308ecSroot    * which doesn't match any pattern.</dd>
124dad308ecSroot    * </dl>
125dad308ecSroot    * @param $aMatch String The text matched by the patterns.
126dad308ecSroot    * @param $aState Integer The lexer state for the match.
127dad308ecSroot    * @param $aPos Integer The character position of the matched text.
128dad308ecSroot    * @param $aHandler Object Reference to the Doku_Handler object.
129dad308ecSroot    * @return Integer The current lexer state for the match.
130dad308ecSroot    * @public
131dad308ecSroot    * @see render()
132dad308ecSroot    * @static
133dad308ecSroot    */
134dad308ecSroot    function handle($match, $state, $pos, Doku_Handler $handler)
135dad308ecSroot    {
136dad308ecSroot        switch ($state) {
137dad308ecSroot            case DOKU_LEXER_ENTER:
138dad308ecSroot                $this->_reset();        // reset object;
139dad308ecSroot
140dad308ecSroot                $opts = $this->_parseOptions(trim(substr($match,5,-1)));
141dad308ecSroot                $col = $opts['col'];
142dad308ecSroot                if (!empty($col) && is_numeric($col) && $col > 0 && $col < 5)
143dad308ecSroot                        $this->rcmd['columns'] = $col;
144*cca3ead5SAnna Dabrowska
145*cca3ead5SAnna Dabrowska                if (isset($opts['align'])) {
146dad308ecSroot                    if ($opts['align'] == "left")   $this->rcmd['float'] = "left";
147dad308ecSroot                    if ($opts['align'] == "center") $this->rcmd['float'] = "center";
148dad308ecSroot                    if ($opts['align'] == "right")  $this->rcmd['float'] = "right";
149*cca3ead5SAnna Dabrowska                }
150*cca3ead5SAnna Dabrowska                if (isset($opts['valign'])) {
151ddbf0766SEli Fenton                    if ($opts['valign'] == "top")   $this->rcmd['valign'] = "vtop";
152ddbf0766SEli Fenton                    if ($opts['valign'] == "center") $this->rcmd['valign'] = "vcenter";
153ddbf0766SEli Fenton                    if ($opts['valign'] == "bottom")  $this->rcmd['valign'] = "vbottom";
154*cca3ead5SAnna Dabrowska                }
155dad308ecSroot                if (!empty($opts['caption']))
156dad308ecSroot                    $this->rcmd['caption'] = hsc($opts['caption']);
157dad308ecSroot                if (!empty($opts['type']))
158dad308ecSroot                    $this->rcmd['type'] = hsc($opts['type']);
159ff0823ddSEli Fenton                if (!empty($opts['width']))
160ff0823ddSEli Fenton                    $this->rcmd['width'] = hsc($opts['width']);
161ff0823ddSEli Fenton                $this->rcmd['wrap'] = !empty($opts['wrap']);
162dad308ecSroot            break;
163dad308ecSroot          case DOKU_LEXER_MATCHED:
164dad308ecSroot
165dad308ecSroot                $menuitem = preg_split('/\|/', trim(substr($match,6,-7)));
166dad308ecSroot
167dad308ecSroot                $title = hsc($menuitem[0]);
168dad308ecSroot                if (substr($menuitem[2],0,2) == "{{")
169dad308ecSroot                    $link = $this->_itemimage($menuitem[2], $title);
170dad308ecSroot                else
171dad308ecSroot                    $link = $this->_itemLink($menuitem[2], $title);
172dad308ecSroot                $image = $this->_itemimage($menuitem[3], $title);
173dad308ecSroot
174dad308ecSroot                $this->rcmd['items'][] = array("image" => $image,
175dad308ecSroot                                               "link"  => $link,
176dad308ecSroot                                               "descr" => hsc($menuitem[1]));
177dad308ecSroot
178ff0823ddSEli Fenton                if (!empty($opts['width'])) {
179dad308ecSroot                    // find out how much space the biggest menu item needs
180dad308ecSroot                    $titlelen = mb_strlen($menuitem[0], "UTF-8");
181dad308ecSroot                    if ($titlelen > $this->rcmd['width'])
182dad308ecSroot                        $this->rcmd['width'] = $titlelen;
183ff0823ddSEli Fenton                }
184dad308ecSroot            break;
185dad308ecSroot          case DOKU_LEXER_EXIT:
186dad308ecSroot              // give the menu a convinient width. IE6 needs more space here than Firefox
187ff0823ddSEli Fenton              if (!empty($opts['width'])) {
188dad308ecSroot                  $this->rcmd['width'] += 5;
189ff0823ddSEli Fenton              }
190dad308ecSroot              return $this->rcmd;
191dad308ecSroot          default:
192dad308ecSroot            break;
193dad308ecSroot        }
194dad308ecSroot        return array();
195dad308ecSroot    }
196dad308ecSroot
197dad308ecSroot    function _reset()
198dad308ecSroot    {
199dad308ecSroot        $this->rcmd = array();
200dad308ecSroot        $this->rcmd['columns'] = 1;
201dad308ecSroot        $this->rcmd['float']   = "left";
202ddbf0766SEli Fenton        $this->rcmd['valign']  = "vtop";
203dad308ecSroot    }
204dad308ecSroot
205dad308ecSroot    function _itemlink($match, $title) {
206dad308ecSroot        // Strip the opening and closing markup
207dad308ecSroot        $link = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match);
208dad308ecSroot
209dad308ecSroot        // Split title from URL
210dad308ecSroot        $link = explode('|',$link,2);
211dad308ecSroot        $ref  = trim($link[0]);
212dad308ecSroot
213dad308ecSroot        //decide which kind of link it is
214dad308ecSroot        if ( preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u',$ref) ) {
215dad308ecSroot            // Interwiki
216dad308ecSroot            $interwiki = explode('>',$ref,2);
217dad308ecSroot            return array('interwikilink',
218dad308ecSroot                         array($ref,$title,strtolower($interwiki[0]),$interwiki[1]));
219dad308ecSroot        } elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$ref) ) {
220dad308ecSroot            // Windows Share
221dad308ecSroot            return array('windowssharelink', array($ref,$title));
222dad308ecSroot        } elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$ref) ) {
223dad308ecSroot            // external link (accepts all protocols)
224dad308ecSroot            return array('externallink', array($ref,$title));
225dad308ecSroot        } elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$ref) ) {
226dad308ecSroot            // E-Mail (pattern above is defined in inc/mail.php)
227dad308ecSroot            return array('emaillink', array($ref,$title));
228dad308ecSroot        } elseif ( preg_match('!^#.+!',$ref) ) {
229dad308ecSroot            // local link
230dad308ecSroot            return array('locallink', array(substr($ref,1),$title));
231dad308ecSroot        } else {
232dad308ecSroot            // internal link
233dad308ecSroot            return array('internallink', array($ref,$title));
234dad308ecSroot        }
235dad308ecSroot    }
236dad308ecSroot
237dad308ecSroot    function _itemimage($match, $title) {
238dad308ecSroot        $p = Doku_Handler_Parse_Media($match);
239dad308ecSroot
240dad308ecSroot        return array($p['type'],
241dad308ecSroot                     array($p['src'], $title, $p['align'], $p['width'],
242dad308ecSroot                     $p['height'], $p['cache'], $p['linking']));
243dad308ecSroot    }
244dad308ecSroot
245dad308ecSroot   /**
246dad308ecSroot    * Handle the actual output creation.
247dad308ecSroot    *
248dad308ecSroot    * <p>
249dad308ecSroot    * The method checks for the given <tt>$aFormat</tt> and returns
250dad308ecSroot    * <tt>FALSE</tt> when a format isn't supported. <tt>$aRenderer</tt>
251dad308ecSroot    * contains a reference to the renderer object which is currently
252dad308ecSroot    * handling the rendering. The contents of <tt>$aData</tt> is the
253dad308ecSroot    * return value of the <tt>handle()</tt> method.
254dad308ecSroot    * </p>
255dad308ecSroot    * @param $aFormat String The output format to generate.
256dad308ecSroot    * @param $aRenderer Object A reference to the renderer object.
257dad308ecSroot    * @param $aData Array The data created by the <tt>handle()</tt>
258dad308ecSroot    * method.
259dad308ecSroot    * @return Boolean <tt>TRUE</tt> if rendered successfully, or
260dad308ecSroot    * <tt>FALSE</tt> otherwise.
261dad308ecSroot    * @public
262dad308ecSroot    * @see handle()
263dad308ecSroot    */
264dad308ecSroot    function render($mode, Doku_Renderer $renderer, $data) {
265dad308ecSroot
266dad308ecSroot        if (empty($data)) return false;
267dad308ecSroot
268dad308ecSroot        if($mode == 'xhtml'){
269dad308ecSroot            if ($data['type'] != "menubar"){
270ddbf0766SEli Fenton                    $renderer->doc .= '<div class="menu menu'.$data['float'].' menu'.$data['valign'].'"';
271ff0823ddSEli Fenton                    $renderer->doc .= ' style="width:' . $data['width'] . '">'."\n";
272dad308ecSroot                    if (isset($data['caption']))
273dad308ecSroot                        $renderer->doc .= '<p class="caption">'.$data['caption'].'</p>'."\n";
274dad308ecSroot
275ff0823ddSEli Fenton                    $width = floor(100 / $data['columns']) . '%';
276ff0823ddSEli Fenton
277dad308ecSroot                    foreach($data['items'] as $item) {
278ff0823ddSEli Fenton                        $renderer->doc .= '<div class="menuitem" style="width:' . $width . '">'."\n";
279dad308ecSroot
280dad308ecSroot                        // create <img .. /> tag
281dad308ecSroot                        list($type, $args) = $item['image'];
282dad308ecSroot                        list($ext,$mime,$dl) = mimetype($args[0]);
283dad308ecSroot                        $class = ($ext == 'png') ? ' png' : NULL;
284dad308ecSroot                        $img = $renderer->_media($args[0],$args[1],$class,$args[3],$args[4],$args[5]);
285dad308ecSroot
286dad308ecSroot                        // create <a href= .. /> tag
287dad308ecSroot                        list($type, $args) = $item['link'];
288dad308ecSroot                        $link = $this->_getLink($type, $args, $renderer);
289dad308ecSroot                        $link['title'] = $args[1];
290dad308ecSroot
291dad308ecSroot                        $link['name']  = $img;
292dad308ecSroot                        $renderer->doc .= $renderer->_formatLink($link);
293dad308ecSroot
294dad308ecSroot                        $link['name']  = '<span class="menutext">'.$args[1].'</span>';
295ff0823ddSEli Fenton                        $renderer->doc .= '<div class="menutextcontainer">'."\n";
296dad308ecSroot                        $renderer->doc .= $renderer->_formatLink($link);
297dad308ecSroot                        $renderer->doc .= '<p class="menudesc">'.$item['descr'].'</p>';
298dad308ecSroot                        $renderer->doc .= '</div>'."\n";
299ff0823ddSEli Fenton
300ff0823ddSEli Fenton                        $renderer->doc .= '</div>'."\n";
301dad308ecSroot                    }
302dad308ecSroot
303dad308ecSroot                    $renderer->doc .= '</div>'."\n";
304dad308ecSroot
305ff0823ddSEli Fenton                    // Clear left/right floats, unless the 'wrap' setting is enabled.
306ff0823ddSEli Fenton                    if (!$data['wrap'] && ($data['float'] == "right" || $data['float'] == "left"))
307dad308ecSroot                        $renderer->doc .= '<p style="clear:both;" />';
308dad308ecSroot
309dad308ecSroot                    return true;
310dad308ecSroot            }
311dad308ecSroot            // menubar mode: 1 row with small captions
312dad308ecSroot            if ($data['type'] == "menubar"){
313dad308ecSroot                    $renderer->doc .= '<div id="menu"><ul class="menubar">'."\n";
314dad308ecSroot                  //  if (isset($data['caption']))
315dad308ecSroot                  //      $renderer->doc .= '<p class="caption">'.$data['caption'].'</p>'."\n";
316dad308ecSroot
317dad308ecSroot                    foreach($data['items'] as $item) {
318dad308ecSroot                        $renderer->doc .= '<li>'."\n";
319dad308ecSroot
320dad308ecSroot                        // create <img .. /> tag
321dad308ecSroot                        list($type, $args) = $item['image'];
322dad308ecSroot                        list($ext,$mime,$dl) = mimetype($args[0]);
323dad308ecSroot                        $class = ($ext == 'png') ? ' png' : NULL;
324dad308ecSroot                        $img = $renderer->_media($args[0],$item['descr'],$class,$args[3],$args[4],$args[5]);
325dad308ecSroot
326dad308ecSroot                        // create <a href= .. /> tag
327dad308ecSroot                        list($type, $args) = $item['link'];
328dad308ecSroot                        $link = $this->_getLink($type, $args, $renderer);
329dad308ecSroot                        $link['title'] = $args[1];
330dad308ecSroot
331dad308ecSroot                        $link['name']  = $img;
332dad308ecSroot                        $renderer->doc .= $renderer->_formatLink($link);
333dad308ecSroot
334dad308ecSroot                        $link['name']  = '<p class="menutext">'.$args[1].'</p>';
335dad308ecSroot                        $renderer->doc .= $renderer->_formatLink($link);
336dad308ecSroot                        //$renderer->doc .= '<p class="menudesc">'.$item['descr'].'</p>';
337dad308ecSroot                        $renderer->doc .= '</li>';
338dad308ecSroot                    }
339dad308ecSroot
340dad308ecSroot                    $renderer->doc .= '</ul></div>'."\n";
341dad308ecSroot
342dad308ecSroot                    return true;
343dad308ecSroot            }
344dad308ecSroot
345dad308ecSroot        }
346dad308ecSroot        return false;
347dad308ecSroot    }
348dad308ecSroot
349dad308ecSroot    function _createLink($url, $target=NULL)
350dad308ecSroot    {
351dad308ecSroot        global $conf;
352dad308ecSroot
353dad308ecSroot        $link = array();
354dad308ecSroot        $link['class']  = '';
355dad308ecSroot        $link['style']  = '';
356dad308ecSroot        $link['pre']    = '';
357dad308ecSroot        $link['suf']    = '';
358dad308ecSroot        $link['more']   = '';
359dad308ecSroot        $link['title']  = '';
360dad308ecSroot        $link['name']   = '';
361dad308ecSroot        $link['url']    = $url;
362dad308ecSroot
363dad308ecSroot        $link['target'] = $target == NULL ? '' : $conf['target'][$target];
364dad308ecSroot        if ($target == 'interwiki' && strpos($url,DOKU_URL) === 0) {
365dad308ecSroot            //we stay at the same server, so use local target
366dad308ecSroot            $link['target'] = $conf['target']['wiki'];
367dad308ecSroot        }
368dad308ecSroot
369dad308ecSroot        return $link;
370dad308ecSroot    }
371dad308ecSroot
372dad308ecSroot    function _getLink($type, $args, &$renderer)
373dad308ecSroot    {
374dad308ecSroot        global $ID;
375ff0823ddSEli Fenton        global $conf;
376dad308ecSroot
377dad308ecSroot        $check = false;
378dad308ecSroot        $exists = false;
379dad308ecSroot
380dad308ecSroot        switch ($type) {
381dad308ecSroot        case 'interwikilink':
382dad308ecSroot            $url  = $renderer->_resolveInterWiki($args[2],$args[3]);
383dad308ecSroot            $link = $this->_createLink($url, 'interwiki');
384dad308ecSroot            break;
385dad308ecSroot        case 'windowssharelink':
386dad308ecSroot            $url  = str_replace('\\','/',$args[0]);
387dad308ecSroot            $url  = 'file:///'.$url;
388dad308ecSroot            $link = $this->_createLink($url, 'windows');
389dad308ecSroot            break;
390dad308ecSroot        case 'externallink':
391dad308ecSroot            $link = $this->_createLink($args[0], 'extern');
392dad308ecSroot            break;
393dad308ecSroot        case 'emaillink':
394dad308ecSroot            $address = $renderer->_xmlEntities($args[0]);
395dad308ecSroot            $address = obfuscate($address);
396dad308ecSroot            if ($conf['mailguard'] == 'visible')
397dad308ecSroot                 $address = rawurlencode($address);
398dad308ecSroot
399dad308ecSroot            $link = $this->_createLink('mailto:'.$address);
400dad308ecSroot            $link['class'] = 'JSnocheck';
401dad308ecSroot            break;
402dad308ecSroot        case 'locallink':
403dad308ecSroot            $hash = sectionID($args[0], $check);
404dad308ecSroot            $link = $this->_createLink('#'.$hash);
405dad308ecSroot            $link['class'] = "wikilink1";
406dad308ecSroot            break;
407dad308ecSroot        case 'internallink':
408dad308ecSroot            resolve_pageid(getNS($ID),$args[0],$exists);
409dad308ecSroot            $url  = wl($args[0]);
410*cca3ead5SAnna Dabrowska            list($id, $hash) = sexplode('#',$args[0],2);
411dad308ecSroot            if (!empty($hash)) $hash = sectionID($hash, $check);
412dad308ecSroot            if ($hash) $url .= '#'.$hash;    //keep hash anchor
413dad308ecSroot
414dad308ecSroot            $link = $this->_createLink($url, 'wiki');
415dad308ecSroot            $link['class'] = $exists ? 'wikilink1' : 'wikilink2';
416dad308ecSroot            break;
417dad308ecSroot        case 'internalmedia':
418dad308ecSroot            resolve_mediaid(getNS($ID),$args[0], $exists);
419dad308ecSroot            $url  = ml($args[0],array('id'=>$ID,'cache'=>$args[5]),true);
420dad308ecSroot            $link = $this->_createLink($url);
421dad308ecSroot            if (!$exists) $link['class'] = 'wikilink2';
422dad308ecSroot            break;
423dad308ecSroot        case 'externalmedia':
424dad308ecSroot            $url  = ml($args[0],array('cache'=>$args[5]));
425dad308ecSroot            $link = $this->_createLink($url);
426dad308ecSroot            break;
427dad308ecSroot        }
428dad308ecSroot        return $link;
429dad308ecSroot    }
430dad308ecSroot
431dad308ecSroot   /**
432dad308ecSroot    * Parse menu options
433dad308ecSroot    *
434dad308ecSroot    *
435dad308ecSroot    * @param $string String Option string from <menu> tag.
436dad308ecSroot    * @return array of options (name >= option). the array will be empty
437dad308ecSroot    *         if no options are found
438dad308ecSroot    * @private
439dad308ecSroot    */
440dad308ecSroot    function _parseOptions($string) {
441dad308ecSroot		$data = array();
442dad308ecSroot
443dad308ecSroot		$dq    = false;
444dad308ecSroot		$iskey = true;
445dad308ecSroot		$key   = '';
446dad308ecSroot		$val   = '';
447dad308ecSroot
448dad308ecSroot		$len = strlen($string);
449dad308ecSroot		for ($i=0; $i<=$len; $i++) {
450dad308ecSroot			// done for this one?
451*cca3ead5SAnna Dabrowska			if ((isset($string[$i]) && $string[$i] == ',') || $i == $len) {
452dad308ecSroot				$key = trim($key);
453dad308ecSroot				$val = trim($val);
454dad308ecSroot				if($key && $val) $data[strtolower($key)] = $val;
455dad308ecSroot				$iskey = true;
456dad308ecSroot				$key = '';
457dad308ecSroot				$val = '';
458dad308ecSroot				continue;
459dad308ecSroot			}
460dad308ecSroot
461dad308ecSroot			// double quotes
462dad308ecSroot			if ($string[$i] == '"') {
463dad308ecSroot				$dq = $dq ? false : true;
464dad308ecSroot				continue;
465dad308ecSroot			}
466dad308ecSroot
467dad308ecSroot			// key value separator
468dad308ecSroot			if ($string[$i] == '=' && !$dq && $iskey) {
469dad308ecSroot				$iskey = false;
470dad308ecSroot				continue;
471dad308ecSroot			}
472dad308ecSroot
473dad308ecSroot			// default
474dad308ecSroot			if ($iskey)
475dad308ecSroot				$key .= $string[$i];
476dad308ecSroot			else
477dad308ecSroot				$val .= $string[$i];
478dad308ecSroot		}
479dad308ecSroot		return $data;
480dad308ecSroot    }
481dad308ecSroot
482dad308ecSroot}
483dad308ecSroot
484dad308ecSroot//Setup VIM: ex: et ts=4 enc=utf-8 :
485dad308ecSroot?>
486