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 .= "
"; $ret .= $e->htmlExplorer('settingstree',':',$folder); $ret .= "
"; $ret .= "
"; $level = $set->getLevel($folder); $ret .= $level->showHtml(); $ret .="
"; $ret .= ""; 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')."
".$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: