Skip to content

Commit 1fcf871

Browse files
committed
basic JS based sync interface works
1 parent 3e7646f commit 1fcf871

File tree

4 files changed

+345
-121
lines changed

4 files changed

+345
-121
lines changed

Profile.php

Lines changed: 72 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ class Profile {
1010
const DIR_PUSH_DEL = 2;
1111
const DIR_NONE = 0;
1212

13+
const TYPE_BOTH = 0;
14+
const TYPE_PAGES = 1;
15+
const TYPE_MEDIA = 2;
16+
1317
/** @var array hold the profile configuration */
1418
protected $config;
1519
/** @var Client the API client */
1620
protected $client;
1721
/** @var array the options we use to query the files to sync */
1822
protected $syncoptions;
1923
/** @var array the list of files to sync */
20-
protected $synclist;
24+
protected $synclist = [];
2125

2226
/**
2327
* Profile constructor.
@@ -45,7 +49,7 @@ public function __construct($config) {
4549
* @param string|null $key when a key is given only that key's config value is returned
4650
* @return mixed
4751
*/
48-
public function getConfig($key=null) {
52+
public function getConfig($key = null) {
4953
if($key !== null) {
5054
if(isset($this->config[$key])) {
5155
return $this->config[$key];
@@ -83,23 +87,27 @@ public function getTimes() {
8387
/**
8488
* Get a list of changed files
8589
*
86-
* @param string $type pages|media
8790
* @return array
8891
*/
89-
public function getSyncList($type) {
90-
$this->fetchRemoteFileList($type);
91-
$this->fetchLocalFileList($type);
92-
$this->consolidateSyncList($type);
92+
public function getSyncList() {
93+
if($this->config['type'] == self::TYPE_PAGES || $this->config['type'] == self::TYPE_BOTH) {
94+
$this->fetchRemoteFileList(self::TYPE_PAGES);
95+
$this->fetchLocalFileList(self::TYPE_PAGES);
96+
}
97+
if($this->config['type'] == self::TYPE_MEDIA || $this->config['type'] == self::TYPE_BOTH) {
98+
$this->fetchRemoteFileList(self::TYPE_MEDIA);
99+
$this->fetchLocalFileList(self::TYPE_MEDIA);
100+
}
93101

102+
$this->consolidateSyncList();
94103
ksort($this->synclist); #FIXME implement our own sort with dir=0 at the top
95-
96104
return $this->synclist;
97105
}
98106

99107
/**
100108
* Synchronise the given file
101109
*
102-
* @param string $type pages|media
110+
* @param int $type pages|media
103111
* @param string $id the ID of the page or media
104112
* @param int $dir the sync direction
105113
* @param string $summary the editing summary
@@ -126,21 +134,21 @@ public function syncFile($type, $id, $dir, $summary) {
126134
/**
127135
* Sync from remote to local
128136
*
129-
* @param string $type pages|media
137+
* @param int $type pages|media
130138
* @param string $id the ID of the page or media
131139
* @param string $summary the editing summary
132140
* @throws SyncException
133141
*/
134142
protected function syncPull($type, $id, $summary) {
135-
if($type == 'pages') {
143+
if($type === self::TYPE_PAGES) {
136144
if(checklock($id)) throw new SyncException('Local file is locked');
137145
$this->client->query('wiki.getPage', $id);
138146
} else {
139147
$this->client->query('wiki.getAttachment', $id);
140148
}
141149

142150
$data = $this->client->getResponse();
143-
if($type == 'pages') {
151+
if($type === self::TYPE_PAGES) {
144152
saveWikiText($id, $data, $summary, false);
145153
idx_addPage($id);
146154
} else {
@@ -151,13 +159,13 @@ protected function syncPull($type, $id, $summary) {
151159
/**
152160
* Delete a local file
153161
*
154-
* @param string $type pages|media
162+
* @param int $type pages|media
155163
* @param string $id the ID of the page or media
156164
* @param string $summary the editing summary
157165
* @throws SyncException
158166
*/
159167
protected function syncPullDelete($type, $id, $summary) {
160-
if($type == 'pages') {
168+
if($type === self::TYPE_PAGES) {
161169
if(checklock($id)) throw new SyncException('Local file is locked');
162170
saveWikiText($id, '', $summary, false);
163171
} else {
@@ -168,13 +176,13 @@ protected function syncPullDelete($type, $id, $summary) {
168176
/**
169177
* Sync from local to remote
170178
*
171-
* @param string $type pages|media
179+
* @param int $type pages|media
172180
* @param string $id the ID of the page or media
173181
* @param string $summary the editing summary
174182
* @throws SyncException
175183
*/
176184
protected function syncPush($type, $id, $summary) {
177-
if($type == 'pages') {
185+
if($type === self::TYPE_PAGES) {
178186
$this->setRemoteLock($id, true);
179187
$data = rawWiki($id);
180188
$this->client->query('wiki.putPage', $id, $data, array('sum' => $summary));
@@ -189,13 +197,13 @@ protected function syncPush($type, $id, $summary) {
189197
/**
190198
* Delete a remote file
191199
*
192-
* @param string $type pages|media
200+
* @param int $type pages|media
193201
* @param string $id the ID of the page or media
194202
* @param string $summary the editing summary
195203
* @throws SyncException
196204
*/
197205
protected function syncPushDelete($type, $id, $summary) {
198-
if($type == 'pages') {
206+
if($type === self::TYPE_PAGES) {
199207
$this->setRemoteLock($id, true);
200208
$this->client->query('wiki.putPage', $id, '', array('sum' => $summary));
201209
$this->setRemoteLock($id, false);
@@ -230,10 +238,10 @@ protected function setRemoteLock($id, $state) {
230238
/**
231239
* put all remote files for this profile into the sync list
232240
*
233-
* @param string $type pages|media
241+
* @param int $type pages|media
234242
*/
235243
protected function fetchRemoteFileList($type) {
236-
if($type == 'pages') {
244+
if($type === self::TYPE_PAGES) {
237245
$cmd = 'dokuwiki.getPagelist';
238246
} else {
239247
$cmd = 'wiki.getAttachments';
@@ -244,19 +252,19 @@ protected function fetchRemoteFileList($type) {
244252

245253
// put into synclist
246254
foreach($remote as $item) {
247-
$this->synclist[$type][$item['id']]['remote'] = $item;
255+
$this->synclist[$type][$item['id']]['remote'] = $this->itemEnhance($item);
248256
}
249257
}
250258

251259
/**
252260
* put all local files for this profile into the sync list
253261
*
254-
* @param string $type pages|media
262+
* @param int $type pages|media
255263
*/
256264
protected function fetchLocalFileList($type) {
257265
global $conf;
258266

259-
if($type == 'pages') {
267+
if($type === self::TYPE_PAGES) {
260268
$basedir = $conf['datadir'];
261269
$cmd = 'search_allpages';
262270
} else {
@@ -270,52 +278,63 @@ protected function fetchLocalFileList($type) {
270278

271279
// put into synclist
272280
foreach($local as $item) {
273-
$this->synclist[$type][$item['id']]['local'] = $item;
281+
$this->synclist[$type][$item['id']]['local'] = $this->itemEnhance($item);
274282
}
275283
}
276284

277285
/**
278-
* removes all files that do not need syncing and calulates direction for the rest
286+
* Enance item with formatted info
279287
*
280-
* @param $type
288+
* @param array $item
289+
* @return mixed
290+
*/
291+
protected function itemEnhance($item) {
292+
$item['info'] = dformat($item['mtime']) . '<br />' . filesize_h($item['size']);
293+
return $item;
294+
}
295+
296+
/**
297+
* removes all files that do not need syncing and calulates direction for the rest
281298
*/
282-
protected function consolidateSyncList($type) {
299+
protected function consolidateSyncList() {
283300
// synctimes
284301
$ltime = (int) $this->config['ltime'];
285302
$rtime = (int) $this->config['rtime'];
286303
$letime = (int) $this->config['letime'];
287304
$retime = (int) $this->config['retime'];
288305

289-
foreach($this->synclist[$type] as $id => $item) {
290-
291-
// no sync if hashes match
292-
if($item['remote']['hash'] == $item['local']['hash']) {
293-
unset($this->synclist[$type][$item['id']]);
294-
continue;
295-
}
306+
foreach([self::TYPE_PAGES, self::TYPE_MEDIA] as $type) {
307+
foreach($this->synclist[$type] as $id => $item) {
296308

297-
// check direction
298-
$dir = self::DIR_NONE;
299-
if($ltime && $rtime) { // synced before
300-
if($item['remote']['mtime'] > $rtime &&
301-
$item['local']['mtime'] <= $letime
302-
) {
303-
$dir = self::DIR_PULL;
304-
}
305-
if($item['remote']['mtime'] <= $retime &&
306-
$item['local']['mtime'] > $ltime
307-
) {
308-
$dir = self::DIR_PUSH;
309+
// no sync if hashes match
310+
if($item['remote']['hash'] == $item['local']['hash']) {
311+
unset($this->synclist[$type][$item['id']]);
312+
continue;
309313
}
310-
} else { // never synced
311-
if(!$item['local']['mtime'] && $item['remote']['mtime']) {
312-
$dir = self::DIR_PULL;
313-
}
314-
if($item['local']['mtime'] && !$item['remote']['mtime']) {
315-
$dir = self::DIR_PUSH;
314+
315+
// check direction
316+
$dir = self::DIR_NONE;
317+
if($ltime && $rtime) { // synced before
318+
if($item['remote']['mtime'] > $rtime &&
319+
$item['local']['mtime'] <= $letime
320+
) {
321+
$dir = self::DIR_PULL;
322+
}
323+
if($item['remote']['mtime'] <= $retime &&
324+
$item['local']['mtime'] > $ltime
325+
) {
326+
$dir = self::DIR_PUSH;
327+
}
328+
} else { // never synced
329+
if(!$item['local']['mtime'] && $item['remote']['mtime']) {
330+
$dir = self::DIR_PULL;
331+
}
332+
if($item['local']['mtime'] && !$item['remote']['mtime']) {
333+
$dir = self::DIR_PUSH;
334+
}
316335
}
336+
$this->synclist[$type][$item['id']]['dir'] = $dir;
317337
}
318-
$this->synclist[$type][$item['id']]['dir'] = $dir;
319338
}
320339
}
321340

action.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
use dokuwiki\plugin\sync\ProfileManager;
4+
use dokuwiki\plugin\sync\SyncException;
5+
6+
class action_plugin_sync extends DokuWiki_Action_Plugin {
7+
8+
public function register(Doku_Event_Handler $controller) {
9+
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax');
10+
}
11+
12+
/**
13+
* Dispatch the AJAX calls
14+
*
15+
* @param Doku_Event $e
16+
*/
17+
public function handle_ajax(Doku_Event $e) {
18+
$call = $e->data;
19+
if(substr($call, 0, 5) !== 'sync_') return;
20+
$e->preventDefault();
21+
$e->stopPropagation();
22+
23+
try {
24+
$data = $this->$call();
25+
header('Content-Type: application/json');
26+
echo json_encode($data);
27+
} catch(SyncException $e) {
28+
http_status(500);
29+
header('Content-Type: text/plain');
30+
echo $e->getMessage();
31+
}
32+
}
33+
34+
/**
35+
* Syncs a single file
36+
*
37+
* @return bool
38+
*/
39+
protected function sync_file() {
40+
global $INPUT;
41+
42+
$prmanager = new ProfileManager();
43+
$profno = $INPUT->int('no');
44+
45+
$profile = $prmanager->getProfile($profno);
46+
$profile->syncFile(
47+
$INPUT->int('type'),
48+
$INPUT->filter('cleanID')->str('id'),
49+
$INPUT->int('dir'),
50+
'FIXME'
51+
);
52+
53+
return true;
54+
}
55+
56+
/**
57+
* Initializes the sync by fetching the synclist and the inital times
58+
*
59+
* @return array
60+
*/
61+
protected function sync_init() {
62+
global $INPUT;
63+
$prmanager = new ProfileManager();
64+
$profno = $INPUT->int('no');
65+
66+
$profile = $prmanager->getProfile($profno);
67+
$list = $profile->getSyncList();
68+
$times = $profile->getTimes();
69+
70+
$data = [
71+
'times' => [
72+
'ltime' => $times[0],
73+
'rtime' => $times[1],
74+
],
75+
'list' => $list,
76+
];
77+
78+
return $data;
79+
}
80+
}

0 commit comments

Comments
 (0)