-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhelper.php
More file actions
312 lines (285 loc) · 13.7 KB
/
Copy pathhelper.php
File metadata and controls
312 lines (285 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
<?php
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
if (!defined('DOKU_SETTINGS_DIR')) define('DOKU_SETTINGS_DIR',DOKU_INC.'data/settings');
require_once('settings/settingshierarchy.class.php');
class helper_plugin_settingstree extends DokuWiki_Plugin {
private $memcache = false; // memcache false: not initialized, null: not present/usable, object: the helper plugin.
private $explorer_helper = null; // mandatory dependency, error if dependency is broken.
private $explorer_registered = false; // flag to indicate that the callbacks/options are registered to explorertree or not.
private $_settingsHierarchy = array(); // settings hierarchy for a plugin array(pluginname => hierarchy)
function get_explorer(){
if (!$this->explorer_helper){
$this->explorer_helper = plugin_load('helper','explorertree');
if (!$this->explorer_helper){
// what is the dokuwiki way to die with fatal plugin errors?
trigger_error('Explorertree is a dependency but not available!',E_USER_ERROR);
}
}
return $this->explorer_helper;
}
function init_explorertree(){
if (!($e = $this->get_explorer())) return;
if (!$this->explorer_registered){
$e->registerRoute('settingstree',array(
'init_plugin' => array( // this is the method to register routing, hence this method itself is the 'init_plugin' option.
'plugin' => 'settingstree',
'type' => 'helper',
'method' => 'init_explorertree',
),
'vars' => array(
'id' => 'settingstree_expolrertree',
'class' => 'settingstree_explorer',
),
));
$this->explorer_registered = true;
}
return $e;
}
function cache(){
if ($this->memcache === false){
$this->memcache = plugin_load('helper','memcache');
// we don't want to use cache if it does not give performance upgrade
if ($this->memcache && $this->memcache->emulated()){
$this->memcache = null;
}
settingshierarchy::$cache = $this->memcahce;
}
return $this->memcahce;
}
/**
* Constructor gets default preferences
*
* These can be overriden by plugins using this class
*/
function __construct() {
// checks if data/settings directory exists, attempts to create it, or error if it's not possible.
if (!file_exists(DOKU_SETTINGS_DIR)){
if (!mkdir(DOKU_SETTINGS_DIR)){
trigger_error("Cannot create settings directory:'".DOKU_SETTINGS_DIR."'!",E_USER_ERROR);
}
}elseif(!is_dir(DOKU_INC."data/settings")){
trigger_error("The '".DOKU_SETTINGS_DIR."' is not a directory!",E_USER_ERROR);
}
$this->cache();
settingshierarchy::$helper = $this;
}
function getMethods() {
$result = array();
$result[] = array(
'name' => 'checkSettingsVersion',
'desc' => 'Checks if a plugin settings require (re)registering settings, by comparing the version in parameter to the currently stored version.',
'parameters' => array(
'pluginname' => "string plugin's name that needs to be checked e.g. 'dw2pdf'.",
'version' => "integer the version of meta/defaults for settings, that is needed (usually timestamp)",
),
'return' => 'boolean (stored_version < parameter_version).'
);
$result[] = array(
'name' => 'registerSettings',
'desc' => 'Register config settings for a plugin.',
'parameters' => array(
'pluginname' => "string plugin's name that needs to be stored e.g. 'dw2pdf'.",
'version' => "integer the version of meta/defaults for settings that is going to be registered (usually timestamp)",
'meta' => "array the settings' metas. Same structure as in 'conf/metadata.php', i.e. array('settingsname' => array('onoff'),'settingname2'=>array('string','_pattern'=>'/^[1-5]x[1-5]$/'))",
'defaults' => "array the default values. i.e. array('settingsname'=>1,'settingsname2'=>'1x3')",
),
);
$result[] = array(
'name' => 'showAdmin',
'desc' => 'Returns embeddable html that can be used on an admin page (or any page) ->explorertree + cofiguration area + placeholder for hierarchy area.',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'folder' => "string the folder opened by default. You should use ':' (colon) to separate namespaces.",
),
'return' => 'string html (echo-able or sendable via ajax)',
);
$result[] = array(
'name' => 'showHtml',
'desc' => 'Returns embeddable html of the configuration area only.',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'folder' => "string the folder opened by default. You should use ':' (colon) to separate namespaces.",
),
'return' => 'string html (echo-able or sendable via ajax)',
);
$result[] = array(
'name' => 'showExportHtml',
'desc' => 'Returns embeddable html of the configuration area only (export-config version).',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'folder' => "string the folder opened by default. You should use ':' (colon) to separate namespaces.",
'options' => "array the options for exporting (e.g. title of export, onsuccess callback)",
),
'return' => 'string html (echo-able or sendable via ajax)',
);
$result[] = array(
'name' => 'showHierarchy',
'desc' => 'Returns embeddable html of the hierarchy area only.',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'key' => "string the name of the setting e.g. 'pagesize'.",
),
'return' => 'string html (echo-able or sendable via ajax)',
);
$result[] = array(
'name' => 'saveLevel',
'desc' => 'Saves/validates changes and returns the updated embeddable html of the configuration area only.',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'folder' => "string the folder (level) which's values are going to be saved. You should use ':' (colon) to separate namespaces.",
'data' => "array the data to be saved. required structure: array('settingsname'=>array('protect'=>1/0, 'config'=>'newvalue')). Requires only the parameters that are changed!",
'results' => "OUT array the results of save: array('success' => true/false, 'error' => 'true/false', 'msg' => 'Changes are saved/Changes are not saved (by lang)')",
),
'return' => 'string html (echo-able or sendable via ajax)',
);
$result[] = array(
'name' => 'exportLevel',
'desc' => 'Validates changes and returns nothing on success or the updated embeddable html of the configuration area only with all changes/errors on error.',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'folder' => "string the folder (level) which's values are going to be saved. You should use ':' (colon) to separate namespaces.",
'data' => "array the data to be saved. required structure: array('settingsname'=>array('protect'=>1/0, 'config'=>'newvalue')). Requires only the parameters that are changed!",
'results' => "OUT array the results of save: array('success' => true/false, 'error' => 'true/false', 'msg' => 'Changes are saved/Changes are not saved (by lang)')",
'options' => "array the options for exporting (e.g. title of export, onsuccess callback)",
),
'return' => 'mixed null on success, string html (echo-able or sendable via ajax) on error',
);
$result[] = array(
'name' => 'getConf',
'desc' => 'Gets the effective values for the current namespace/page. Only values that are changeable by settingstree are returned (i.e. no ignored settings).',
'parameters' => array(
'pluginname' => "string plugin's name which's settings are displayed e.g. 'dw2pdf'.",
'folder' => "string the folder (level) which's values are returned. You should use ':' (colon) to separate namespaces.",
),
'return' => "array effective values for each key e.g. array('settingsname'=>1, 'settingsname2'=>'1x3')",
);
return $result;
}
function checkSettingsVersion($pluginname,$version){
if ($this->cache() && $cache_ver = $this->cache()->get("plugin_settringstree_settingsversion_{$pluginname}")){
return ((int)$cache_ver) < $version;
}
return @filemtime(DOKU_SETTINGS_DIR."/{$pluginname}.meta.json") < $version;
}
function registerSettings($pluginname,$version,$meta,$defaults){
if (!file_put_contents($file = DOKU_SETTINGS_DIR."/{$pluginname}.meta.json",json_encode($meta))
||
!file_put_contents($file = DOKU_SETTINGS_DIR."/{$pluginname}.defaults.json",json_encode($defaults))
){
trigger_error("Can not store settings for {$pluginname} to {$file}!",E_USER_ERROR);
}
if ($c = $this->cache()){
$TTL = 0; // DECIDE: push this to config?
$c->set("plugin_settringstree_settingsversion_{$pluginname}",$version,$TTL);
$c->set("plugin_settringstree_settingsmeta_{$pluginname}",$meta,$TTL);
$c->set("plugin_settringstree_settingsdefaults_{$pluginname}",$defaults,$TTL);
}
}
private function _loadSettings($pluginname){
if (!$this->_settingsHierarchy[$pluginname]){
$c = $this->cache();
if (!$c || !($meta = $c->get("plugin_settringstree_settingsmeta_{$pluginname}"))){
$meta = json_decode(@file_get_contents($file = DOKU_SETTINGS_DIR."/{$pluginname}.meta.json"),true);
}
if (!is_array($meta)){
trigger_error("Could not load file: {$file}",E_USER_ERROR);
}
if (!$c || !($defaults = $c->get("plugin_settringstree_settingsdefaults_{$pluginname}"))){
$defaults = json_decode(@file_get_contents($file = DOKU_SETTINGS_DIR."/{$pluginname}.defaults.json"),true);
}
if (!is_array($defaults)){
trigger_error("Could not load file: {$file}",E_USER_ERROR);
}
if (!$c || !($values = $c->get("plugin_settringstree_settingsvalues_{$pluginname}"))){
$values = json_decode(@file_get_contents(DOKU_SETTINGS_DIR."/{$pluginname}.json"),true);
}
if (!is_array($values)){ $values = array(); }
$this->_settingsHierarchy[$pluginname] = new settingshierarchy($pluginname,$meta,$defaults,$values);
}
return $this->_settingsHierarchy[$pluginname];
}
private function _storeValues($pluginname,settingshierarchy $set){
$c = $this->cache();
$values = $set->getValueTree();
if ($ret = file_put_contents(DOKU_SETTINGS_DIR."/{$pluginname}.json",json_encode($values)) !== false){
if ($c){ // we don't update cache, if we can't save the values to the filesystem. It would be bad to have correct data until cache is flushed then suddenly something corrupt...
$TTL = 0; // TODO: push this to config?
$c->set("plugin_settringstree_settingsvalues_{$pluginname}",$values,$TTL);
}
}
return $ret;
}
function getConf($pluginname,$folder){
$set = $this->_loadSettings($pluginname);
$level = $set->getLevel($folder);
return $level->getAllValues();
}
function showAdmin($pluginname,$folder){
$set = $this->_loadSettings($pluginname);
$e = $this->init_explorertree();
$ret = "";
$ret .= "<div class='settingstree_left'>";
$ret .= $e->htmlExplorer('settingstree',':',$folder);
$ret .= "<div class='settingstree_left_column'></div></div>";
$ret .= "<div class='settingstree_right'><form id='settingstree_area' class='settingstree_area' method='GET' onsubmit='return false;'>";
$level = $set->getLevel($folder);
$ret .= $level->showHtml();
$ret .="</form></div>";
$ret .= "<script type='text/javascript'> jQuery('#settingstree_area').settingsTree({$this->_treeOpts($pluginname)});</script>";
return $ret;
}
function saveLevel($pluginname,$folder,$data,&$results){
$set = $this->_loadSettings($pluginname);
$level = $set->getLevel($folder);
if ($level->checkValues($data) && $this->_storeValues($pluginname,$set)){ // the values are okay, and it managed to save to file/cache
$results['error'] = false;
$results['msg'] = $this->getLang('changes_saved');
$results['success'] = true;
}else{
$results['error'] = true;
$results['msg'] = $this->getLang('invalid_values')."<br/>".$this->getLang('changes_not_saved');
$results['success'] = false;
}
return $level->showHtml();
}
function exportLevel($pluginname,$folder,$data,&$results,$options){
$set = $this->_loadSettings($pluginname);
$level = $set->getLevel($folder)->getExport($options);
if ($level->checkValues($data)){ // the values are okay, and it managed to save to file/cache
$results['error'] = false;
$results['values'] = $level->getAllValues();
// $results['msg'] = $this->getLang('changes_saved');
$results['success'] = true;
return null;
}else{
$results['error'] = true;
$results['msg'] = $this->getLang('invalid_values');
$results['success'] = false;
return $level->showHtml();
}
}
function showHtml($pluginname,$folder){
$set = $this->_loadSettings($pluginname);
$level = $set->getLevel($folder);
return $level->showHtml();
}
function showExportHtml($pluginname,$folder,array $options = array()){
$set = $this->_loadSettings($pluginname);
$level = $set->getLevel($folder)->getExport($options);
return $level->showHtml();
}
function showHierarchy($pluginname,$key){
$set = $this->_loadSettings($pluginname);
return $set->showHierarchy($key);
}
private function _treeOpts($pluginname){
return json_encode(array(
'token'=> getSecurityToken(),
'pluginname'=> $pluginname,
'explorertree_id' => 'settingstree_expolrertree',
));
}
}
// vim:ts=4:sw=4:et: