1<?php 2 3 4if (!class_exists('settingslevel',false)){ 5require_once('settingswrapper.class.php'); 6 7 8class settingslevel{ 9 public $path = null; // absolute path 10 protected $_parent = null; // the parent or null if it's the root 11 protected $_hierarchy = null; // the settingshierarchy containing this level. 12 private $_children = array(); // children levels 13 private $_settings = null; // the array of settingswrapper (by key) to this level has. 14 private $_values = null; // values (array: key=>[prot,value]) for the level. 15 16 function __construct(settingshierarchy $hierarchy, settingslevel $parent = null, $path){ 17 $this->_parent = $parent; 18 $this->_hierarchy = $hierarchy; 19 $this->path = ':'.ltrim($path,':'); 20 } 21 22 function getLevelNameRelative(){ 23 if ($this->path == ':'){ 24 global $lang; 25 return '['.$lang['mediaroot'].']'; 26 } 27 if (!$this->_parent){ 28 return $this->path; 29 } 30 $val = substr($this->path,strlen($this->_parent->path)); 31 if ($val[0] == ':') $val = substr($val,1); 32 return $val; 33 } 34 function getHierarchy(){ 35 return $this->_hierarchy; 36 } 37 function getCurrent($key){ 38 /* 1, if there is protected value then that (here) 39 2, if there is value for level then that (in getCurrentNoProt) 40 3, parent's current value (in getCurrentNoProt) */ 41 if (($v = $this->getProtected($key)) !== null) {return $v;} 42 return $this->getCurrentNoProt($key); 43 44 } 45 private function getCurrentNoProt($key){ 46 // getCurrentNoProt: getProtected() may return getCurrent() value, but getCurrent() value checks getProtected()... we need a getCurrent() without calling getProtected() 47 /* 1, if there is protected value then that (in getCurrent) 48 2, if there is value for level then that (here) 49 3, parent's current value (here) */ 50 if (($v = @$this->_values[$key]['value']) !== null){ return $v; } 51 if ($this->_parent) { return $this->_parent->getCurrent($key); } 52 /* root's current: 53 1, if there is protected, then that (done) 54 2, if root has value then that (done) 55 3, if config's local then that 56 4, config's default 57 */ 58 if (($v = $this->_hierarchy->getLocal($key)) !== null) {return $v;} 59 return $this->_hierarchy->getDefault($key); 60 } 61 62 function getDefault($key){ 63 /* 1, if there is a protected value then that 64 2, parents's current value */ 65 if (($v = $this->getProtected($key)) !== null) {return $v;} 66 if ($this->_parent){ return $this->_parent->getCurrent($key); } 67 /* root's default: 68 1, if config's protected then that (done) 69 2, if config's local then that 70 3, config's default */ 71 if (($v = $this->_hierarchy->getLocal($key)) !== null) {return $v;} 72 return $this->_hierarchy->getDefault($key); 73 } 74 75 76 function getLocal($key){ 77 /* 1, if there is a protected value then null 78 2, if the level has value then that 79 3, null */ 80 if (($v = $this->getProtected($key)) !== null) {return null;} 81 if (($v = @$this->_values[$key]['value']) !== null){ return $v; } 82 return null; 83 } 84 85 function getProtected($key){ 86 /* 1, if there is a protected value from parent then that 87 2, if there is a protection on this level then the current value 88 3, null */ 89 if (($v = $this->getParentProtected($key)) !== null) {return $v;} 90 if (@$this->_values[$key]['protect']){ return $this->getCurrentNoProt($key); } 91 return null; 92 } 93 function getParentProtected($key){ 94 if ($this->_parent){ // check parent level. 95 return $this->_parent->getProtected($key); 96 } 97 return $this->_hierarchy->getProtected($key); 98 } 99 100 101 function isLevelValue($key){ 102 return isset($this->_values[$key]['value']); 103 } 104 function getLevelValue($key){ 105 return @$this->_values[$key]['value']; 106 } 107 function isLevelValueIgnored($key){ 108 return (isset($this->_values[$key]['value']) && ($this->getParentProtected($key) !== null)); 109 } 110 function isLevelProtected($key){ 111 return isset($this->_values[$key]['protect']); 112 } 113 114 function setValues(array $values){ // setValues should always be called before getSettings. If not, just ignore. 115 if ($this->_settings === null) 116 $this->_values = $values; 117 } 118 function getValues(){ 119 return $this->_values; 120 } 121 122 function getValuesRecursive(){ 123 $ret = array(); 124 $v = $this->getValues(); 125 if (!empty($v)){ 126 $ret[$this->path] = $v; 127 } 128 foreach($this->_children as $child){ 129 $ret = array_merge($ret,$child->getValuesRecursive()); 130 } 131 return $ret; 132 } 133 function getAllValues(){ 134 $ret = array(); 135 foreach ($this->_hierarchy->getFieldConfig() as $key=>$meta){ 136 $ret[$key] = $this->getCurrent($key); 137 } 138 return $ret; 139 } 140 141 142 function getParent(){ 143 return $this->_parent; 144 } 145 146 protected function _getSettings(){ 147 if (!$this->_settings){ 148 foreach ($this->_hierarchy->getFieldConfig() as $key=>$meta){ 149 $this->_settings[$key] = new settingswrapper($key,$this,$meta,$this->_values[$key]); 150 } 151 } 152 return $this->_settings; 153 } 154 function checkValues($data){ 155 $set = $this->_getSettings(); 156 $check_success = true; 157 foreach ($data as $key=>$new){ 158 if (isset($new['config'])){ 159 if (!$set[$key]->tryUpdate($new['config'])){ // returns false on error 160 $check_success = false; 161 }else{ 162 $par_val = $this->getDefault($key); 163 if ($set[$key]->_value !== null && $par_val !== $set[$key]->_value){ 164 $this->_values[$key]['value'] = $set[$key]->_value; // we do need to save value, as it's not default. (default == parent's value) 165 }else{ 166 unset($this->_values[$key]['value']); // we do need to delete the value, as it's default. 167 } 168 } 169 } 170 if (isset($new['protect'])){ 171 if ($new['protect'] === 'false') $new['protect'] = false; 172 if ($new['protect'] === 'true') $new['protect'] = true; 173 $par_val = $this->getParentProtected($key); 174 $toset = $par_val ? null : $new['protect']; 175 $set[$key]->setProtect($toset); 176 if ($toset) $this->_values[$key]['protect'] = true; // we only save if a level is protected. 177 else unset($this->_values[$key]['protect']); 178 } 179 if (empty($this->_values[$key])) 180 unset($this->_values[$key]); 181 } 182 if (!$check_success){ 183 $this->_markChanged(array_keys($data)); 184 } 185 return $check_success; 186 } 187 protected function _markChanged($keys){ 188 $set = $this->_getSettings(); 189 foreach ($keys as $key){ 190 $set[$key]->markChanged($key); 191 } 192 } 193 194 protected function _getTitle(){ 195 return sprintf(settingshierarchy::$helper->getLang('settings_for_%s'),$this->path); 196 } 197 protected function _getButtons(){ 198 return 199 "<button id='settingstree_save_button' onclick=\"jQuery(this).trigger('settingstree_save'); return false;\">".settingshierarchy::$helper->getLang('save')."</button> 200 <button id='settingstree_cancel_button' onclick=\"jQuery(this).trigger('settingstree_cancel'); return false;\">".settingshierarchy::$helper->getLang('cancel')."</button>"; 201 202 } 203 204 function showHtml(){ 205 206 // DECIDE: non-ajax compatibility: plain posts and js states in hidden fields? 207// $ret .= "<input type='hidden' name='settingstree_path' value='{$this->path}' /><input type='hidden' name='settingstree_pluginname' value='{$this->_hierarchy->getPluginName()}' />"; 208 $ret .= "<div class='settingstree_error_area'></div>"; 209 $ret .= "<div id='config__manager' data-path='{$this->path}'><fieldset><legend>{$this->_getTitle()}</legend><div class='table'><table class='inline'><tbody>"; 210 foreach ($this->_getSettings() as $key => $setting){ 211 $ret .= $setting->showHtml(); 212 } 213 $ret .= "</tbody></table></div></fieldset></div>"; 214 $ret .= "<div class='settingstree_error_area'></div>"; 215 $ret .= "<div class='settingstree_buttons'>{$this->_getButtons()}</div>"; 216 return $ret; 217 } 218 function getExport($options){ 219 $level = new settingslevel_export($this->_hierarchy,$this,$this->path); 220 $level->setOptions($options); 221 return $level; 222 } 223 224 function getPath(){ 225 return $this->path; 226 } 227 function isRoot(){ 228 return !$this->_parent; 229 } 230 231 function getLevel(array $path){ 232 if (empty($path)){ 233 return $this; 234 } 235 $child = array_shift($path); 236 if ($child == ''){ 237 global $conf; 238 $child = $conf['start']; 239 } 240 if (!($c = @$this->_children[$child])){ 241 $this->_children[$child] = new static($this->_hierarchy,$this,$this->path.':'.$child); 242 $c = $this->_children[$child]; 243 } 244 return $c->getLevel($path); 245 } 246 247 function addLevel($path,$values){ 248 if (!is_array($path)){ 249 $path = explode(':',ltrim($path,':')); // explode path if not already exploded. 250 } 251 if (empty($path)){ 252 $this->setValues($values); 253 return; 254 } 255 $child = array_shift($path); 256 if ($child == '') { 257 global $conf; 258 $child = $conf['start']; 259 } 260 if (!($c = @$this->_children[$child])){ 261 $this->_children[$child] = new static($this->_hierarchy,$this,$this->path.':'.$child); 262 $c = $this->_children[$child]; 263 } 264 $c->addLevel($path,$values); 265 } 266 267 function getChildren(){ 268 return $this->_children; 269 } 270} 271 272class settingslevel_export extends settingslevel{ 273 private $_title = null; 274 function setOptions($options){ 275 $this->_title = @$options['title']; 276 } 277 278 protected function _getTitle(){ 279 return $this->_title !== null ? $this->_title : settingshierarchy::$helper->getLang('export_options');; 280 } 281 protected function _getButtons(){ 282 return 283 "<button id='settingstree_export_button' onclick=\"jQuery(this).trigger('settingstree_export'); return false;\">".settingshierarchy::$helper->getLang('export')."</button> 284 <button id='settingstree_close_button' onclick=\"jQuery(this).trigger('settingstree_close'); return false;\">".settingshierarchy::$helper->getLang('cancel')."</button>"; 285 } 286 function getAllValues(){ 287 $ret = array(); 288 foreach ($this->_hierarchy->getFieldConfig() as $key=>$meta){ 289 if ($meta['_ignore_for_export']) continue; 290 $ret[$key] = $this->getCurrent($key); 291 } 292 return $ret; 293 } 294 295 296 protected function _getSettings(){ 297 if (!$this->_settings){ 298 foreach ($this->_hierarchy->getFieldConfig() as $key=>$meta){ 299 if ($meta['_ignore_for_export']) continue; 300 $this->_settings[$key] = new settingswrapper_export($key,$this,$meta,$this->_values[$key]); 301 } 302 } 303 return $this->_settings; 304 } 305 306} 307 308} // class_exists