1<?php
2/**
3 * DokuWiki Plugin foldablelist (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  medmen <med-men@gmx.net>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) die();
11
12class syntax_plugin_foldablelist extends DokuWiki_Syntax_Plugin {
13    /**
14     * protected $entry_pattern = ' <note.*?>(?=.*?</note>)';
15     */
16    protected $entry_pattern   = '<foldablelist.*?>(?=.*?</foldablelist>)';
17    protected $exit_pattern    = '</foldablelist>';
18
19    /**
20     * @return string Syntax mode type
21     */
22    public function getType() {
23        return 'container';
24    }
25
26    function getAllowedTypes() {
27        return array('container','substition','protected','disabled','formatting','paragraphs');
28    }
29
30    /**
31     * @return string Paragraph type
32     */
33    public function getPType() {
34        return 'block';
35    }
36
37    /**
38     * @return int Sort order - Low numbers go before high numbers
39     */
40    public function getSort() {
41        return 201;
42    }
43
44    /**
45     * Connect lookup pattern to lexer.
46     *
47     * @param string $mode Parser mode
48     */
49    public function connectTo($mode) {
50        // $this->Lexer->addSpecialPattern($this->special_pattern, $mode, 'plugin_foldablelist');
51        $this->Lexer->addEntryPattern($this->entry_pattern, $mode, 'plugin_foldablelist');
52    }
53
54    public function postConnect() {
55        $this->Lexer->addExitPattern($this->exit_pattern, 'plugin_foldablelist');
56    }
57
58
59    /**
60     * Handle matches of the scrollticker syntax
61     *
62     * @param string          $match   The match of the syntax
63     * @param int             $state   The state of the handler
64     * @param int             $pos     The position in the document
65     * @param Doku_Handler    $handler The handler
66     * @return array Data for the renderer
67     */
68    public function handle($match, $state, $pos, Doku_Handler $handler){
69        global $conf;
70        $plugin = $this->getPluginName();
71
72        switch ($state) {
73            case DOKU_LEXER_ENTER:
74                /**
75                 * $match = "<foldablelist collapse_after=5&collapse_level=2>"
76                 */
77                $parameters = trim(substr($match, 13, -1)); // get string between "<foldablelist" and ">"
78                if(strlen(trim($parameters))< 3) {
79                    return array($state, $match, false); // no parameters given, dont bother with extra work
80                }
81
82                // split string by predifined separators
83                $namevaluepairs = preg_split("/[,&]+/", $parameters);
84
85                $params_arr = array();
86
87                if(count($namevaluepairs) < 1 ) {
88                    return array($state, $match, $params_arr);
89                }
90
91                foreach ($namevaluepairs as $parameters) {
92                    if($parameters and strpos($parameters, '=')) { // see if we have a string and it contains at least one '='
93                        $parameters = preg_split('/\s+/', $parameters, -1, PREG_SPLIT_NO_EMPTY); // turn into array separated by whit spaces
94                        foreach($parameters as $parameter) {
95                            list($key, $val) = explode('=', $parameter);
96                            $key = 'data-'.strtolower(trim(htmlspecialchars($key))); // http://html5doctor.com/html5-custom-data-attributes/
97                            $val = strtolower(trim(htmlspecialchars($val)));
98                            $params_arr[$key] = $val;
99                        }
100                    }
101                }
102
103                return array($state, $match, $params_arr);
104
105            default:
106                return array($state, $match, false);
107        }
108    }
109
110    /**
111     * Render xhtml output or metadata
112     *
113     * @param string         $mode      Renderer mode (supported modes: xhtml)
114     * @param Doku_Renderer  $renderer  The renderer
115     * @param array          $data      The data from the handler() function
116     * @return bool If rendering was successful.
117     */
118    public function render($mode, Doku_Renderer $renderer, $data) {
119        global $conf;
120        if($mode != 'xhtml') return false;
121        if (empty($data)) return false;
122
123        list($state, $match, $parameters) = $data;
124
125        switch ($state) {
126            case DOKU_LEXER_ENTER :
127                // xdebug_break();
128                if(is_array($parameters) and count($parameters) > 0) {
129                    // implode array fast
130                    $parameters = http_build_query($parameters,'', ' ');
131                }
132
133                $renderer->doc .= '<div class="foldablelist" '.$parameters.'>';
134                break;
135            case DOKU_LEXER_UNMATCHED :
136                $renderer->doc .= $renderer->_xmlEntities($match);
137                break;
138            case DOKU_LEXER_EXIT :
139                $renderer->doc .= '</div>';
140                break;
141            default:
142                $renderer->doc.= 'MATCH: '.$renderer->_xmlEntities($match);
143                $renderer->doc.= 'STATE: '.$renderer->_xmlEntities($state);
144                $renderer->doc.= 'PARAMS: '.$renderer->_xmlEntities($parameters);
145        }
146
147        // $renderer->doc .= var_export($data, true); // might be helpful when debugging
148        return true;
149    }
150}
151
152// vim:ts=4:sw=4:et: