1<?php 2// must be run within DokuWiki 3if(!defined('DOKU_INC')) die(); 4 5if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 6require_once DOKU_PLUGIN.'syntax.php'; 7 8/** 9 * All DokuWiki plugins to extend the parser/rendering mechanism 10 * need to inherit from this class 11 */ 12class action_plugin_dtable extends DokuWiki_Action_Plugin { 13 14 function register(Doku_Event_Handler $controller) { 15 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'add_php_data'); 16 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax'); 17 $controller->register_hook('PARSER_WIKITEXT_PREPROCESS', 'AFTER', $this, 'parser_preprocess_handler'); 18 $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'insert_button', array ()); 19 20 } 21 22 public function insert_button (Doku_Event $event, $param) { 23 $event->data[] = array ( 24 'type' => 'format', 25 'title' => $this->getLang('toolbar_insert_button'), 26 'icon' => '../../plugins/dtable/images/add_table.png', 27 'open' => '<dtable>', 28 'close' => '</dtable>', 29 'sample' => "\n^ ^ ^\n| | |\n| | |\n| | |\n" 30 ); 31 } 32 function parser_preprocess_handler(&$event, $parm) 33 { 34 global $ID, $INFO; 35 $lines = explode("\n", $event->data); 36 $new_lines = array(); 37 //determine dtable page 38 39 //only 100 dtables per page 40 $i = 0; 41 $dtable_pages = array(); 42 foreach($lines as $line) 43 { 44 if(strpos($line, '<dtable>') === 0) { 45 $new_lines[] = '<dtab'.( $i < 10 ? '0'.$i : $i ).'>'; 46 $dtable_pages[$i] = $ID; 47 $i++; 48 } else 49 { 50 $new_lines[] = $line; 51 } 52 } 53 54 //it will make include plugin behaves correctly 55 p_set_metadata($INFO['id'], array('dtable_pages' => $dtable_pages), false, false); 56 57 //mark dtables 58 //it will not work becouse section editing in dokuwiki needs no modified content. 59 if($this->getConf('all_tables')) 60 { 61 $new_lines = array(); 62 63 $in_tab = 0; 64 $in_dtable_tag = 0; 65 66 foreach($lines as $line) 67 { 68 if(strpos($line, '<dtable>') === 0) 69 $in_dtable_tag = 1; 70 if(strpos($line, '</dtable>') === 0) 71 $in_dtable_tag = 0; 72 73 if(strpos($line, '|') !== 0 && $in_tab == 1 && $in_dtable_tag == 0) 74 { 75 $new_lines[] = '</dtable>'; 76 $in_tab = 0; 77 } 78 79 if(strpos($line, '^') === 0 && $in_tab == 0 && $in_dtable_tag == 0) 80 { 81 $new_lines[] = '<dtable>'; 82 $in_tab = 1; 83 } 84 85 $new_lines[] = $line; 86 } 87 $lines = $new_lines; 88 } 89 $event->data = implode("\n", $new_lines); 90 } 91 function add_php_data(&$event, $param) { 92 global $JSINFO, $ID; 93 94 if (auth_quickaclcheck($ID) >= AUTH_EDIT) 95 $JSINFO['write'] = true; 96 else 97 $JSINFO['write'] = false; 98 99 $JSINFO['disabled'] = explode(',', $this->getConf('disabled')); 100 101 102 $JSINFO['lang']['insert_before'] = $this->getLang('insert_before'); 103 $JSINFO['lang']['insert_after'] = $this->getLang('insert_after'); 104 $JSINFO['lang']['edit'] = $this->getLang('edit'); 105 $JSINFO['lang']['remove'] = $this->getLang('remove'); 106 $JSINFO['lang']['insert_col_left'] = $this->getLang('insert_col_left'); 107 $JSINFO['lang']['insert_col_right'] = $this->getLang('insert_col_right'); 108 $JSINFO['lang']['mark_row_as_header'] = $this->getLang('mark_row_as_header'); 109 $JSINFO['lang']['mark_col_as_header'] = $this->getLang('mark_col_as_header'); 110 $JSINFO['lang']['mark_cell_as_header'] = $this->getLang('mark_cell_as_header'); 111 112 $JSINFO['lang']['mark_row_as_cell'] = $this->getLang('mark_row_as_cell'); 113 $JSINFO['lang']['mark_col_as_cell'] = $this->getLang('mark_col_as_cell'); 114 $JSINFO['lang']['mark_cell_as_cell'] = $this->getLang('mark_cell_as_cell'); 115 116 $JSINFO['lang']['show_merged_rows'] = $this->getLang('show_merged_rows'); 117 118 $JSINFO['lang']['lock_notify'] = str_replace( 119 array('%u', '%t'), 120 array('<span class="who"></span>', '<span class="time_left"></span>'), 121 $this->getLang('lock_notify')); 122 $JSINFO['lang']['unlock_notify'] = $this->getLang('unlock_notify'); 123 } 124 function handle_ajax(&$event, $param) 125 { 126 global $conf; 127 128 switch($event->data) 129 { 130 case 'dtable': 131 $event->preventDefault(); 132 $event->stopPropagation(); 133 134 135 136 $json = new JSON(); 137 138 list($dtable_start_line, $dtable_page_id) = explode('_', $_POST['table'], 2); 139 $file = wikiFN( $dtable_page_id ); 140 if( ! @file_exists( $file ) ) 141 { 142 echo $json->encode( array('type' => 'error', 'msg' => 'This page does not exist.') ); 143 exit(0); 144 } 145 146 $dtable =& plugin_load('helper', 'dtable'); 147 148 $page_lines = explode( "\n", io_readFile( $file ) ); 149 150 if(isset($_POST['remove'])) 151 { 152 $scope = $json->decode($_POST['remove']); 153 154 $lines_to_remove = array(); 155 for ($i = $scope[0]; $i <= $scope[1]; $i++) 156 $lines_to_remove[] = $i; 157 158 $removed_line = ''; 159 foreach ($lines_to_remove as $line) { 160 $removed_line .= $page_lines[ $line ]." "; 161 } 162 163 array_splice($page_lines, $scope[0], $scope[1] - $scope[0] + 1); 164 165 $new_cont = implode( "\n", $page_lines ); 166 167 saveWikiText($dtable_page_id, $new_cont, $this->getLang('summary_remove').' '.$removed_line); 168 169 170 171 echo $json->encode( array('type' => 'success', 'spans' => 172 $dtable->get_spans($dtable_start_line, $page_lines, $dtable_page_id) ) ); 173 174 } else 175 { 176 $cols = array(); 177 $new_table_line = array(); 178 foreach( $_POST as $k => $v ) 179 { 180 if( strpos( $k, 'col' ) === 0) 181 { 182 //remove col from col12, col1 etc. to be 12 1 183 $cols[(int)substr($k, 3)] = $json->decode($v); 184 } 185 } 186 ksort($cols); 187 188 //reset index 189 $cols = array_values($cols); 190 191 $j = 0; 192 for($i = 0; $i < count($cols); $i++) { 193 $class = $cols[$i][0]; 194 $value = $cols[$i][1]; 195 196 if ($value == '' && $j >= 1) 197 $new_table_line[$j-1][1]++; 198 else { 199 $type = $class == 'tablecell_open' ? '|' : '^'; 200 $new_table_line[$j] = array(1, 1, $type, $value); 201 $j++; 202 } 203 } 204 $new_line = $dtable->format_row($cols); 205 206 if( isset( $_POST['add'] ) ) 207 { 208 $action = 'add'; 209 210 /*$table_line = (int) $_POST['add'] + 1; 211 $line_to_add = $dtable_start_line + $table_line;*/ 212 $line_to_add = (int) $_POST['add'] + 1; 213 214 array_splice($page_lines, $line_to_add, 0, $new_line ); 215 $line_nr = $line_to_add; 216 217 $info = $this->getLang('summary_add').' '.$new_line; 218 219 } elseif( isset( $_POST['edit'] ) ) 220 { 221 $action = 'edit'; 222 223 $scope = $json->decode($_POST['edit']); 224 225 $lines_to_change = array(); 226 for ($i = $scope[0]; $i <= $scope[1]; $i++) 227 $lines_to_change[] = $i; 228 229 $old_line= ''; 230 foreach ($lines_to_change as $line) { 231 $old_line .= $page_lines[ $line ]." "; 232 } 233 234 //$old_line = $page_lines[ $line_to_change ]; 235 236 array_splice($page_lines, $scope[0], $scope[1] - $scope[0] + 1, $new_line); 237 $line_nr = $scope[0]; 238 239 $new_cont = implode( "\n", $page_lines ); 240 241 $info = str_replace( array('%o', '%n'), array($old_line, $new_line), $this->getLang('summary_edit') ); 242 } 243 244 $new_cont = implode( "\n", $page_lines ); 245 saveWikiText($dtable_page_id, $new_cont, $info); 246 247 echo $json->encode( array('type' => 'success', 'action' => $action, 'new_row' => $dtable->parse_line($new_line, $dtable_page_id), 'raw_row' => array($new_table_line, array($line_nr, $line_nr)), 'spans' => $dtable->get_spans($dtable_start_line, $page_lines, $dtable_page_id) ) ); 248 249 } 250 break; 251 case 'dtable_page_lock': 252 $event->preventDefault(); 253 $event->stopPropagation(); 254 255 $ID = $_POST['page']; 256 lock($ID); 257 break; 258 case 'dtable_page_unlock': 259 $event->preventDefault(); 260 $event->stopPropagation(); 261 262 $ID = $_POST['page']; 263 unlock($ID); 264 break; 265 case 'dtable_is_page_locked': 266 $event->preventDefault(); 267 $event->stopPropagation(); 268 269 $ID = $_POST['page']; 270 $checklock = checklock($ID); 271 272 //check when lock expire 273 $lock_file = wikiLockFN($ID); 274 if(file_exists($lock_file)) 275 { 276 $locktime = filemtime(wikiLockFN($ID)); 277 //dokuwiki uses dformat here but we will use raw unix timesamp 278 $expire = $locktime + $conf['locktime'] - time(); 279 } else 280 $expire = $conf['locktime']; 281 282 $json = new JSON(); 283 284 if($checklock === false) 285 echo $json->encode(array('locked' => 0, 'time_left' => $expire)); 286 else 287 echo $json->encode(array('locked' => 1, 'who' => $checklock, 'time_left' => $expire)); 288 289 break; 290 } 291 } 292} 293