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