PageRenderTime 22ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/framework/Prefs/lib/Horde/Prefs.php

https://github.com/sgtcarneiro/horde
PHP | 445 lines | 205 code | 50 blank | 190 comment | 18 complexity | 9b3c8018f4514e16fcceebd9b29b66ad MD5 | raw file
  1. <?php
  2. /**
  3. * The Horde_Prefs:: class provides a common abstracted interface into the
  4. * various preferences storage mediums. It also includes all of the
  5. * functions for retrieving, storing, and checking preference values.
  6. *
  7. * Copyright 1999-2011 The Horde Project (http://www.horde.org/)
  8. *
  9. * See the enclosed file COPYING for license information (LGPL). If you
  10. * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  11. *
  12. * @author Jon Parise <jon@horde.org>
  13. * @category Horde
  14. * @license http://www.fsf.org/copyleft/lgpl.html LGPL
  15. * @package Prefs
  16. */
  17. class Horde_Prefs implements ArrayAccess
  18. {
  19. /* The default scope name. */
  20. const DEFAULT_SCOPE = 'horde';
  21. /**
  22. * Caching object.
  23. *
  24. * @var Horde_Prefs_Cache
  25. */
  26. protected $_cache;
  27. /**
  28. * General library options.
  29. *
  30. * @var array
  31. */
  32. protected $_opts = array(
  33. 'cache' => null,
  34. 'logger' => null,
  35. 'password' => '',
  36. 'sizecallback' => null,
  37. 'storage' => null,
  38. 'user' => ''
  39. );
  40. /**
  41. * String containing the name of the current scope. This is used
  42. * to differentiate between sets of preferences. By default, preferences
  43. * belong to this scope.
  44. *
  45. * @var string
  46. */
  47. protected $_scope = self::DEFAULT_SCOPE;
  48. /**
  49. * Scope list. Keys are scope names, values are Horde_Prefs_Scope
  50. * objects.
  51. *
  52. * @var array
  53. */
  54. protected $_scopes = array();
  55. /**
  56. * The storage driver(s).
  57. *
  58. * @var array
  59. */
  60. protected $_storage;
  61. /**
  62. * Constructor.
  63. *
  64. * @param string $scope The scope for this set of preferences.
  65. * @param mixed $storage The storage object(s) to use. Either a single
  66. * Horde_Prefs_Storage object, or an array of
  67. * objects.
  68. * @param array $opts Additional confguration options:
  69. * <pre>
  70. * cache - (Horde_Prefs_Cache) The cache driver to use.
  71. * DEFAULT: No caching.
  72. * logger - (Horde_Log_Logger) Logging object.
  73. * DEFAULT: NONE
  74. * password - (string) The password associated with 'user'.
  75. * DEFAULT: NONE
  76. * sizecallback - (callback) If set, called when setting a value in the
  77. * backend.
  78. * DEFAULT: NONE
  79. * user - (string) The name of the user who owns this set of preferences.
  80. * DEFAULT: NONE
  81. * </pre>
  82. */
  83. public function __construct($scope, $storage = null, array $opts = array())
  84. {
  85. $this->_opts = array_merge($this->_opts, $opts);
  86. $this->_cache = isset($this->_opts['cache'])
  87. ? $this->_opts['cache']
  88. : new Horde_Prefs_Cache_Null($this->getUser());
  89. $this->_scope = $scope;
  90. if (is_null($storage)) {
  91. $storage = array(new Horde_Prefs_Storage_Null($this->getUser()));
  92. } elseif (!is_array($storage)) {
  93. $storage = array($storage);
  94. }
  95. $this->_storage = $storage;
  96. register_shutdown_function(array($this, 'store'));
  97. $this->retrieve($scope);
  98. }
  99. /**
  100. * Return the user who owns these preferences.
  101. *
  102. * @return string The user these preferences are for.
  103. */
  104. public function getUser()
  105. {
  106. return $this->_opts['user'];
  107. }
  108. /**
  109. * Get the current scope.
  110. *
  111. * @return string The current scope (application).
  112. */
  113. public function getScope()
  114. {
  115. return $this->_scope;
  116. }
  117. /**
  118. * Returns the storage drivers.
  119. *
  120. * @return array The storage drivers.
  121. */
  122. public function getStorage()
  123. {
  124. return $this->_storage;
  125. }
  126. /**
  127. * Removes a preference entry from the $prefs hash.
  128. *
  129. * @param string $pref The name of the preference to remove. If null,
  130. * removes all prefs.
  131. */
  132. public function remove($pref = null)
  133. {
  134. if (is_null($pref)) {
  135. foreach ($this->_scopes as $val) {
  136. foreach (array_keys(iterator_to_array($val)) as $prefname) {
  137. $val->remove($prefname);
  138. }
  139. }
  140. } elseif ($scope = $this->_getScope($pref)) {
  141. $this->_scopes[$scope]->remove($pref);
  142. }
  143. }
  144. /**
  145. * Sets the given preference to the specified value if the preference is
  146. * modifiable.
  147. *
  148. * @param string $pref The preference name to modify.
  149. * @param string $val The preference value (UTF-8).
  150. * @param array $opts Additional options:
  151. * <pre>
  152. * nosave - (boolean) If true, the preference will not be saved to the
  153. * storage backend(s).
  154. * </pre>
  155. *
  156. * @return boolean True if the value was successfully set, false on a
  157. * failure.
  158. * @throws Horde_Prefs_Exception
  159. */
  160. public function setValue($pref, $val, array $opts = array())
  161. {
  162. /* Exit early if preference doesn't exist or is locked. */
  163. if (!($scope = $this->_getScope($pref)) ||
  164. $this->_scopes[$scope]->isLocked($pref)) {
  165. return false;
  166. }
  167. // Check to see if the value exceeds the allowable storage limit.
  168. if ($this->_opts['sizecallback'] &&
  169. call_user_func($this->_opts['sizecallback'], $pref, strlen($val))) {
  170. return false;
  171. }
  172. $this->_scopes[$scope]->set($pref, $val);
  173. if (!empty($opts['nosave'])) {
  174. $this->_scopes[$scope]->setDirty($pref, false);
  175. }
  176. foreach ($this->_storage as $storage) {
  177. $storage->onChange($scope, $pref);
  178. }
  179. if ($this->_opts['logger']) {
  180. $this->_opts['logger']->log(__CLASS__ . ': Storing preference value (' . $pref . ')', 'DEBUG');
  181. }
  182. return true;
  183. }
  184. /**
  185. * Shortcut to setValue().
  186. */
  187. public function __set($name, $value)
  188. {
  189. return $this->setValue($name, $value);
  190. }
  191. /**
  192. * Returns the value of the requested preference.
  193. *
  194. * @param string $pref The preference name.
  195. *
  196. * @return string The value of the preference (UTF-8), null if it doesn't
  197. * exist.
  198. */
  199. public function getValue($pref)
  200. {
  201. return ($scope = $this->_getScope($pref))
  202. ? $this->_scopes[$scope]->get($pref)
  203. : null;
  204. }
  205. /**
  206. * Shortcut to getValue().
  207. */
  208. public function __get($name)
  209. {
  210. return $this->getValue($name);
  211. }
  212. /**
  213. * Mark a preference as locked.
  214. *
  215. * @param string $pref The preference name.
  216. * @param boolean $locked Is the preference locked?
  217. */
  218. public function setLocked($pref, $bool)
  219. {
  220. if ($scope = $this->_getScope($pref)) {
  221. $this->_scopes[$scope]->setLocked($pref, $bool);
  222. }
  223. }
  224. /**
  225. * Is a preference locked?
  226. *
  227. * @param string $pref The preference name.
  228. *
  229. * @return boolean Whether the preference is locked.
  230. */
  231. public function isLocked($pref)
  232. {
  233. return ($scope = $this->_getScope($pref))
  234. ? $this->_scopes[$scope]->isLocked($pref)
  235. : false;
  236. }
  237. /**
  238. * Is a preference marked dirty?
  239. *
  240. * @param string $pref The preference name.
  241. *
  242. * @return boolean True if the preference is marked dirty.
  243. */
  244. public function isDirty($pref)
  245. {
  246. return ($scope = $this->_getScope($pref))
  247. ? $this->_scopes[$scope]->isDirty($pref)
  248. : false;
  249. }
  250. /**
  251. * Returns the default value of the given preference.
  252. *
  253. * @param string $pref The name of the preference to get the default for.
  254. *
  255. * @return string The preference's default value.
  256. */
  257. public function getDefault($pref)
  258. {
  259. return ($scope = $this->_getScope($pref))
  260. ? $this->_scopes[$scope]->getDefault($pref)
  261. : null;
  262. }
  263. /**
  264. * Determines if the current preference value is the default value.
  265. *
  266. * @param string $pref The name of the preference to check.
  267. *
  268. * @return boolean True if the preference is the application default
  269. * value.
  270. */
  271. public function isDefault($pref)
  272. {
  273. return ($scope = $this->_getScope($pref))
  274. ? $this->_scopes[$scope]->isDefault($pref)
  275. : false;
  276. }
  277. /**
  278. * Returns the scope of a preference.
  279. *
  280. * @param string $pref The preference name.
  281. *
  282. * @return mixed The scope of the preference, or null if it doesn't
  283. * exist.
  284. */
  285. protected function _getScope($pref)
  286. {
  287. if ($this->_scopes[$this->_scope]->exists($pref)) {
  288. return $this->_scope;
  289. } elseif (($this->_scope != self::DEFAULT_SCOPE) &&
  290. ($this->_scopes[self::DEFAULT_SCOPE]->exists($pref))) {
  291. return self::DEFAULT_SCOPE;
  292. }
  293. return null;
  294. }
  295. /**
  296. * Retrieves preferences for the current scope.
  297. *
  298. * @param string $scope Optional scope specifier - if not present the
  299. * current scope will be used.
  300. */
  301. public function retrieve($scope = null)
  302. {
  303. if (is_null($scope)) {
  304. $scope = $this->getScope();
  305. } else {
  306. $this->_scope = $scope;
  307. }
  308. $this->_loadScope(self::DEFAULT_SCOPE);
  309. if ($scope != self::DEFAULT_SCOPE) {
  310. $this->_loadScope($scope);
  311. }
  312. }
  313. /**
  314. * Load a specific preference scope.
  315. *
  316. * @param string $scope The scope to load.
  317. */
  318. protected function _loadScope($scope)
  319. {
  320. // Return if we've already loaded these prefs.
  321. if (!empty($this->_scopes[$scope])) {
  322. return;
  323. }
  324. // Now check the prefs cache for existing values.
  325. try {
  326. if (($cached = $this->_cache->get($scope)) !== false) {
  327. $this->_scopes[$scope] = $cached;
  328. return;
  329. }
  330. } catch (Horde_Prefs_Exception $e) {}
  331. $scope_ob = new Horde_Prefs_Scope($scope);
  332. $scope_ob->init = true;
  333. // Need to set object in scopes array now, since the storage object
  334. // might recursively call the prefs object.
  335. $this->_scopes[$scope] = $scope_ob;
  336. foreach ($this->_storage as $storage) {
  337. $scope_ob = $storage->get($scope_ob);
  338. }
  339. $scope_ob->init = false;
  340. $this->_cache->store($scope_ob);
  341. }
  342. /**
  343. * This function will be run at the end of every request as a shutdown
  344. * function (registered by the constructor). All dirty prefs will be
  345. * saved to the storage backend.
  346. */
  347. public function store()
  348. {
  349. foreach ($this->_scopes as $scope) {
  350. if ($scope->isDirty()) {
  351. foreach ($this->_storage as $storage) {
  352. $storage->store($scope);
  353. }
  354. $this->_cache->store($scope);
  355. }
  356. }
  357. }
  358. /**
  359. * Cleanup (e.g. remove) scope(s).
  360. *
  361. * @param boolean $all Cleanup all scopes. If false, clean present scope
  362. * only.
  363. */
  364. public function cleanup($all = false)
  365. {
  366. if ($all) {
  367. /* Destroy all scopes. */
  368. $this->_scopes = array();
  369. $scope = null;
  370. } else {
  371. unset($this->_scopes[$this->_scope]);
  372. $scope = $this->_scope;
  373. }
  374. try {
  375. $this->_cache->remove($scope);
  376. } catch (Horde_Prefs_Exception $e) {}
  377. }
  378. /* ArrayAccess methods. */
  379. public function offsetExists($offset)
  380. {
  381. return !is_null($this->getValue($offset));
  382. }
  383. public function offsetGet($offset)
  384. {
  385. return $this->getValue($offset);
  386. }
  387. public function offsetSet($offset, $value)
  388. {
  389. $this->setValue($offset, $value);
  390. }
  391. public function offsetUnset($offset)
  392. {
  393. $this->remove($offset);
  394. }
  395. }