1<?php
2/**
3 * exttab1-Plugin: Parses extended tables (like MediaWiki)
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Werner Flamme <w.flamme@web.de>
7 * @date       2006-10-19
8 */
9
10if(!defined('DOKU_INC'))
11    define('DOKU_INC', realpath(dirname(__FILE__) . '/../../') . '/');
12if(!defined('DOKU_PLUGIN'))
13    define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
14require_once(DOKU_PLUGIN . 'syntax.php');
15
16/**
17 * All DokuWiki plugins to extend the parser/rendering mechanism
18 * need to inherit from this class
19 */
20class syntax_plugin_exttab1 extends DokuWiki_Syntax_Plugin {
21    /** settings
22    *
23    */
24    var $lineHasStartTag = false;
25    var $lineHasEndTag   = false;
26    var $bodyHasStartTag = false;
27    var $tableHasHeader  = false;
28
29    /**
30     * return some info
31     */
32    function getInfo()
33    {
34        return array(
35            'author' => 'Werner Flamme',
36            'email'  => 'w.flamme@web.de',
37            'date'   => '2006-10-19',
38            'name'   => 'Extended Table Plugin',
39            'desc'   => 'parses MediaWiki-like tables',
40            'url'    => 'http://www.dokuwiki.org/doku.php?id=plugin:exttab1'
41        );
42    } // function getInfo
43
44    /**
45    * What kind of syntax are we?
46    */
47    function getType()
48    {
49        return 'protected';
50    } // function getType
51
52    /**
53    * What kind of plugin are we?
54    */
55    function getPType()
56    {
57        return 'block';
58    } // function getPType
59
60    /**
61    * Where to sort in?
62    */
63    function getSort()
64    {
65        return 100;
66    } // function getSort
67
68    /**
69    * Connect pattern to lexer
70    */
71    function connectTo($mode)
72    {
73        $this->Lexer->addEntryPattern('<exttab1(?=.*</exttab1>)', $mode, 'plugin_exttab1');
74    } // function connectTo
75
76    function postConnect()
77    {
78        $this->Lexer->addExitPattern('</exttab1>', 'plugin_exttab1');
79    } // function postConnect
80
81    /**
82     * Handle the match
83    */
84    function handle($match, $state, $pos)
85    {
86      if ( $state == DOKU_LEXER_UNMATCHED ) {
87        $matches = preg_split('/>/u', $match, 2);
88        $matches[0] = trim($matches[0]);
89        if ( trim($matches[0]) == '' ) {
90          $matches[0] = NULL;
91        } // if ( trim($matches[0]) == '' )
92        return array($matches[1], $matches[0]);
93      } // if ( $state == DOKU_LEXER_UNMATCHED )
94      return true;
95    } // function handle
96
97    /**
98     * Create output
99     @param $mode       current mode of DokuWiki (see http://www.dokuwiki.org/plugin:tutorial)
100     @param $renderer   DokuWiki's rendering object
101     @param $data       the data between \<exttab1> and \</exttab1> tags
102     @var   $rawdata    $data split into lines
103     @var   $rawline    any line of $rawdata
104     @var   $mytable    the code that will be inserted into the document
105     @return true, if rendering happens, false in all other cases
106    */
107    function render($mode, Doku_Renderer $renderer, $data)
108    {
109        if ($mode == 'xhtml' && strlen($data[0]) > 1) {
110            $rawdata = explode("\n", $data[0]);
111            $mytable = '';
112            $this->lineHasStartTag = false;
113            $this->lineHasEndTag   = false;
114            foreach ($rawdata as $rawline) {
115                $rawline = trim($rawline);
116                if (substr($rawline, 0, 2) == '|-') {
117                    // new table line
118                    $mytable .= $this->_handleNewTableLine($rawline);
119                } // new table line
120                elseif (substr($rawline, 0, 2) == '{|') {
121                    // start table
122                    $mytable .= $this->_handleTableStart($rawline);
123                } // start table
124                elseif (substr($rawline, 0, 2) == '|}') {
125                    // end table
126                    $mytable .= "    </tr>\n  </tbody>\n</table>\n";
127                    $this->bodyHasStartTag = false;
128                } // end table
129                elseif (substr($rawline, 0, 2) == '|+') {
130                    // table caption
131                    $mytable .= $this->_handleTableCaption($rawline);
132                } // table caption
133                elseif (substr($rawline, 0, 1) == '|') {
134                    // regular line
135                    $mytable .= $this->_handleRegularLine($rawline);
136                } // regular line
137                elseif (substr($rawline, 0, 1) == '!') {
138                    // header line
139                    $mytable .= $this->_handleHeaderLine($rawline);
140                } // header line
141            } // foreach ($rawdata as $rawline)
142            $renderer->doc .= $mytable;
143            return true;
144        } // if ($mode == 'xhtml' && strlen($data[0]) > 1)
145        return false;
146    } // function render
147
148    /**
149        handle tags for a new table line
150        @param $linedata    the line to be interpreted
151        @return HTML code
152    **/
153    function _handleNewTableLine($linedata)
154    {
155        $my2c = '';
156        if (!$this->lineHasEndTag) {
157            $my2c .= "    </tr>\n";
158            $this->lineHasEndTag   = true;
159            $this->lineHasStartTag = false;
160        } //if (!this->lineHasEndTag)
161        if ($this->tableHasHeader) {
162            $my2c .= "  </thead>\n";
163            $this->tableHasHeader = false;
164        } // if ($this->tableHasHeader)
165        if (!$this->bodyHasStartTag) {
166            $my2c .= "  <tbody>\n";
167            $this->bodyHasStartTag = true;
168        } // if (!$this->bodyHasStartTag)
169        if (!$this->lineHasStartTag) {
170            $my2c .= "    <tr " . substr($linedata, 2) . ">\n";
171            $this->lineHasStartTag = true;
172            $this->lineHasEndTag   = false;
173        } // if (!$this->lineHasStartTag)
174        return $my2c;
175    } // function _handleNewTableLine
176
177    /**
178        handle start of table
179        @param $linedata    the line to be interpreted
180        @return HTML code
181    **/
182    function _handleTableStart($linedata)
183    {
184        if (strlen(trim($linedata)) > 2)
185            $fillInData = 'class="exttab1" ' . substr($linedata, 2);
186        else
187            $fillInData = 'class="exttab1"';
188        $my2c = "\n<table $fillInData>\n";
189        $this->lineHasStartTag = false;
190        $this->bodyHasStartTag = false;
191        $this->lineHasEndTag   = true;
192        return $my2c;
193    } // function _handleTableStart
194
195    /**
196        handle table caption
197        @param $linedata    the line to be interpreted
198        @return HTML code
199    **/
200    function _handleTableCaption($linedata)
201    {
202        $my2c = '';
203        if ($this->lineHasStartTag)
204            $my2c .= "    </tr>\n";
205        if ( ($pos = strpos($linedata, '|', 2)) !== false ) {
206            $parsedData = $this->_parseDisplayData(trim(substr($linedata, $pos + 1)));
207            $my2c .= '  <caption ' . trim(substr($linedata, 2, $pos - 2)) . '>' .
208                        "$parsedData</caption>\n";
209        } // formatting data plus content
210        else {
211            $parsedData = $this->_parseDisplayData(trim(substr($linedata, 2)));
212            $my2c .= "  <caption>$parsedData</caption>\n";
213        } // content only
214        $this->lineHasStartTag = false;
215        $this->lineHasEndTag   = true;
216        $my2c .= "  <tbody>\n";
217        $this->bodyHasStartTag = true;
218        return $my2c;
219    } // function _handleTableCaption
220
221    /**
222        handles regular table line
223        @param $linedata    the line to be interpreted
224        @return HTML code
225    **/
226    function _handleRegularLine($linedata)
227    {
228        $my2c = '';
229        if (!$this->lineHasStartTag) {
230            if (!$this->bodyHasStartTag) {
231                $my2c .= "  <tbody>\n";
232                $this->bodyHasStartTag = true;
233            } // if (!$this->bodyHasStartTag)
234            $my2c .= "    <tr>\n";
235            $this->lineHasStartTag = true;
236            $this->lineHasEndTag   = false;
237        } // if (!$lineHasStartTag)
238        $subitems = explode('||', $linedata);
239        foreach($subitems as $pick) {
240            if ( ($pos = strpos($pick, '|', 1)) !== false ) {
241                $parsedData = $this->_parseDisplayData(trim(substr($pick, $pos + 1)));
242                $my2c .= '      <td ' . trim(substr($pick, 1, $pos - 1)) . '>' .
243                            "$parsedData</td>\n";
244            } // formatting data plus content
245            else {
246                $parsedData = $this->_parseDisplayData(trim(substr($pick, 1)));
247                $my2c .= '      <td>' . "$parsedData</td>\n";
248            } // content only
249        } // foreach($subitems as $pick)
250        return $my2c;
251    } // function _handleRegularLine
252
253    /**
254        handles table header entries
255        @param $linedata    the line to be interpreted
256        @return HTML code
257    **/
258    function _handleHeaderLine($linedata)
259    {
260        $my2c = '';
261        if (!$this->lineHasStartTag) {
262            $my2c .= "  <thead>\n    <tr>\n";
263            $this->lineHasStartTag = true;
264            $this->lineHasEndTag   = false;
265            $this->tableHasHeader  = true;
266        } // if (!$lineHasStartTag)
267        $subitems = explode('!!', $linedata);
268        foreach ($subitems as $pick) {
269            if ( ($pos = strpos($pick, '|', 1)) !== false ) {
270                $parsedData = $this->_parseDisplayData(trim(substr($pick, $pos + 1)));
271                // formatting data plus content
272                $my2c .= '      <th ' . trim(substr($pick, 1, $pos - 1)) . '>' .
273                            "$parsedData</th>\n";
274            } // formatting data plus content
275            else {
276                // content only
277                $parsedData = $this->_parseDisplayData(trim(substr($pick, 1)));
278                $my2c .= '      <th>' . "$parsedData</th>\n";
279            } // content only
280        } // foreach ($subitems as $pick)
281        return $my2c;
282    } // function _handleHeaderLine
283
284    /**
285        this function parses data "internally"
286    **/
287    function _parseDisplayData($mydata)
288    {
289        $retval = $mydata;
290        $really = false;
291        $allowedTags = array('}}', ']]', "''");
292        foreach ($allowedTags as $tag) {
293            $really = ($really or (strrpos($mydata, $tag) > 0));
294        } // foreach ($allowedTags as $tag)
295        if ($really) {
296            if (!function_exists('p_get_instructions'))
297                require_once(DOKU_INC . 'inc/parserutils.php');
298            $instruc = p_get_instructions($mydata);
299            $myinfo  = array();
300            $retval = p_render('xhtml', $instruc, $myinfo);
301            $retval = str_replace('\n', '', $retval);
302            $retval = substr($retval, 4, -5);
303        } // if ($really)
304        return $retval;
305    } // function _parseDisplayData
306
307} // class syntax_plugin_exttab1
308
309//Setup VIM: ex: et ts=4 enc=utf-8 :