| [ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 3 /** 4 * Preference is administratively locked. 5 */ 6 define('_PREF_LOCKED', 1); 7 8 /** 9 * Preference is shared amongst applications. 10 */ 11 define('_PREF_SHARED', 2); 12 13 /** 14 * Preference value has been changed. 15 */ 16 define('_PREF_DIRTY', 4); 17 18 /** 19 * Preference value is the application default. 20 */ 21 define('_PREF_DEFAULT', 8); 22 23 /** 24 * The Prefs:: class provides a common abstracted interface into the 25 * various preferences storage mediums. It also includes all of the 26 * functions for retrieving, storing, and checking preference values. 27 * 28 * TODO: document the format of the $_prefs hash here 29 * 30 * $_prefs[*pref name*] = array( 31 * 'value' => *Default value*, 32 * 'locked' => *boolean*, 33 * 'shared' => *boolean*, 34 * 'type' => 'checkbox' 35 * 'text' 36 * 'password' 37 * 'textarea' 38 * 'select' 39 * 'number' 40 * 'implicit' 41 * 'special' 42 * 'link' - There must be a field named either 'url' 43 * (internal application link) or 'xurl' 44 * (external application link) if this type is used. 45 * 'enum' 46 * 'enum' => TODO, 47 * 'desc' => _(*Description string*), 48 * 'help' => *Name of the entry in the XML help file* 49 * ); 50 * 51 * $Horde: framework/Prefs/Prefs.php,v 1.137.10.27 2006/07/03 17:38:11 chuck Exp $ 52 * 53 * Copyright 1999-2006 Jon Parise <jon@horde.org> 54 * 55 * See the enclosed file COPYING for license information (LGPL). If you 56 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 57 * 58 * @author Jon Parise <jon@horde.org> 59 * @since Horde 1.3 60 * @package Horde_Prefs 61 */ 62 class Prefs { 63 64 /** 65 * Hash holding all of the user's preferences. Each preference is 66 * itself a hash, so this will ultimately be multi-dimensional. 67 * 68 * [*pref name*] => Array( 69 * [d] => *default value* 70 * [m] => *pref mask* 71 * [v] => *pref value* 72 * ) 73 * 74 * @access private 75 * 76 * @var array 77 */ 78 var $_prefs = array(); 79 80 /** 81 * String containing the name of this scope. This is used to 82 * maintain the application scope between sets of preferences. By 83 * default, all preferences belong to the "global" (Horde) scope. 84 * 85 * @var string 86 */ 87 var $_scope = 'horde'; 88 89 /** 90 * String containing the current username. This indicates the owner of the 91 * preferences. 92 * 93 * @var string 94 */ 95 var $_user = ''; 96 97 /** 98 * Boolean indicating whether preference caching should be used. 99 * 100 * @var boolean 101 */ 102 var $_caching = false; 103 104 /** 105 * Hash holding preferences with hook functions defined. 106 * 107 * @var array 108 */ 109 var $_hooks = array(); 110 111 /** 112 * Have we run hook functions yet? 113 * 114 * @var boolean 115 */ 116 var $_hooksCalled = null; 117 118 /** 119 * Default constructor (must be called from each extending class in their 120 * constructors via parent::Prefs()). 121 */ 122 function Prefs() 123 { 124 $this->_shutdown(); 125 } 126 127 /** 128 * Returns the charset used by the concrete preference backend. 129 * 130 * @return string The preference backend's charset. 131 */ 132 function getCharset() 133 { 134 return NLS::getCharset(); 135 } 136 137 /** 138 * Updates the session-based preferences cache (if available). 139 * 140 * @param string $pref The preference to update. If empty, will update 141 * the entire cache with the current set of prefs. 142 */ 143 function cacheUpdate($pref = null) 144 { 145 /* Return immediately if caching is disabled. */ 146 if (!$this->_caching) { 147 return; 148 } 149 150 if (isset($_SESSION['prefs_cache'])) { 151 if (is_null($pref)) { 152 $prefs = $this->_prefs; 153 } else { 154 $prefs = array($pref => $this->_prefs[$pref]); 155 } 156 157 /* Place each preference in the cache according to its 158 * scope. */ 159 foreach ($prefs as $name => $pref) { 160 $_SESSION['prefs_cache'][$this->getScope($name)][$name] = $pref; 161 } 162 } 163 } 164 165 /** 166 * Tries to find the requested preferences in the cache. If they exist, 167 * update the $prefs hash with the cached values. 168 * 169 * @return boolean True on success, false on failure. 170 */ 171 function cacheLookup() 172 { 173 /* Return immediately if caching is disabled. */ 174 if (!$this->_caching) { 175 return false; 176 } 177 178 if (isset($_SESSION['prefs_cache']['horde']) && 179 isset($_SESSION['prefs_cache'][$this->_scope])) { 180 181 /* Restore global preferences. */ 182 $this->_prefs = array_merge($this->_prefs, $_SESSION['prefs_cache']['horde'], $_SESSION['prefs_cache'][$this->_scope]); 183 184 return true; 185 } 186 187 return false; 188 } 189 190 /** 191 * Adds a new preference entry to the $prefs hash. 192 * 193 * @param string $pref The name of the preference to add. 194 * @param string $val The initial value of the preference. 195 * @param integer $mask The initial bitmask of the preference. 196 */ 197 function add($pref, $val = '', $mask = 0) 198 { 199 if (is_array($this->_prefs)) { 200 $this->_prefs[$pref] = array('v' => $val, 'm' => $mask, 'd' => $val); 201 } 202 } 203 204 /** 205 * Removes a preference entry from the $prefs hash. 206 * 207 * @param string $pref The name of the preference to remove. 208 */ 209 function remove($pref) 210 { 211 if (is_array($this->_prefs)) { 212 $scope = $this->getScope($pref); 213 unset($this->_prefs[$pref]); 214 unset($_SESSION['prefs_cache'][$scope][$pref]); 215 } 216 } 217 218 /** 219 * Sets the given preferences ($pref) to the specified value 220 * ($val), if the preference is modifiable. 221 * 222 * @param string $pref The name of the preference to modify. 223 * @param string $val The new value for this preference. 224 * @param boolean $convert If true the preference value gets converted 225 * from the current charset to the backend's 226 * charset. 227 * 228 * @return boolean True if the value was successfully set, false on a 229 * failure. 230 */ 231 function setValue($pref, $val, $convert = true) 232 { 233 /* Exit early if this preference is locked or doesn't exist. */ 234 if (!isset($this->_prefs[$pref]) || $this->isLocked($pref)) { 235 return false; 236 } 237 238 return $this->_setValue($pref, $val, true, $convert); 239 } 240 241 function __set($name, $value) 242 { 243 return $this->setValue($name, $value); 244 } 245 246 /** 247 * Sets the given preferences ($pref) to the specified value 248 * ($val), whether or not the preference is user-modifiable, unset 249 * the default bit, and set the dirty bit. 250 * 251 * @access protected 252 * 253 * @param string $pref The name of the preference to modify. 254 * @param string $val The new value for this preference. 255 * @param boolean $dirty True if we should mark the new value as 256 * dirty (changed). 257 * @param boolean $convert If true the preference value gets converted 258 * from the current charset to the backend's 259 * charset. 260 * 261 * @return boolean True if the value was successfully set, false on a 262 * failure. 263 */ 264 function _setValue($pref, $val, $dirty = true, $convert = true) 265 { 266 global $conf; 267 268 if ($convert) { 269 $val = $this->convertToDriver($val, NLS::getCharset()); 270 } 271 272 /* If the preference's value is already equal to $val, don't 273 * bother changing it. Changing it would set the "dirty" bit, 274 * causing an unnecessary update later on in the storage 275 * routine. */ 276 if (isset($this->_prefs[$pref]) && 277 (($this->_prefs[$pref]['v'] == $val) && 278 !$this->isDefault($pref))) { 279 return true; 280 } 281 282 /* Check to see if the value exceeds the allowable storage 283 * limit. */ 284 if (isset($conf['prefs']['maxsize'])) { 285 if (strlen($val) > $conf['prefs']['maxsize']) { 286 global $notification; 287 if (isset($notification)) { 288 $notification->push(sprintf(_("The preference \"%s\" could not be saved because its data exceeded the maximum allowable size"), $pref), 'horde.error'); 289 return false; 290 } 291 } 292 } 293 294 /* Assign the new value, unset the "default" bit, and set the 295 "dirty" bit. */ 296 if (empty($this->_prefs[$pref]['m'])) { 297 $this->_prefs[$pref]['m'] = 0; 298 } 299 $this->_prefs[$pref]['v'] = $val; 300 $this->setDefault($pref, false); 301 if ($dirty) { 302 $this->setDirty($pref, true); 303 } 304 305 $this->cacheUpdate($pref); 306 307 return true; 308 } 309 310 /** 311 * Returns the value of the requested preference. 312 * 313 * @param string $pref The name of the preference to retrieve. 314 * @param boolean $convert If true the preference value gets converted 315 * from the backend's charset to the current 316 * charset. 317 * 318 * @return string The value of the preference, null if it doesn't exist. 319 */ 320 function getValue($pref, $convert = true) 321 { 322 static $charset; 323 if (!isset($charset)) { 324 $charset = NLS::getCharset(); 325 } 326 327 return (isset($this->_prefs[$pref]['v'])) ? 328 ($convert ? 329 $this->convertFromDriver($this->_prefs[$pref]['v'], $charset) : 330 $this->_prefs[$pref]['v']) : 331 null; 332 } 333 334 function __get($name) 335 { 336 return $this->getValue($name); 337 } 338 339 /** 340 * Modifies the "locked" bit for the given preference. 341 * 342 * @param string $pref The name of the preference to modify. 343 * @param boolean $bool The new boolean value for the "locked" bit. 344 */ 345 function setLocked($pref, $bool) 346 { 347 $this->_setMask($pref, $bool, _PREF_LOCKED); 348 } 349 350 /** 351 * Returns the state of the "locked" bit for the given preference. 352 * 353 * @param string $pref The name of the preference to check. 354 * 355 * @return boolean The boolean state of $pref's "locked" bit. 356 */ 357 function isLocked($pref) 358 { 359 return $this->_getMask($pref, _PREF_LOCKED); 360 } 361 362 /** 363 * Modifies the "shared" bit for the given preference. 364 * 365 * @param string $pref The name of the preference to modify. 366 * @param boolean $bool The new boolean value for the "shared" bit. 367 */ 368 function setShared($pref, $bool) 369 { 370 $this->_setMask($pref, $bool, _PREF_SHARED); 371 } 372 373 /** 374 * Returns the state of the "shared" bit for the given preference. 375 * 376 * @param string $pref The name of the preference to check. 377 * 378 * @return boolean The boolean state of $pref's "shared" bit. 379 */ 380 function isShared($pref) 381 { 382 return $this->_getMask($pref, _PREF_SHARED); 383 } 384 385 /** 386 * Modifies the "dirty" bit for the given preference. 387 * 388 * @param string $pref The name of the preference to modify. 389 * @param boolean $bool The new boolean value for the "dirty" bit. 390 */ 391 function setDirty($pref, $bool) 392 { 393 $this->_setMask($pref, $bool, _PREF_DIRTY); 394 } 395 396 /** 397 * Returns the state of the "dirty" bit for the given preference. 398 * 399 * @param string $pref The name of the preference to check. 400 * 401 * @return boolean The boolean state of $pref's "dirty" bit. 402 */ 403 function isDirty($pref) 404 { 405 return $this->_getMask($pref, _PREF_DIRTY); 406 } 407 408 /** 409 * Modifies the "default" bit for the given preference. 410 * 411 * @param string $pref The name of the preference to modify. 412 * @param boolean $bool The new boolean value for the "default" bit. 413 */ 414 function setDefault($pref, $bool) 415 { 416 $this->_setMask($pref, $bool, _PREF_DEFAULT); 417 } 418 419 /** 420 * Returns the default value of the given preference. 421 * 422 * @param string $pref The name of the preference to get the default for. 423 * 424 * @return string The preference's default value. 425 */ 426 function getDefault($pref) 427 { 428 return !empty($this->_prefs[$pref]['d']) ? 429 $this->_prefs[$pref]['d'] : 430 ''; 431 } 432 433 /** 434 * Determines if the current preference value is the default 435 * value from prefs.php or a user defined value 436 * 437 * @param string $pref The name of the preference to check. 438 * 439 * @return boolean True if the preference is the application default 440 * value. 441 */ 442 function isDefault($pref) 443 { 444 return $this->_getMask($pref, _PREF_DEFAULT); 445 } 446 447 /** 448 * Sets the value for a given mask. 449 * 450 * @access private 451 * 452 * @param string $pref The name of the preference to modify. 453 * @param boolean $bool The new boolean value for the "default" bit. 454 * @param integer $mask The mask to add. 455 */ 456 function _setMask($pref, $bool, $mask) 457 { 458 if (isset($this->_prefs[$pref])) { 459 if ($bool != $this->_getMask($pref, $mask)) { 460 if ($bool) { 461 $this->_prefs[$pref]['m'] |= $mask; 462 } else { 463 $this->_prefs[$pref]['m'] &= ~$mask; 464 } 465 } 466 } 467 } 468 469 /** 470 * Gets the boolean state for a given mask. 471 * 472 * @access private 473 * 474 * @param string $pref The name of the preference to modify. 475 * @param integer $mask The mask to get. 476 * 477 * @return boolean The boolean state for the given mask. 478 */ 479 function _getMask($pref, $mask) 480 { 481 return isset($this->_prefs[$pref]['m']) ? ($this->_prefs[$pref]['m'] & $mask) : false; 482 } 483 484 /** 485 * Determines whether the current preference is empty. 486 * 487 * @param string $pref The name of the preference to check. 488 * 489 * @return boolean True if the preference is empty. 490 */ 491 function isEmpty($pref) 492 { 493 return empty($this->_prefs[$pref]['v']); 494 } 495 496 /** 497 * Returns the scope of the given preference. 498 * 499 * @param string $pref The name of the preference to examine. 500 * 501 * @return string The scope of the $pref. 502 */ 503 function getScope($pref) 504 { 505 if ($this->isShared($pref)) { 506 return 'horde'; 507 } else { 508 return $this->_scope; 509 } 510 } 511 512 /** 513 * Return a list of "dirty" preferences. 514 * 515 * @access private 516 * 517 * @return array The list of "dirty" preferences in $this->_prefs. 518 */ 519 function _dirtyPrefs() 520 { 521 $dirty_prefs = array(); 522 523 foreach (array_keys($this->_prefs) as $pref) { 524 if ($this->isDirty($pref)) { 525 $dirty_prefs[] = $pref; 526 } 527 } 528 529 return $dirty_prefs; 530 } 531 532 /** 533 * Retrieves the default preferences. 534 */ 535 function retrieve() 536 { 537 /* Load defaults to make sure we have all preferences. */ 538 $this->_setDefaults('horde'); 539 $this->_setDefaults($this->_scope); 540 541 return true; 542 } 543 544 /** 545 * This function will be run at the end of every request as a shutdown 546 * function (registered by the Prefs:: constructor). All prefs with the 547 * dirty bit set will be saved to the storage backend at this time; thus, 548 * there is no need to manually call $prefs->store() every time a 549 * preference is changed. 550 * 551 * @abstract 552 */ 553 function store() 554 { 555 return true; 556 } 557 558 /** 559 * This function provides common cleanup functions for all of the driver 560 * implementations. 561 * 562 * @param boolean $all Clean up all Horde preferences. 563 */ 564 function cleanup($all = false) 565 { 566 /* Remove this scope from the preferences cache, if it 567 exists. */ 568 if (isset($_SESSION['prefs_cache'][$this->_scope])) { 569 unset($_SESSION['prefs_cache'][$this->_scope]); 570 } 571 572 /* Perform a Horde-wide cleanup? */ 573 if ($all) { 574 /* Destroy the contents of the preferences hash. */ 575 $this->_prefs = array(); 576 577 /* Destroy the contents of the preferences cache. */ 578 if (isset($_SESSION['prefs_cache'])) { 579 unset($_SESSION['prefs_cache']); 580 } 581 } 582 } 583 584 /** 585 * Clears all preferences from the backend. 586 */ 587 function clear() 588 { 589 $this->cleanup(true); 590 } 591 592 /** 593 * Converts a value from the driver's charset to the specified charset. 594 * 595 * @param mixed $value A value to convert. 596 * @param string $charset The charset to convert to. 597 * 598 * @return mixed The converted value. 599 */ 600 function convertFromDriver($value, $charset) 601 { 602 return $value; 603 } 604 605 /** 606 * Converts a value from the specified charset to the driver's charset. 607 * 608 * @param mixed $value A value to convert. 609 * @param string $charset The charset to convert from. 610 * 611 * @return mixed The converted value. 612 */ 613 function convertToDriver($value, $charset) 614 { 615 return $value; 616 } 617 618 /** 619 * Populates the $prefs hash with new entries and externally defined 620 * default values. 621 * 622 * @param string $app The application to load defaults for. 623 */ 624 function _setDefaults($app) 625 { 626 global $registry; 627 $filename = $registry->get('fileroot', $app) . '/config/prefs.php'; 628 629 /* Ensure that the defaults from this file are only read once. 630 Also, make sure we can read this file. */ 631 if (!@is_readable($filename)) { 632 return; 633 } 634 635 /* Read the configuration file. The $_prefs array, which will be 636 in local scope, is assumed to hold the default values. */ 637 include $filename; 638 foreach ($_prefs as $pref => $pvals) { 639 if (isset($pvals['value']) && 640 isset($pvals['locked']) && 641 isset($pvals['shared']) && 642 ($pvals['type'] != 'link') && 643 ($pvals['type'] != 'special')) { 644 $pref = str_replace('.', '_', $pref); 645 $mask = 0; 646 if ($pvals['locked']) { 647 $mask |= _PREF_LOCKED; 648 } 649 if ($pvals['shared'] || $app == 'horde') { 650 $mask |= _PREF_SHARED; 651 } 652 $mask &= ~_PREF_DIRTY; 653 $mask |= _PREF_DEFAULT; 654 655 $this->add($pref, $pvals['value'], $mask); 656 if (!empty($pvals['hook'])) { 657 $this->_setHook($pref); 658 } 659 } 660 } 661 662 /* Update the preferences cache with the defaults. */ 663 $this->cacheUpdate(); 664 } 665 666 /** 667 * Performs shutdown activities. 668 * 669 * @access private 670 */ 671 function _shutdown() 672 { 673 register_shutdown_function(array(&$this, 'store')); 674 } 675 676 /** 677 * Add $pref to the list of preferences with hook functions. 678 * 679 * @param string $pref The preference with a hook. 680 */ 681 function _setHook($pref) 682 { 683 $this->_hooks[] = $pref; 684 } 685 686 /** 687 * After preferences have been loaded, set any locked or empty 688 * preferences that have hooks to the result of the hook. 689 */ 690 function _callHooks() 691 { 692 if (!is_null($this->_hooksCalled)) { 693 return; 694 } 695 696 $this->_hooksCalled = true; 697 698 if (!count($this->_hooks)) { 699 return; 700 } 701 702 global $registry; 703 include_once $registry->get('fileroot', 'horde') . '/config/hooks.php'; 704 foreach ($this->_hooks as $pref) { 705 if ($this->isLocked($pref) || 706 !$this->getValue($pref) || 707 $this->isDefault($pref)) { 708 $func = '_prefs_hook_' . $pref; 709 if (function_exists($func)) { 710 $this->_setValue($pref, $func($this->_user)); 711 } 712 } 713 } 714 } 715 716 /** 717 * Attempts to return a concrete Prefs instance based on $driver. 718 * 719 * @param mixed $driver The type of concrete Prefs subclass to return. 720 * If $driver is an array, then we will look in 721 * $driver[0]/lib/Prefs/ for the subclass 722 * implementation named $driver[1].php. 723 * @param string $scope The scope for this set of preferences. 724 * @param string $user The name of the user who owns this set of 725 * preferences. 726 * @param string $password The password associated with $user. 727 * @param array $params A hash containing any additional configuration 728 * or connection parameters a subclass might need. 729 * @param boolean $caching Should caching be used? 730 * 731 * @return Prefs The newly created concrete Prefs instance, or false on 732 * error. 733 */ 734 function &factory($driver, $scope = 'horde', $user = '', $password = '', 735 $params = null, $caching = true) 736 { 737 if (is_array($driver)) { 738 $app = $driver[0]; 739 $driver = $driver[1]; 740 } 741 742 /* Attempt to register (cache) the $prefs hash in session storage. */ 743 if ($caching) { 744 if (!isset($_SESSION['prefs_cache'])) { 745 $_SESSION['prefs_cache'] = array(); 746 } 747 } 748 749 $driver = basename($driver); 750 if (empty($driver) || $driver == 'none') { 751 $driver = 'session'; 752 } 753 754 if (is_null($params)) { 755 $params = Horde::getDriverConfig('prefs', $driver); 756 } 757 758 /* If $params['user_hook'] is defined, use it to retrieve the value to 759 * use for the username ($this->_user). Otherwise, just use the value 760 * passed in the $user parameter. */ 761 if (!empty($params['user_hook']) && 762 function_exists($params['user_hook'])) { 763 $user = call_user_func($params['user_hook'], $user); 764 } 765 766 if (!empty($app)) { 767 require_once $GLOBALS['registry']->get('fileroot', $app) . '/lib/Prefs/' . $driver . '.php'; 768 } elseif (file_exists(dirname(__FILE__) . '/Prefs/' . $driver . '.php')) { 769 require_once dirname(__FILE__) . '/Prefs/' . $driver . '.php'; 770 } else { 771 include_once 'Horde/Prefs/' . $driver . '.php'; 772 } 773 774 $class = 'Prefs_' . $driver; 775 if (class_exists($class)) { 776 $prefs = &new $class($user, $password, $scope, $params, $caching); 777 } else { 778 $prefs = PEAR::raiseError('Class definition of ' . $class . ' not found.'); 779 } 780 781 return $prefs; 782 } 783 784 /** 785 * Attempts to return a reference to a concrete Prefs instance based on 786 * $driver. It will only create a new instance if no Prefs instance 787 * with the same parameters currently exists. 788 * 789 * This should be used if multiple preference sources (and, thus, 790 * multiple Prefs instances) are required. 791 * 792 * This method must be invoked as: $var = &Prefs::singleton() 793 * 794 * @param mixed $driver The type of concrete Prefs subclass to return. 795 * If $driver is an array, then we will look in 796 * $driver[0]/lib/Prefs/ for the subclass 797 * implementation named $driver[1].php. 798 * @param string $scope The scope for this set of preferences. 799 * @param string $user The name of the user who owns this set of 800 * preferences. 801 * @param string $password The password associated with $user. 802 * @param array $params A hash containing any additional configuration 803 * or connection parameters a subclass might need. 804 * @param boolean $caching Should caching be used? 805 * 806 * @return Prefs The concrete Prefs reference, or false on an error. 807 */ 808 function &singleton($driver, $scope = 'horde', $user = '', $password = '', 809 $params = null, $caching = true) 810 { 811 static $instances = array(); 812 813 if (is_null($params)) { 814 $params = Horde::getDriverConfig('prefs', $driver); 815 } 816 817 $signature = serialize(array($driver, $user, $params)); 818 if (!isset($instances[$signature])) { 819 $instances[$signature] = &Prefs::factory($driver, $scope, $user, $password, $params, $caching); 820 } 821 822 return $instances[$signature]; 823 } 824 825 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |