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