3 * PEAR_Config, customized configuration handling for the PEAR Installer
\r
5 * PHP versions 4 and 5
\r
7 * LICENSE: This source file is subject to version 3.0 of the PHP license
\r
8 * that is available through the world-wide-web at the following URI:
\r
9 * http://www.php.net/license/3_0.txt. If you did not receive a copy of
\r
10 * the PHP License and are unable to obtain it through the web, please
\r
11 * send a note to license@php.net so we can mail you a copy immediately.
\r
15 * @author Stig Bakken <ssb@php.net>
\r
16 * @author Greg Beaver <cellog@php.net>
\r
17 * @copyright 1997-2008 The PHP Group
\r
18 * @license http://www.php.net/license/3_0.txt PHP License 3.0
\r
19 * @version CVS: $Id: Config.php 8901 2009-11-11 19:10:19Z cindy $
\r
20 * @link http://pear.php.net/package/PEAR
\r
21 * @since File available since Release 0.1
\r
25 * Required for error handling
\r
27 require_once 'PEAR.php';
\r
28 require_once 'PEAR/Registry.php';
\r
29 require_once 'PEAR/Installer/Role.php';
\r
30 require_once 'System.php';
\r
31 require_once 'PEAR/Remote.php';
\r
34 * Last created PEAR_Config instance.
\r
37 $GLOBALS['_PEAR_Config_instance'] = null;
\r
38 if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
\r
39 $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
\r
41 $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
\r
44 // Below we define constants with default values for all configuration
\r
45 // parameters except username/password. All of them can have their
\r
46 // defaults set through environment variables. The reason we use the
\r
47 // PHP_ prefix is for some security, PHP protects environment
\r
48 // variables starting with PHP_*.
\r
50 // default channel and preferred mirror is based on whether we are invoked through
\r
51 // the "pear" or the "pecl" command
\r
53 if (!defined('PEAR_RUNTYPE') || PEAR_RUNTYPE == 'pear') {
\r
54 define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
\r
56 define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
\r
59 if (getenv('PHP_PEAR_SYSCONF_DIR')) {
\r
60 define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
\r
61 } elseif (getenv('SystemRoot')) {
\r
62 define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
\r
64 define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
\r
67 // Default for master_server
\r
68 if (getenv('PHP_PEAR_MASTER_SERVER')) {
\r
69 define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
\r
71 define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
\r
74 // Default for http_proxy
\r
75 if (getenv('PHP_PEAR_HTTP_PROXY')) {
\r
76 define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
\r
77 } elseif (getenv('http_proxy')) {
\r
78 define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
\r
80 define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
\r
83 // Default for php_dir
\r
84 if (getenv('PHP_PEAR_INSTALL_DIR')) {
\r
85 define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
\r
87 if (@is_dir($PEAR_INSTALL_DIR)) {
\r
88 define('PEAR_CONFIG_DEFAULT_PHP_DIR',
\r
91 define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
\r
95 // Default for ext_dir
\r
96 if (getenv('PHP_PEAR_EXTENSION_DIR')) {
\r
97 define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
\r
99 if (ini_get('extension_dir')) {
\r
100 define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
\r
101 } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) {
\r
102 define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
\r
103 } elseif (defined('PHP_EXTENSION_DIR')) {
\r
104 define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
\r
106 define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
\r
110 // Default for doc_dir
\r
111 if (getenv('PHP_PEAR_DOC_DIR')) {
\r
112 define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
\r
114 define('PEAR_CONFIG_DEFAULT_DOC_DIR',
\r
115 $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
\r
118 // Default for bin_dir
\r
119 if (getenv('PHP_PEAR_BIN_DIR')) {
\r
120 define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
\r
122 define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
\r
125 // Default for data_dir
\r
126 if (getenv('PHP_PEAR_DATA_DIR')) {
\r
127 define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
\r
129 define('PEAR_CONFIG_DEFAULT_DATA_DIR',
\r
130 $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
\r
133 // Default for test_dir
\r
134 if (getenv('PHP_PEAR_TEST_DIR')) {
\r
135 define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
\r
137 define('PEAR_CONFIG_DEFAULT_TEST_DIR',
\r
138 $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
\r
141 // Default for cache_dir
\r
142 if (getenv('PHP_PEAR_CACHE_DIR')) {
\r
143 define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
\r
145 define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
\r
146 System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
\r
147 DIRECTORY_SEPARATOR . 'cache');
\r
150 // Default for php_bin
\r
151 if (getenv('PHP_PEAR_PHP_BIN')) {
\r
152 define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
\r
154 define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
\r
155 DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
\r
158 // Default for verbose
\r
159 if (getenv('PHP_PEAR_VERBOSE')) {
\r
160 define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
\r
162 define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
\r
165 // Default for preferred_state
\r
166 if (getenv('PHP_PEAR_PREFERRED_STATE')) {
\r
167 define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
\r
169 define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
\r
172 // Default for umask
\r
173 if (getenv('PHP_PEAR_UMASK')) {
\r
174 define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
\r
176 define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
\r
179 // Default for cache_ttl
\r
180 if (getenv('PHP_PEAR_CACHE_TTL')) {
\r
181 define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
\r
183 define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
\r
186 // Default for sig_type
\r
187 if (getenv('PHP_PEAR_SIG_TYPE')) {
\r
188 define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
\r
190 define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
\r
193 // Default for sig_bin
\r
194 if (getenv('PHP_PEAR_SIG_BIN')) {
\r
195 define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
\r
197 define('PEAR_CONFIG_DEFAULT_SIG_BIN',
\r
199 'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
\r
202 // Default for sig_keydir
\r
203 if (getenv('PHP_PEAR_SIG_KEYDIR')) {
\r
204 define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
\r
206 define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
\r
207 PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
\r
211 * This is a class for storing configuration data, keeping track of
\r
212 * which are system-defined, user-defined or defaulted.
\r
215 * @author Stig Bakken <ssb@php.net>
\r
216 * @author Greg Beaver <cellog@php.net>
\r
217 * @copyright 1997-2008 The PHP Group
\r
218 * @license http://www.php.net/license/3_0.txt PHP License 3.0
\r
219 * @version Release: 1.4.4
\r
220 * @link http://pear.php.net/package/PEAR
\r
221 * @since Class available since Release 0.1
\r
223 class PEAR_Config extends PEAR
\r
228 * Array of config files used.
\r
230 * @var array layer => config file
\r
232 var $files = array(
\r
237 var $layers = array();
\r
240 * Configuration data, two-dimensional array where the first
\r
241 * dimension is the config layer ('user', 'system' and 'default'),
\r
242 * and the second dimension is keyname => value.
\r
244 * The order in the first dimension is important! Earlier
\r
245 * layers will shadow later ones when a config value is
\r
246 * requested (if a 'user' value exists, it will be returned first,
\r
247 * then 'system' and finally 'default').
\r
249 * @var array layer => array(keyname => value, ...)
\r
251 var $configuration = array(
\r
253 'system' => array(),
\r
254 'default' => array(),
\r
258 * Configuration values that can be set for a channel
\r
260 * All other configuration values can only have a global value
\r
264 var $_channelConfigInfo = array(
\r
265 'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir',
\r
266 'test_dir', 'php_bin', 'username', 'password', 'verbose',
\r
267 'preferred_state', 'umask', 'preferred_mirror',
\r
271 * Channels that can be accessed
\r
272 * @see setChannels()
\r
276 var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
\r
279 * This variable is used to control the directory values returned
\r
280 * @see setInstallRoot();
\r
281 * @var string|false
\r
284 var $_installRoot = false;
\r
287 * If requested, this will always refer to the registry
\r
288 * contained in php_dir
\r
289 * @var PEAR_Registry
\r
291 var $_registry = array();
\r
297 var $_regInitialized = array();
\r
303 var $_noRegistry = false;
\r
306 * amount of errors found while parsing config
\r
310 var $_errorsFound = 0;
\r
311 var $_lastError = null;
\r
314 * Information about the configuration data. Stores the type,
\r
315 * default value and a documentation string for each configuration
\r
318 * @var array layer => array(infotype => value, ...)
\r
320 var $configuration_info = array(
\r
321 // Channels/Internet Access
\r
322 'default_channel' => array(
\r
323 'type' => 'string',
\r
324 'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
\r
325 'doc' => 'the default channel to use for all non explicit commands',
\r
326 'prompt' => 'Default Channel',
\r
327 'group' => 'Internet Access',
\r
329 'preferred_mirror' => array(
\r
330 'type' => 'string',
\r
331 'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
\r
332 'doc' => 'the default server or mirror to use for channel actions',
\r
333 'prompt' => 'Default Channel Mirror',
\r
334 'group' => 'Internet Access',
\r
336 'remote_config' => array(
\r
337 'type' => 'password',
\r
339 'doc' => 'ftp url of remote configuration file to use for synchronized install',
\r
340 'prompt' => 'Remote Configuration File',
\r
341 'group' => 'Internet Access',
\r
343 'auto_discover' => array(
\r
344 'type' => 'integer',
\r
346 'doc' => 'whether to automatically discover new channels',
\r
347 'prompt' => 'Auto-discover new Channels',
\r
348 'group' => 'Internet Access',
\r
351 'master_server' => array(
\r
352 'type' => 'string',
\r
353 'default' => 'pear.php.net',
\r
354 'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
\r
355 'prompt' => 'PEAR server [DEPRECATED]',
\r
356 'group' => 'Internet Access',
\r
358 'http_proxy' => array(
\r
359 'type' => 'string',
\r
360 'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
\r
361 'doc' => 'HTTP proxy (host:port) to use when downloading packages',
\r
362 'prompt' => 'HTTP Proxy Server Address',
\r
363 'group' => 'Internet Access',
\r
366 'php_dir' => array(
\r
367 'type' => 'directory',
\r
368 'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
\r
369 'doc' => 'directory where .php files are installed',
\r
370 'prompt' => 'PEAR directory',
\r
371 'group' => 'File Locations',
\r
373 'ext_dir' => array(
\r
374 'type' => 'directory',
\r
375 'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
\r
376 'doc' => 'directory where loadable extensions are installed',
\r
377 'prompt' => 'PHP extension directory',
\r
378 'group' => 'File Locations',
\r
380 'doc_dir' => array(
\r
381 'type' => 'directory',
\r
382 'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
\r
383 'doc' => 'directory where documentation is installed',
\r
384 'prompt' => 'PEAR documentation directory',
\r
385 'group' => 'File Locations',
\r
387 'bin_dir' => array(
\r
388 'type' => 'directory',
\r
389 'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
\r
390 'doc' => 'directory where executables are installed',
\r
391 'prompt' => 'PEAR executables directory',
\r
392 'group' => 'File Locations',
\r
394 'data_dir' => array(
\r
395 'type' => 'directory',
\r
396 'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
\r
397 'doc' => 'directory where data files are installed',
\r
398 'prompt' => 'PEAR data directory',
\r
399 'group' => 'File Locations (Advanced)',
\r
401 'test_dir' => array(
\r
402 'type' => 'directory',
\r
403 'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
\r
404 'doc' => 'directory where regression tests are installed',
\r
405 'prompt' => 'PEAR test directory',
\r
406 'group' => 'File Locations (Advanced)',
\r
408 'cache_dir' => array(
\r
409 'type' => 'directory',
\r
410 'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
\r
411 'doc' => 'directory which is used for XMLRPC cache',
\r
412 'prompt' => 'PEAR Installer cache directory',
\r
413 'group' => 'File Locations (Advanced)',
\r
415 'php_bin' => array(
\r
417 'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
\r
418 'doc' => 'PHP CLI/CGI binary for executing scripts',
\r
419 'prompt' => 'PHP CLI/CGI binary',
\r
420 'group' => 'File Locations (Advanced)',
\r
423 'username' => array(
\r
424 'type' => 'string',
\r
426 'doc' => '(maintainers) your PEAR account name',
\r
427 'prompt' => 'PEAR username (for maintainers)',
\r
428 'group' => 'Maintainers',
\r
430 'password' => array(
\r
431 'type' => 'password',
\r
433 'doc' => '(maintainers) your PEAR account password',
\r
434 'prompt' => 'PEAR password (for maintainers)',
\r
435 'group' => 'Maintainers',
\r
438 'verbose' => array(
\r
439 'type' => 'integer',
\r
440 'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
\r
441 'doc' => 'verbosity level
\r
446 'prompt' => 'Debug Log Level',
\r
447 'group' => 'Advanced',
\r
449 'preferred_state' => array(
\r
451 'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
\r
452 'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
\r
453 'valid_set' => array(
\r
454 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
\r
455 'prompt' => 'Preferred Package State',
\r
456 'group' => 'Advanced',
\r
460 'default' => PEAR_CONFIG_DEFAULT_UMASK,
\r
461 'doc' => 'umask used when creating files (Unix-like systems only)',
\r
462 'prompt' => 'Unix file mask',
\r
463 'group' => 'Advanced',
\r
465 'cache_ttl' => array(
\r
466 'type' => 'integer',
\r
467 'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
\r
468 'doc' => 'amount of secs where the local cache is used and not updated',
\r
469 'prompt' => 'Cache TimeToLive',
\r
470 'group' => 'Advanced',
\r
472 'sig_type' => array(
\r
474 'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
\r
475 'doc' => 'which package signature mechanism to use',
\r
476 'valid_set' => array('gpg'),
\r
477 'prompt' => 'Package Signature Type',
\r
478 'group' => 'Maintainers',
\r
480 'sig_bin' => array(
\r
481 'type' => 'string',
\r
482 'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
\r
483 'doc' => 'which package signature mechanism to use',
\r
484 'prompt' => 'Signature Handling Program',
\r
485 'group' => 'Maintainers',
\r
487 'sig_keyid' => array(
\r
488 'type' => 'string',
\r
490 'doc' => 'which key to use for signing with',
\r
491 'prompt' => 'Signature Key Id',
\r
492 'group' => 'Maintainers',
\r
494 'sig_keydir' => array(
\r
495 'type' => 'directory',
\r
496 'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
\r
497 'doc' => 'directory where signature keys are located',
\r
498 'prompt' => 'Signature Key Directory',
\r
499 'group' => 'Maintainers',
\r
501 // __channels is reserved - used for channel-specific configuration
\r
506 // {{{ PEAR_Config([file], [defaults_file])
\r
511 * @param string file to read user-defined options from
\r
512 * @param string file to read system-wide defaults from
\r
513 * @param bool determines whether a registry object "follows"
\r
514 * the value of php_dir (is automatically created
\r
515 * and moved when php_dir is changed)
\r
516 * @param bool if true, fails if configuration files cannot be loaded
\r
520 * @see PEAR_Config::singleton
\r
522 function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
\r
526 PEAR_Installer_Role::initializeConfig($this);
\r
527 $sl = DIRECTORY_SEPARATOR;
\r
528 if (empty($user_file)) {
\r
530 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
\r
532 $user_file = getenv('HOME') . $sl . '.pearrc';
\r
535 if (empty($system_file)) {
\r
537 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';
\r
539 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';
\r
543 $this->layers = array_keys($this->configuration);
\r
544 $this->files['user'] = $user_file;
\r
545 $this->files['system'] = $system_file;
\r
546 if ($user_file && @file_exists($user_file)) {
\r
547 $this->pushErrorHandling(PEAR_ERROR_RETURN);
\r
548 $this->readConfigFile($user_file, 'user', $strict);
\r
549 $this->popErrorHandling();
\r
550 if ($this->_errorsFound > 0) {
\r
555 if ($system_file && @file_exists($system_file)) {
\r
556 $this->mergeConfigFile($system_file, false, 'system', $strict);
\r
557 if ($this->_errorsFound > 0) {
\r
564 $ftp_file = $this->get('remote_config');
\r
567 if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
\r
568 $this->readFTPConfigFile($ftp_file);
\r
571 foreach ($this->configuration_info as $key => $info) {
\r
572 $this->configuration['default'][$key] = $info['default'];
\r
575 $this->_registry['default'] = new PEAR_Registry($this->configuration['default']['php_dir']);
\r
576 $this->_registry['default']->setConfig($this);
\r
577 $this->_regInitialized['default'] = false;
\r
578 //$GLOBALS['_PEAR_Config_instance'] = &$this;
\r
582 // {{{ singleton([file], [defaults_file])
\r
585 * Static singleton method. If you want to keep only one instance
\r
586 * of this class in use, this method will give you a reference to
\r
587 * the last created PEAR_Config object if one exists, or create a
\r
590 * @param string (optional) file to read user-defined options from
\r
591 * @param string (optional) file to read system-wide defaults from
\r
593 * @return object an existing or new PEAR_Config instance
\r
597 * @see PEAR_Config::PEAR_Config
\r
599 function &singleton($user_file = '', $system_file = '', $strict = true)
\r
601 if (is_object($GLOBALS['_PEAR_Config_instance'])) {
\r
602 return $GLOBALS['_PEAR_Config_instance'];
\r
605 $t_conf = new PEAR_Config($user_file, $system_file, false, $strict);
\r
606 if ($t_conf->_errorsFound > 0) {
\r
607 return $t_conf->lastError;
\r
610 $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
\r
611 return $GLOBALS['_PEAR_Config_instance'];
\r
615 // {{{ validConfiguration()
\r
618 * Determine whether any configuration files have been detected, and whether a
\r
619 * registry object can be retrieved from this configuration.
\r
621 * @since PEAR 1.4.0a1
\r
623 function validConfiguration()
\r
625 if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
\r
632 // {{{ readConfigFile([file], [layer])
\r
635 * Reads configuration data from a file. All existing values in
\r
636 * the config layer are discarded and replaced with data from the
\r
638 * @param string file to read from, if NULL or not specified, the
\r
639 * last-used file for the same layer (second param) is used
\r
640 * @param string config layer to insert data into ('user' or 'system')
\r
641 * @return bool TRUE on success or a PEAR error on failure
\r
643 function readConfigFile($file = null, $layer = 'user', $strict = true)
\r
645 if (empty($this->files[$layer])) {
\r
646 return $this->raiseError("unknown config layer `$layer'");
\r
649 if ($file === null) {
\r
650 $file = $this->files[$layer];
\r
653 $data = $this->_readConfigDataFrom($file);
\r
655 if (PEAR::isError($data)) {
\r
657 $this->_errorsFound++;
\r
658 $this->lastError = $data;
\r
665 $this->files[$layer] = $file;
\r
668 $this->_decodeInput($data);
\r
669 $this->configuration[$layer] = $data;
\r
670 $this->_setupChannels();
\r
671 if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
\r
672 $this->_registry[$layer] = new PEAR_Registry($phpdir);
\r
673 $this->_registry[$layer]->setConfig($this);
\r
674 $this->_regInitialized[$layer] = false;
\r
676 unset($this->_registry[$layer]);
\r
684 * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
\r
685 * @return true|PEAR_Error
\r
687 function readFTPConfigFile($path)
\r
689 do { // poor man's try
\r
690 if (!class_exists('Net_FTP')) {
\r
691 if (!class_exists('PEAR_Common')) {
\r
692 require_once 'PEAR/Common.php';
\r
694 if (PEAR_Common::isIncludeable('Net/FTP.php')) {
\r
695 include_once 'Net/FTP.php';
\r
698 if (class_exists('Net_FTP') &&
\r
699 (class_exists('PEAR_FTP') || PEAR_Common::isIncludeable('PEAR/FTP.php'))) {
\r
700 require_once 'PEAR/FTP.php';
\r
701 $this->_ftp = new PEAR_FTP;
\r
702 $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
\r
703 $e = $this->_ftp->init($path);
\r
704 if (PEAR::isError($e)) {
\r
705 $this->_ftp->popErrorHandling();
\r
708 $tmp = System::mktemp('-d');
\r
709 PEAR_Common::addTempFile($tmp);
\r
710 $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
\r
711 'pear.ini', false, FTP_BINARY);
\r
712 if (PEAR::isError($e)) {
\r
713 $this->_ftp->popErrorHandling();
\r
716 PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
\r
717 $this->_ftp->disconnect();
\r
718 $this->_ftp->popErrorHandling();
\r
719 $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
\r
720 $e = $this->readConfigFile(null, 'ftp');
\r
721 if (PEAR::isError($e)) {
\r
725 foreach ($this->configuration_info as $key => $val) {
\r
726 if (in_array($this->getGroup($key),
\r
727 array('File Locations', 'File Locations (Advanced)')) &&
\r
728 $this->getType($key) == 'directory') {
\r
729 // any directory configs must be set for this to work
\r
730 if (!isset($this->configuration['ftp'][$key])) {
\r
735 if (count($fail)) {
\r
736 $fail = '"' . implode('", "', $fail) . '"';
\r
737 unset($this->files['ftp']);
\r
738 unset($this->configuration['ftp']);
\r
739 return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
\r
740 'directory configuration variables. These variables were not set: ' .
\r
746 return PEAR::raiseError('Net_FTP must be installed to use remote config');
\r
748 } while (false); // poor man's catch
\r
749 unset($this->files['ftp']);
\r
750 return PEAR::raiseError('no remote host specified');
\r
753 // {{{ _setupChannels()
\r
756 * Reads the existing configurations and creates the _channels array from it
\r
758 function _setupChannels()
\r
760 $set = array_flip(array_values($this->_channels));
\r
761 foreach ($this->configuration as $layer => $data) {
\r
763 if (isset($data['__channels'])) {
\r
764 foreach ($data['__channels'] as $channel => $info) {
\r
765 $set[$channel] = $i++;
\r
769 $this->_channels = array_values(array_flip($set));
\r
770 $this->setChannels($this->_channels);
\r
774 // {{{ deleteChannel(channel)
\r
776 function deleteChannel($channel)
\r
778 foreach ($this->configuration as $layer => $data) {
\r
779 if (isset($data['__channels'])) {
\r
780 if (isset($data['__channels'][strtolower($channel)])) {
\r
781 unset($this->configuration[$layer]['__channels'][strtolower($channel)]);
\r
785 $this->_channels = array_flip($this->_channels);
\r
786 unset($this->_channels[strtolower($channel)]);
\r
787 $this->_channels = array_flip($this->_channels);
\r
791 // {{{ mergeConfigFile(file, [override], [layer])
\r
794 * Merges data into a config layer from a file. Does the same
\r
795 * thing as readConfigFile, except it does not replace all
\r
796 * existing values in the config layer.
\r
797 * @param string file to read from
\r
798 * @param bool whether to overwrite existing data (default TRUE)
\r
799 * @param string config layer to insert data into ('user' or 'system')
\r
800 * @param string if true, errors are returned if file opening fails
\r
801 * @return bool TRUE on success or a PEAR error on failure
\r
803 function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
\r
805 if (empty($this->files[$layer])) {
\r
806 return $this->raiseError("unknown config layer `$layer'");
\r
808 if ($file === null) {
\r
809 $file = $this->files[$layer];
\r
811 $data = $this->_readConfigDataFrom($file);
\r
812 if (PEAR::isError($data)) {
\r
814 $this->_errorsFound++;
\r
815 $this->lastError = $data;
\r
822 $this->_decodeInput($data);
\r
824 $this->configuration[$layer] =
\r
825 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
\r
827 $this->configuration[$layer] =
\r
828 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
\r
830 $this->_setupChannels();
\r
831 if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
\r
832 $this->_registry[$layer] = new PEAR_Registry($phpdir);
\r
833 $this->_registry[$layer]->setConfig($this);
\r
834 $this->_regInitialized[$layer] = false;
\r
836 unset($this->_registry[$layer]);
\r
842 // {{{ arrayMergeRecursive($arr2, $arr1)
\r
849 function arrayMergeRecursive($arr2, $arr1)
\r
852 foreach ($arr2 as $key => $data) {
\r
853 if (!isset($arr1[$key])) {
\r
854 $ret[$key] = $data;
\r
855 unset($arr1[$key]);
\r
858 if (is_array($data)) {
\r
859 if (!is_array($arr1[$key])) {
\r
860 $ret[$key] = $arr1[$key];
\r
861 unset($arr1[$key]);
\r
864 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
\r
865 unset($arr1[$key]);
\r
868 return array_merge($ret, $arr1);
\r
872 // {{{ writeConfigFile([file], [layer])
\r
875 * Writes data into a config layer from a file.
\r
877 * @param string|null file to read from, or null for default
\r
878 * @param string config layer to insert data into ('user' or
\r
880 * @param string|null data to write to config file or null for internal data [DEPRECATED]
\r
881 * @return bool TRUE on success or a PEAR error on failure
\r
883 function writeConfigFile($file = null, $layer = 'user', $data = null)
\r
885 $this->_lazyChannelSetup($layer);
\r
886 if ($layer == 'both' || $layer == 'all') {
\r
887 foreach ($this->files as $type => $file) {
\r
888 $err = $this->writeConfigFile($file, $type, $data);
\r
889 if (PEAR::isError($err)) {
\r
895 if (empty($this->files[$layer])) {
\r
896 return $this->raiseError("unknown config file type `$layer'");
\r
898 if ($file === null) {
\r
899 $file = $this->files[$layer];
\r
901 $data = ($data === null) ? $this->configuration[$layer] : $data;
\r
902 $this->_encodeOutput($data);
\r
903 $opt = array('-p', dirname($file));
\r
904 if (!@System::mkDir($opt)) {
\r
905 return $this->raiseError("could not create directory: " . dirname($file));
\r
907 if (@is_file($file) && !@is_writeable($file)) {
\r
908 return $this->raiseError("no write access to $file!");
\r
910 $fp = @fopen($file, "w");
\r
912 return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed");
\r
914 $contents = "#PEAR_Config 0.9\n" . serialize($data);
\r
915 if (!@fwrite($fp, $contents)) {
\r
916 return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed");
\r
922 // {{{ _readConfigDataFrom(file)
\r
925 * Reads configuration data from a file and returns the parsed data
\r
928 * @param string file to read from
\r
930 * @return array configuration data or a PEAR error on failure
\r
934 function _readConfigDataFrom($file)
\r
936 $fp = @fopen($file, "r");
\r
938 return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
\r
940 $size = filesize($file);
\r
941 $rt = get_magic_quotes_runtime();
\r
942 set_magic_quotes_runtime(0);
\r
943 if (function_exists('file_get_contents')) {
\r
945 $contents = file_get_contents($file);
\r
947 $contents = @fread($fp, $size);
\r
950 if (empty($contents)) {
\r
951 return $this->raiseError('Configuration file "' . $file . '" is empty');
\r
954 set_magic_quotes_runtime($rt);
\r
957 if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
\r
958 $version = $matches[1];
\r
959 $contents = substr($contents, strlen($matches[0]));
\r
961 // Museum config file
\r
962 if (substr($contents,0,2) == 'a:') {
\r
966 if ($version && version_compare("$version", '1', '<')) {
\r
968 // no '@', it is possible that unserialize
\r
969 // raises a notice but it seems to block IO to
\r
970 // STDOUT if a '@' is used and a notice is raise
\r
971 $data = unserialize($contents);
\r
973 if (!is_array($data) && !$data) {
\r
974 if ($contents == serialize(false)) {
\r
977 $err = $this->raiseError("PEAR_Config: bad data in $file");
\r
981 if (!is_array($data)) {
\r
982 if (strlen(trim($contents)) > 0) {
\r
983 $error = "PEAR_Config: bad data in $file";
\r
984 $err = $this->raiseError($error);
\r
990 // add parsing of newer formats here...
\r
992 $err = $this->raiseError("$file: unknown version `$version'");
\r
999 // {{{ getConfFile(layer)
\r
1001 * Gets the file used for storing the config for a layer
\r
1003 * @param string $layer 'user' or 'system'
\r
1006 function getConfFile($layer)
\r
1008 return $this->files[$layer];
\r
1014 * @param array information on a role as parsed from its xml file
\r
1015 * @return true|PEAR_Error
\r
1018 function _addConfigVars($vars)
\r
1020 if (count($vars) > 3) {
\r
1021 return $this->raiseError('Roles can only define 3 new config variables or less');
\r
1023 foreach ($vars as $name => $var) {
\r
1024 if (!is_array($var)) {
\r
1025 return $this->raiseError('Configuration information must be an array');
\r
1027 if (!isset($var['type'])) {
\r
1028 return $this->raiseError('Configuration information must contain a type');
\r
1030 if (!in_array($var['type'],
\r
1031 array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
\r
1032 return $this->raiseError(
\r
1033 'Configuration type must be one of directory, file, string, ' .
\r
1034 'mask, set, or password');
\r
1037 if (!isset($var['default'])) {
\r
1038 return $this->raiseError(
\r
1039 'Configuration information must contain a default value ("default" index)');
\r
1041 if (is_array($var['default'])) {
\r
1042 $real_default = '';
\r
1043 foreach ($var['default'] as $config_var => $val) {
\r
1044 if (strpos($config_var, 'text') === 0) {
\r
1045 $real_default .= $val;
\r
1046 } elseif (strpos($config_var, 'constant') === 0) {
\r
1047 if (defined($val)) {
\r
1048 $real_default .= constant($val);
\r
1050 return $this->raiseError(
\r
1051 'Unknown constant "' . $val . '" requested in ' .
\r
1052 'default value for configuration variable "' .
\r
1055 } elseif (isset($this->configuration_info[$config_var])) {
\r
1057 $this->configuration_info[$config_var]['default'];
\r
1059 return $this->raiseError(
\r
1060 'Unknown request for "' . $config_var . '" value in ' .
\r
1061 'default value for configuration variable "' .
\r
1065 $var['default'] = $real_default;
\r
1067 if ($var['type'] == 'integer') {
\r
1068 $var['default'] = (integer) $var['default'];
\r
1071 if (!isset($var['doc'])) {
\r
1072 return $this->raiseError(
\r
1073 'Configuration information must contain a summary ("doc" index)');
\r
1075 if (!isset($var['prompt'])) {
\r
1076 return $this->raiseError(
\r
1077 'Configuration information must contain a simple prompt ("prompt" index)');
\r
1079 if (!isset($var['group'])) {
\r
1080 return $this->raiseError(
\r
1081 'Configuration information must contain a simple group ("group" index)');
\r
1083 if (isset($this->configuration_info[$name])) {
\r
1084 return $this->raiseError('Configuration variable "' . $name .
\r
1085 '" already exists');
\r
1087 $this->configuration_info[$name] = $var;
\r
1092 // {{{ _encodeOutput(&data)
\r
1095 * Encodes/scrambles configuration data before writing to files.
\r
1096 * Currently, 'password' values will be base64-encoded as to avoid
\r
1097 * that people spot cleartext passwords by accident.
\r
1099 * @param array (reference) array to encode values in
\r
1101 * @return bool TRUE on success
\r
1105 function _encodeOutput(&$data)
\r
1107 foreach ($data as $key => $value) {
\r
1108 if ($key == '__channels') {
\r
1109 foreach ($data['__channels'] as $channel => $blah) {
\r
1110 $this->_encodeOutput($data['__channels'][$channel]);
\r
1113 if (!isset($this->configuration_info[$key])) {
\r
1116 $type = $this->configuration_info[$key]['type'];
\r
1118 // we base64-encode passwords so they are at least
\r
1119 // not shown in plain by accident
\r
1120 case 'password': {
\r
1121 $data[$key] = base64_encode($data[$key]);
\r
1125 $data[$key] = octdec($data[$key]);
\r
1134 // {{{ _decodeInput(&data)
\r
1137 * Decodes/unscrambles configuration data after reading from files.
\r
1139 * @param array (reference) array to encode values in
\r
1141 * @return bool TRUE on success
\r
1145 * @see PEAR_Config::_encodeOutput
\r
1147 function _decodeInput(&$data)
\r
1149 if (!is_array($data)) {
\r
1152 foreach ($data as $key => $value) {
\r
1153 if ($key == '__channels') {
\r
1154 foreach ($data['__channels'] as $channel => $blah) {
\r
1155 $this->_decodeInput($data['__channels'][$channel]);
\r
1158 if (!isset($this->configuration_info[$key])) {
\r
1161 $type = $this->configuration_info[$key]['type'];
\r
1163 case 'password': {
\r
1164 $data[$key] = base64_decode($data[$key]);
\r
1168 $data[$key] = decoct($data[$key]);
\r
1177 // {{{ getDefaultChannel([layer])
\r
1179 * Retrieve the default channel.
\r
1181 * On startup, channels are not initialized, so if the default channel is not
\r
1182 * pear.php.net, then initialize the config.
\r
1183 * @param string registry layer
\r
1184 * @return string|false
\r
1186 function getDefaultChannel($layer = null)
\r
1189 if ($layer === null) {
\r
1190 foreach ($this->layers as $layer) {
\r
1191 if (isset($this->configuration[$layer]['default_channel'])) {
\r
1192 $ret = $this->configuration[$layer]['default_channel'];
\r
1196 } elseif (isset($this->configuration[$layer]['default_channel'])) {
\r
1197 $ret = $this->configuration[$layer]['default_channel'];
\r
1199 if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
\r
1200 $ret = 'pecl.php.net';
\r
1203 if ($ret != 'pear.php.net') {
\r
1204 $this->_lazyChannelSetup();
\r
1208 return PEAR_CONFIG_DEFAULT_CHANNEL;
\r
1211 // {{{ get(key, [layer])
\r
1213 * Returns a configuration value, prioritizing layers as per the
\r
1214 * layers property.
\r
1216 * @param string config key
\r
1218 * @return mixed the config value, or NULL if not found
\r
1222 function get($key, $layer = null, $channel = false)
\r
1224 if (!isset($this->configuration_info[$key])) {
\r
1227 if ($key == '__channels') {
\r
1230 if ($key == 'default_channel') {
\r
1231 return $this->getDefaultChannel($layer);
\r
1234 $channel = $this->getDefaultChannel();
\r
1235 } elseif ($channel != 'pear.php.net') {
\r
1236 $this->_lazyChannelSetup();
\r
1238 $channel = strtolower($channel);
\r
1240 $test = (in_array($key, $this->_channelConfigInfo)) ?
\r
1241 $this->_getChannelValue($key, $layer, $channel) :
\r
1243 if ($test !== null) {
\r
1244 if ($this->_installRoot) {
\r
1245 if (in_array($this->getGroup($key),
\r
1246 array('File Locations', 'File Locations (Advanced)')) &&
\r
1247 $this->getType($key) == 'directory') {
\r
1248 return $this->_prependPath($test, $this->_installRoot);
\r
1253 if ($layer === null) {
\r
1254 foreach ($this->layers as $layer) {
\r
1255 if (isset($this->configuration[$layer][$key])) {
\r
1256 $test = $this->configuration[$layer][$key];
\r
1257 if ($this->_installRoot) {
\r
1258 if (in_array($this->getGroup($key),
\r
1259 array('File Locations', 'File Locations (Advanced)')) &&
\r
1260 $this->getType($key) == 'directory') {
\r
1261 return $this->_prependPath($test, $this->_installRoot);
\r
1264 if ($key == 'preferred_mirror') {
\r
1265 $reg = &$this->getRegistry();
\r
1266 if (is_object($reg)) {
\r
1267 $chan = &$reg->getChannel($channel);
\r
1268 if (!$chan->getMirror($test) && $chan->getName() != $test) {
\r
1269 return $channel; // mirror does not exist
\r
1276 } elseif (isset($this->configuration[$layer][$key])) {
\r
1277 $test = $this->configuration[$layer][$key];
\r
1278 if ($this->_installRoot) {
\r
1279 if (in_array($this->getGroup($key),
\r
1280 array('File Locations', 'File Locations (Advanced)')) &&
\r
1281 $this->getType($key) == 'directory') {
\r
1282 return $this->_prependPath($test, $this->_installRoot);
\r
1285 if ($key == 'preferred_mirror') {
\r
1286 $reg = &$this->getRegistry();
\r
1287 if (is_object($reg)) {
\r
1288 $chan = &$reg->getChannel($channel);
\r
1289 if (!$chan->getMirror($test) && $chan->getName() != $test) {
\r
1290 return $channel; // mirror does not exist
\r
1300 // {{{ _getChannelValue(key, value, [layer])
\r
1302 * Returns a channel-specific configuration value, prioritizing layers as per the
\r
1303 * layers property.
\r
1305 * @param string config key
\r
1307 * @return mixed the config value, or NULL if not found
\r
1311 function _getChannelValue($key, $layer, $channel)
\r
1313 if ($key == '__channels' || $channel == 'pear.php.net') {
\r
1317 if ($layer === null) {
\r
1318 foreach ($this->layers as $ilayer) {
\r
1319 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
\r
1320 $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
\r
1324 } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
\r
1325 $ret = $this->configuration[$layer]['__channels'][$channel][$key];
\r
1327 if ($key == 'preferred_mirror') {
\r
1328 if ($ret !== null) {
\r
1329 $reg = &$this->getRegistry($layer);
\r
1330 if (is_object($reg)) {
\r
1331 $chan = &$reg->getChannel($channel);
\r
1332 if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
\r
1333 return $channel; // mirror does not exist
\r
1338 if ($channel == $this->getDefaultChannel($layer)) {
\r
1339 return $channel; // we must use the channel name as the preferred mirror
\r
1340 // if the user has not chosen an alternate
\r
1342 return $this->getDefaultChannel($layer);
\r
1350 // {{{ set(key, value, [layer])
\r
1353 * Set a config value in a specific layer (defaults to 'user').
\r
1354 * Enforces the types defined in the configuration_info array. An
\r
1355 * integer config variable will be cast to int, and a set config
\r
1356 * variable will be validated against its legal values.
\r
1358 * @param string config key
\r
1359 * @param string config value
\r
1360 * @param string (optional) config layer
\r
1361 * @param string channel to set this value for, or null for global value
\r
1362 * @return bool TRUE on success, FALSE on failure
\r
1364 function set($key, $value, $layer = 'user', $channel = false)
\r
1366 if ($key == '__channels') {
\r
1369 if (!isset($this->configuration[$layer])) {
\r
1372 if ($key == 'default_channel') {
\r
1373 // can only set this value globally
\r
1374 $channel = 'pear.php.net';
\r
1375 if ($value != 'pear.php.net') {
\r
1376 $this->_lazyChannelSetup($layer);
\r
1379 if ($key == 'preferred_mirror') {
\r
1380 if ($channel == '__uri') {
\r
1381 return false; // can't set the __uri pseudo-channel's mirror
\r
1383 $reg = &$this->getRegistry($layer);
\r
1384 if (is_object($reg)) {
\r
1385 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
\r
1386 if (!$chan->getMirror($value) && $chan->getName() != $value) {
\r
1387 return false; // mirror does not exist
\r
1391 if (empty($this->configuration_info[$key])) {
\r
1394 extract($this->configuration_info[$key]);
\r
1397 $value = (int)$value;
\r
1400 // If a valid_set is specified, require the value to
\r
1401 // be in the set. If there is no valid_set, accept
\r
1404 reset($valid_set);
\r
1405 if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
\r
1406 (key($valid_set) !== 0 && empty($valid_set[$value])))
\r
1415 $channel = $this->get('default_channel', null, 'pear.php.net');
\r
1417 if (!in_array($channel, $this->_channels)) {
\r
1418 $this->_lazyChannelSetup($layer);
\r
1419 $reg = &$this->getRegistry($layer);
\r
1421 $channel = $reg->channelName($channel);
\r
1423 if (!in_array($channel, $this->_channels)) {
\r
1427 if ($channel != 'pear.php.net') {
\r
1428 if (in_array($key, $this->_channelConfigInfo)) {
\r
1429 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
\r
1435 if ($key == 'default_channel') {
\r
1436 if (!isset($reg)) {
\r
1437 $reg = &$this->getRegistry($layer);
\r
1439 $reg = &$this->getRegistry();
\r
1443 $value = $reg->channelName($value);
\r
1450 $this->configuration[$layer][$key] = $value;
\r
1451 if ($key == 'php_dir' && !$this->_noRegistry) {
\r
1452 if (!isset($this->_registry[$layer]) ||
\r
1453 $value != $this->_registry[$layer]->install_dir) {
\r
1454 $this->_registry[$layer] = new PEAR_Registry($value);
\r
1455 $this->_regInitialized[$layer] = false;
\r
1456 $this->_registry[$layer]->setConfig($this);
\r
1463 function _lazyChannelSetup($uselayer = false)
\r
1465 if ($this->_noRegistry) {
\r
1469 foreach ($this->_registry as $layer => $p) {
\r
1470 if ($uselayer && $uselayer != $layer) {
\r
1473 if (!$this->_regInitialized[$layer]) {
\r
1474 if ($layer == 'default' && isset($this->_registry['user']) ||
\r
1475 isset($this->_registry['system'])) {
\r
1476 // only use the default registry if there are no alternatives
\r
1479 if (!is_object($this->_registry[$layer])) {
\r
1480 if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
\r
1481 $this->_registry[$layer] = new PEAR_Registry($phpdir);
\r
1482 $this->_registry[$layer]->setConfig($this);
\r
1483 $this->_regInitialized[$layer] = false;
\r
1485 unset($this->_registry[$layer]);
\r
1489 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
\r
1490 $this->_regInitialized[$layer] = true;
\r
1495 // {{{ setChannels()
\r
1498 * Set the list of channels.
\r
1500 * This should be set via a call to {@link PEAR_Registry::listChannels()}
\r
1503 * @return bool success of operation
\r
1505 function setChannels($channels, $merge = false)
\r
1507 if (!is_array($channels)) {
\r
1511 $this->_channels = array_merge($this->_channels, $channels);
\r
1513 $this->_channels = $channels;
\r
1515 foreach ($channels as $channel) {
\r
1516 $channel = strtolower($channel);
\r
1517 if ($channel == 'pear.php.net') {
\r
1520 foreach ($this->layers as $layer) {
\r
1521 if (!isset($this->configuration[$layer]['__channels'][$channel])
\r
1522 || !is_array($this->configuration[$layer]['__channels'][$channel])) {
\r
1523 $this->configuration[$layer]['__channels'][$channel] = array();
\r
1531 // {{{ getType(key)
\r
1534 * Get the type of a config value.
\r
1536 * @param string config key
\r
1538 * @return string type, one of "string", "integer", "file",
\r
1539 * "directory", "set" or "password".
\r
1544 function getType($key)
\r
1546 if (isset($this->configuration_info[$key])) {
\r
1547 return $this->configuration_info[$key]['type'];
\r
1553 // {{{ getDocs(key)
\r
1556 * Get the documentation for a config value.
\r
1558 * @param string config key
\r
1560 * @return string documentation string
\r
1565 function getDocs($key)
\r
1567 if (isset($this->configuration_info[$key])) {
\r
1568 return $this->configuration_info[$key]['doc'];
\r
1573 // {{{ getPrompt(key)
\r
1576 * Get the short documentation for a config value.
\r
1578 * @param string config key
\r
1580 * @return string short documentation string
\r
1585 function getPrompt($key)
\r
1587 if (isset($this->configuration_info[$key])) {
\r
1588 return $this->configuration_info[$key]['prompt'];
\r
1593 // {{{ getGroup(key)
\r
1596 * Get the parameter group for a config key.
\r
1598 * @param string config key
\r
1600 * @return string parameter group
\r
1605 function getGroup($key)
\r
1607 if (isset($this->configuration_info[$key])) {
\r
1608 return $this->configuration_info[$key]['group'];
\r
1614 // {{{ getGroups()
\r
1617 * Get the list of parameter groups.
\r
1619 * @return array list of parameter groups
\r
1624 function getGroups()
\r
1627 foreach ($this->configuration_info as $key => $info) {
\r
1628 $tmp[$info['group']] = 1;
\r
1630 return array_keys($tmp);
\r
1634 // {{{ getGroupKeys()
\r
1637 * Get the list of the parameters in a group.
\r
1639 * @param string $group parameter group
\r
1641 * @return array list of parameters in $group
\r
1646 function getGroupKeys($group)
\r
1649 foreach ($this->configuration_info as $key => $info) {
\r
1650 if ($info['group'] == $group) {
\r
1658 // {{{ getSetValues(key)
\r
1661 * Get the list of allowed set values for a config value. Returns
\r
1662 * NULL for config values that are not sets.
\r
1664 * @param string config key
\r
1666 * @return array enumerated array of set values, or NULL if the
\r
1667 * config key is unknown or not a set
\r
1672 function getSetValues($key)
\r
1674 if (isset($this->configuration_info[$key]) &&
\r
1675 isset($this->configuration_info[$key]['type']) &&
\r
1676 $this->configuration_info[$key]['type'] == 'set')
\r
1678 $valid_set = $this->configuration_info[$key]['valid_set'];
\r
1679 reset($valid_set);
\r
1680 if (key($valid_set) === 0) {
\r
1681 return $valid_set;
\r
1683 return array_keys($valid_set);
\r
1692 * Get all the current config keys.
\r
1694 * @return array simple array of config keys
\r
1698 function getKeys()
\r
1701 foreach ($this->layers as $layer) {
\r
1702 $test = $this->configuration[$layer];
\r
1703 if (isset($test['__channels'])) {
\r
1704 foreach ($test['__channels'] as $channel => $configs) {
\r
1705 $keys = array_merge($keys, $configs);
\r
1708 unset($test['__channels']);
\r
1709 $keys = array_merge($keys, $test);
\r
1711 return array_keys($keys);
\r
1715 // {{{ remove(key, [layer])
\r
1718 * Remove the a config key from a specific config layer.
\r
1720 * @param string config key
\r
1722 * @param string (optional) config layer
\r
1724 * @return bool TRUE on success, FALSE on failure
\r
1728 function remove($key, $layer = 'user')
\r
1730 $channel = $this->getDefaultChannel();
\r
1731 if ($channel !== 'pear.php.net') {
\r
1732 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
\r
1733 unset($this->configuration[$layer]['__channels'][$channel][$key]);
\r
1737 if (isset($this->configuration[$layer][$key])) {
\r
1738 unset($this->configuration[$layer][$key]);
\r
1745 // {{{ removeLayer(layer)
\r
1748 * Temporarily remove an entire config layer. USE WITH CARE!
\r
1750 * @param string config key
\r
1752 * @param string (optional) config layer
\r
1754 * @return bool TRUE on success, FALSE on failure
\r
1758 function removeLayer($layer)
\r
1760 if (isset($this->configuration[$layer])) {
\r
1761 $this->configuration[$layer] = array();
\r
1768 // {{{ store([layer])
\r
1771 * Stores configuration data in a layer.
\r
1773 * @param string config layer to store
\r
1775 * @return bool TRUE on success, or PEAR error on failure
\r
1779 function store($layer = 'user', $data = null)
\r
1781 return $this->writeConfigFile(null, $layer, $data);
\r
1785 // {{{ toDefault(key)
\r
1788 * Unset the user-defined value of a config key, reverting the
\r
1789 * value to the system-defined one.
\r
1791 * @param string config key
\r
1793 * @return bool TRUE on success, FALSE on failure
\r
1797 function toDefault($key)
\r
1799 trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE);
\r
1800 return $this->remove($key, 'user');
\r
1804 // {{{ definedBy(key)
\r
1807 * Tells what config layer that gets to define a key.
\r
1809 * @param string config key
\r
1810 * @param boolean return the defining channel
\r
1812 * @return string|array the config layer, or an empty string if not found.
\r
1814 * if $returnchannel, the return is an array array('layer' => layername,
\r
1815 * 'channel' => channelname), or an empty string if not found
\r
1819 function definedBy($key, $returnchannel = false)
\r
1821 foreach ($this->layers as $layer) {
\r
1822 $channel = $this->getDefaultChannel();
\r
1823 if ($channel !== 'pear.php.net') {
\r
1824 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
\r
1825 if ($returnchannel) {
\r
1826 return array('layer' => $layer, 'channel' => $channel);
\r
1831 if (isset($this->configuration[$layer][$key])) {
\r
1832 if ($returnchannel) {
\r
1833 return array('layer' => $layer, 'channel' => 'pear.php.net');
\r
1842 // {{{ isDefaulted(key)
\r
1845 * Tells whether a config value has a system-defined value.
\r
1847 * @param string config key
\r
1855 function isDefaulted($key)
\r
1857 trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE);
\r
1858 return $this->definedBy($key) == 'system';
\r
1862 // {{{ isDefined(key)
\r
1865 * Tells whether a given key exists as a config value.
\r
1867 * @param string config key
\r
1869 * @return bool whether <config key> exists in this object
\r
1873 function isDefined($key)
\r
1875 foreach ($this->layers as $layer) {
\r
1876 if (isset($this->configuration[$layer][$key])) {
\r
1884 // {{{ isDefinedLayer(key)
\r
1887 * Tells whether a given config layer exists.
\r
1889 * @param string config layer
\r
1891 * @return bool whether <config layer> exists in this object
\r
1895 function isDefinedLayer($layer)
\r
1897 return isset($this->configuration[$layer]);
\r
1901 // {{{ getLayers()
\r
1904 * Returns the layers defined (except the 'default' one)
\r
1906 * @return array of the defined layers
\r
1908 function getLayers()
\r
1910 $cf = $this->configuration;
\r
1911 unset($cf['default']);
\r
1912 return array_keys($cf);
\r
1916 // {{{ apiVersion()
\r
1917 function apiVersion()
\r
1924 * @return PEAR_Registry
\r
1926 function &getRegistry($use = null)
\r
1928 if ($use === null) {
\r
1933 if (isset($this->_registry[$layer])) {
\r
1934 return $this->_registry[$layer];
\r
1935 } elseif ($use === null && isset($this->_registry['system'])) {
\r
1936 return $this->_registry['system'];
\r
1937 } elseif ($use === null && isset($this->_registry['default'])) {
\r
1938 return $this->_registry['default'];
\r
1943 // only go here if null was passed in
\r
1944 die("CRITICAL ERROR: Registry could not be initialized from any value");
\r
1948 * This is to allow customization like the use of installroot
\r
1949 * @param PEAR_Registry
\r
1952 function setRegistry(&$reg, $layer = 'user')
\r
1954 if ($this->_noRegistry) {
\r
1957 if (!in_array($layer, array('user', 'system'))) {
\r
1960 $this->_registry[$layer] = &$reg;
\r
1961 if (is_object($reg)) {
\r
1962 $this->_registry[$layer]->setConfig($this);
\r
1967 function noRegistry()
\r
1969 $this->_noRegistry = true;
\r
1973 * @return PEAR_Remote
\r
1975 function &getRemote()
\r
1977 $remote = new PEAR_Remote($this);
\r
1982 * @return PEAR_REST
\r
1984 function &getREST($version, $options = array())
\r
1986 $version = str_replace('.', '', $version);
\r
1987 if (!class_exists($class = 'PEAR_REST_' . $version)) {
\r
1988 require_once 'PEAR/REST/' . $version . '.php';
\r
1990 $remote = new $class($this, $options);
\r
1995 * The ftp server is set in {@link readFTPConfigFile()}. It exists only if a
\r
1996 * remote configuration file has been specified
\r
1997 * @return PEAR_FTP|false
\r
1999 function &getFTP()
\r
2001 if (isset($this->_ftp)) {
\r
2002 return $this->_ftp;
\r
2009 // {{{ _prependPath($path, $prepend)
\r
2011 function _prependPath($path, $prepend)
\r
2013 if (strlen($prepend) > 0) {
\r
2014 if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
\r
2015 if (preg_match('/^[a-z]:/i', $prepend)) {
\r
2016 $prepend = substr($prepend, 2);
\r
2017 } elseif ($prepend{0} != '\\') {
\r
2018 $prepend = "\\$prepend";
\r
2020 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
\r
2022 $path = $prepend . $path;
\r
2030 * @param string|false installation directory to prepend to all _dir variables, or false to
\r
2033 function setInstallRoot($root)
\r
2035 if (substr($root, -1) == DIRECTORY_SEPARATOR) {
\r
2036 $root = substr($root, 0, -1);
\r
2038 $old = $this->_installRoot;
\r
2039 $this->_installRoot = $root;
\r
2040 if (($old != $root) && !$this->_noRegistry) {
\r
2041 foreach (array_keys($this->_registry) as $layer) {
\r
2042 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
\r
2045 $this->_registry[$layer] =
\r
2046 new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
\r
2047 $this->_registry[$layer]->setConfig($this);
\r
2048 $this->_regInitialized[$layer] = false;
\r