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