1<?php
2/**
3 Based on code from http://www.kryogenix.org/code/browser/sorttable/ by Stuart Langridge
4 (distributed under the conditions of MIT licence from http://www.kryogenix.org/code/browser/licence.html).
5 Includes open-source contributions from other people
6 (see https://github.com/FyiurAmron/sortablejs/graphs/contributors for more details).
7 Maintainers:
8 2007-2016 oiv (Otto Vainio at otto@valjakko.net)
9 2016-? vaxquis AKA FyiurAmron (spamove@gmail.com)
10 */
11
12// must be run within Dokuwiki
13if ( !defined( 'DOKU_INC' ) )
14    die();
15if ( !defined( 'DOKU_PLUGIN' ) )
16    define( 'DOKU_PLUGIN', DOKU_INC.'lib/plugins/' );
17require_once(DOKU_PLUGIN.'syntax.php');
18//
19class syntax_plugin_sortablejs extends DokuWiki_Syntax_Plugin {
20
21    function getType() {
22        return 'container';
23    }
24
25    function getPType() {
26        return 'block';
27    }
28
29    function getSort() {
30        return 371;
31    }
32
33    function getAllowedTypes() {
34        return array( 'container', 'formatting', 'substition' );
35    }
36
37    function connectTo( $mode ) {
38        $this->Lexer->addEntryPattern( '<sortable[^>]*>(?=.*?</sortable>)', $mode, 'plugin_sortablejs' );
39    }
40
41    function postConnect() {
42        $this->Lexer->addExitPattern( '</sortable>', 'plugin_sortablejs' );
43    }
44
45    function handle( $match, $state, $pos, Doku_Handler $handler ) {
46
47        switch ( $state ) {
48            case DOKU_LEXER_ENTER :
49                $match = substr( $match, 9, -1 );
50                $match = trim( $match );
51                $scl = "";
52                if ( strlen( $match ) > 0 ) {
53                    $scl = $this->__validateOptions( $match );
54                }
55                return array( $state, $scl );
56            case DOKU_LEXER_UNMATCHED :
57                return array( $state, $match );
58            case DOKU_LEXER_EXIT :
59                return array( $state, "" );
60        }
61        return array();
62    }
63
64    function render( $mode, Doku_Renderer $renderer, $data ) {
65        list($state, $match) = $data;
66        if ( $mode == 'xhtml' ) {
67            switch ( $state ) {
68                case DOKU_LEXER_ENTER :
69                    $renderer->doc .= "<div class=\"sortable$match\">";
70                    break;
71                case DOKU_LEXER_UNMATCHED :
72                    $instructions = p_get_instructions( $match );
73                    foreach( $instructions as $instruction ) {
74                        call_user_func_array( array( &$renderer, $instruction[0] ), $instruction[1] );
75                    }
76
77                    break;
78                case DOKU_LEXER_EXIT :
79                    $renderer->doc .= "</div>";
80                    break;
81            }
82            return true;
83        } else if ( $mode == 'odt' ) {
84            switch ( $state ) {
85                case DOKU_LEXER_ENTER :
86                    // In ODT, tables must not be inside a paragraph. Make sure we
87                    // closed any opened paragraph
88                    $renderer->p_close();
89                    break;
90                case DOKU_LEXER_UNMATCHED :
91                    $instructions = array_slice( p_get_instructions( $match ), 1, -1 );
92                    foreach( $instructions as $instruction ) {
93                        call_user_func_array( array( &$renderer, $instruction[0] ), $instruction[1] );
94                    }
95                    break;
96                case DOKU_LEXER_EXIT :
97                    //$renderer->p_open();
98                    // DO NOT re-open the paragraph, it would cause an error if the table is the last content on a page
99                    break;
100            }
101            return true;
102        }
103        return false;
104    }
105
106    function __validateOptions( $opts ) {
107        if ( empty( $opts ) ) {
108        	return "";
109        }
110        $ret = "";
111        $oa = explode( " ", $opts );
112        foreach( $oa as $opt ) {
113            $explodedOption = explode( "=", $opt );
114            $c = $explodedOption[0];
115            $v = $explodedOption[1] ?? null;
116            if ( $c == "sumrow" ) {
117                $c = $v;
118                $v = "sumrow";
119                if ( $c == "" ) {
120                    $c = "1";
121                }
122            } else if ( $c == "3phase" ) {
123                $v = $c;
124                $c = "";
125            }
126            if ( $v != null ) {
127                $cmpr = $v;
128            } else {
129                if ( preg_match( '/r?\d*/', $c, $matches ) ) {
130                    $cmpr = 'sort';
131                }
132            }
133            switch ( $cmpr ) {
134                case '3phase':
135                    $ret .= " threephase";
136                    break;
137                case 'nosort':
138                    $ret .= " col_".$c."_nosort";
139                    break;
140                case 'numeric':
141                    $ret .= " col_".$c."_numeric";
142                    break;
143                case 'date':
144                    $ret .= " col_".$c."_date";
145                    break;
146                case 'alpha':
147                case 'text':
148                    $ret .= " col_".$c."_alpha";
149                    break;
150                case 'sort':
151                    $ret .= ' sort'.$opt;
152                    break;
153                case 'sumrow':
154                    $ret .= ' sortbottom_'.$c;
155                    break;
156            }
157        }
158        return $ret;
159    }
160}
161