Source for file Registry.php
Documentation is available at Registry.php
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
require_once 'PEAR/DependencyDB.php';
define('PEAR_REGISTRY_ERROR_LOCK', -2 );
define('PEAR_REGISTRY_ERROR_FORMAT', -3 );
define('PEAR_REGISTRY_ERROR_FILE', -4 );
define('PEAR_REGISTRY_ERROR_CONFLICT', -5 );
define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6 );
* Administration class used to maintain the installed package database.
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
* File containing all channel information.
/** Directory where registry files are stored.
/** File where the file map is stored
/** Directory where registry files for channels are stored.
/** Name of file used for locking the registry
/** File descriptor used during locking
/** Mode used during locking
/** Cache of package information. Structure:
* 'package' => array('id' => ... ),
/** Cache of file map. Structure:
* array( '/path/to/file' => 'package', ... )
* @var false|PEAR_ChannelFile
* @var false|PEAR_ChannelFile
* @var false|PEAR_ChannelFile
* PEAR_Registry constructor.
* @param string (optional) PEAR install directory (for .php files)
* @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
* default values are not desired. Only used the very first time a PEAR
* repository is initialized
* @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
* default values are not desired. Only used the very first time a PEAR
* repository is initialized
function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR , $pear_channel = false ,
$this->_pearChannel = $pear_channel;
$this->_peclChannel = $pecl_channel;
$ds = DIRECTORY_SEPARATOR;
$this->install_dir = $pear_install_dir;
$this->channelsdir = $pear_install_dir. $ds. '.channels';
$this->statedir = $pear_install_dir. $ds. '.registry';
$this->filemap = $pear_install_dir. $ds. '.filemap';
$this->lockfile = $pear_install_dir. $ds. '.lock';
$dir = $this->install_dir;
while ($dir && $dir != '.') {
if ($dir == $olddir) { // this can happen in safe mode
function setConfig(&$config, $resetInstallDir = true )
$this->_config = &$config;
function _initializeChannelDirs ()
$ds = DIRECTORY_SEPARATOR;
if (!is_dir ($this->channelsdir ) ||
!file_exists ($this->channelsdir . $ds . 'pear.php.net.reg') ||
!file_exists ($this->channelsdir . $ds . 'pecl.php.net.reg') ||
!file_exists ($this->channelsdir . $ds . 'doc.php.net.reg') ||
!file_exists ($this->channelsdir . $ds . '__uri.reg')) {
if (!file_exists ($this->channelsdir . $ds . 'pear.php.net.reg')) {
$pear_channel = $this->_pearChannel;
if (!is_a ($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate ()) {
if (!class_exists ('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
$pear_channel->setAlias ('pear');
$pear_channel->setServer ('pear.php.net');
$pear_channel->setSummary ('PHP Extension and Application Repository');
$pear_channel->setDefaultPEARProtocols ();
$pear_channel->setBaseURL ('REST1.0', 'http://pear.php.net/rest/');
$pear_channel->setBaseURL ('REST1.1', 'http://pear.php.net/rest/');
$pear_channel->setBaseURL ('REST1.3', 'http://pear.php.net/rest/');
//$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
$pear_channel->setServer ('pear.php.net');
$pear_channel->setAlias ('pear');
$pear_channel->validate ();
$this->_addChannel ($pear_channel);
$pecl_channel = $this->_peclChannel;
if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate ()) {
require_once 'PEAR/ChannelFile.php';
$pecl_channel->setAlias ('pecl');
$pecl_channel->setServer ('pecl.php.net');
$pecl_channel->setSummary ('PHP Extension Community Library');
$pecl_channel->setDefaultPEARProtocols ();
$pecl_channel->setBaseURL ('REST1.0', 'http://pecl.php.net/rest/');
$pecl_channel->setBaseURL ('REST1.1', 'http://pecl.php.net/rest/');
$pecl_channel->setValidationPackage ('PEAR_Validator_PECL', '1.0');
$pecl_channel->setServer ('pecl.php.net');
$pecl_channel->setAlias ('pecl');
$pecl_channel->validate ();
$this->_addChannel ($pecl_channel);
$doc_channel = $this->_docChannel;
if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate ()) {
require_once 'PEAR/ChannelFile.php';
$doc_channel->setAlias ('phpdocs');
$doc_channel->setServer ('doc.php.net');
$doc_channel->setSummary ('PHP Documentation Team');
$doc_channel->setDefaultPEARProtocols ();
$doc_channel->setBaseURL ('REST1.0', 'http://doc.php.net/rest/');
$doc_channel->setBaseURL ('REST1.1', 'http://doc.php.net/rest/');
$doc_channel->setBaseURL ('REST1.3', 'http://doc.php.net/rest/');
$doc_channel->setServer ('doc.php.net');
$doc_channel->setAlias ('doc');
$doc_channel->validate ();
$this->_addChannel ($doc_channel);
require_once 'PEAR/ChannelFile.php';
$private->setName ('__uri');
$private->setDefaultPEARProtocols ();
$private->setBaseURL ('REST1.0', '****');
$private->setSummary ('Pseudo-channel for static packages');
$this->_addChannel ($private);
$this->_rebuildFileMap ();
function _initializeDirs ()
$ds = DIRECTORY_SEPARATOR;
// XXX Compatibility code should be removed in the future
// rename all registry files if any to lowercase
while (false !== ($file = readdir($handle))) {
$this->_initializeChannelDirs ();
$this->_rebuildFileMap ();
$this->_initializeDepDB ();
function _initializeDepDB ()
if (!isset ($this->_dependencyDB )) {
static $initializing = false;
if (!$this->_config ) { // never used?
$file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
$this->_config = &new PEAR_Config ($this->statedir . DIRECTORY_SEPARATOR .
$this->_config ->setRegistry ($this);
$this->_config ->set ('php_dir', $this->install_dir );
// attempt to recover by removing the dep db
if (file_exists($this->_config ->get ('php_dir', null , 'pear.php.net') .
DIRECTORY_SEPARATOR . '.depdb')) {
@unlink($this->_config ->get ('php_dir', null , 'pear.php.net') .
DIRECTORY_SEPARATOR . '.depdb');
echo $this->_dependencyDB ->getMessage ();
echo 'Unrecoverable error';
* PEAR_Registry destructor. Makes sure no locks are forgotten.
function _PEAR_Registry ()
* Make sure the directory where we keep registry files exists.
* @return bool TRUE if directory exists, FALSE if it could not be
function _assertStateDir ($channel = false )
if ($channel && $this->_getChannelFromAlias ($channel) != 'pear.php.net') {
return $this->_assertChannelStateDir ($channel);
if (!file_exists ($this->statedir )) {
if (!$this->hasWriteAccess ()) {
require_once 'System.php';
return $this->raiseError(" could not create directory '{$this->statedir }'" );
'it already exists and is not a directory');
$ds = DIRECTORY_SEPARATOR;
'it already exists and is not a directory');
$this->_initializeDirs ();
$this->_initializeDepDB ();
* Make sure the directory where we keep registry files exists for a non-standard channel.
* @param string channel name
* @return bool TRUE if directory exists, FALSE if it could not be
function _assertChannelStateDir ($channel)
$ds = DIRECTORY_SEPARATOR;
if (!$channel || $this->_getChannelFromAlias ($channel) == 'pear.php.net') {
$this->_initializeChannelDirs ();
return $this->_assertStateDir ($channel);
$this->_initializeChannelDirs ();
require_once 'System.php';
if (!System::mkdir (array ('-p', $channelDir))) {
return $this->raiseError("could not create directory '" . $channelDir .
} elseif (!is_dir($channelDir)) {
return $this->raiseError("could not create directory '" . $channelDir .
"', already exists and is not a directory");
* Make sure the directory where we keep registry files for channels exists
* @return bool TRUE if directory exists, FALSE if it could not be
function _assertChannelDir ()
require_once 'System.php';
return $this->raiseError(" could not create directory '{$this->channelsdir }'" );
return $this->raiseError(" could not create directory '{$this->channelsdir }" .
"', it already exists and is not a directory");
require_once 'System.php';
if (!System::mkdir (array ('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
return $this->raiseError(" could not create directory '{$this->channelsdir }/.alias'" );
return $this->raiseError(" could not create directory '{$this->channelsdir }" .
"/.alias', it already exists and is not a directory");
* Get the name of the file where data for a given package is stored.
* @param string channel name, or false if this is a PEAR package
* @param string package name
* @return string registry file name
if ($channel && $this->_getChannelFromAlias ($channel) != 'pear.php.net') {
* Get the name of the file where data for a given channel is stored.
* @param string channel name
* @return string registry file name
function _channelFileName ($channel, $noaliases = false )
if (file_exists($this->_getChannelAliasFileName ($channel))) {
$channel = implode('', file($this->_getChannelAliasFileName ($channel)));
function _getChannelAliasFileName ($alias)
return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
* Get the name of a channel from its alias
function _getChannelFromAlias ($channel)
if (!$this->_channelExists ($channel)) {
if ($channel == 'pear.php.net') {
if ($channel == 'pecl.php.net') {
if ($channel == 'doc.php.net') {
if ($channel == '__uri') {
if (file_exists($this->_getChannelAliasFileName ($channel))) {
// translate an alias to an actual channel
return implode('', file($this->_getChannelAliasFileName ($channel)));
* Get the alias of a channel from its alias or its name
function _getAlias ($channel)
if (!$this->_channelExists ($channel)) {
if ($channel == 'pear.php.net') {
if ($channel == 'pecl.php.net') {
if ($channel == 'doc.php.net') {
$channel = $this->_getChannel ($channel);
return $channel->getAlias ();
* Get the name of the file where data for a given package is stored.
* @param string channel name, or false if this is a PEAR package
* @param string package name
* @return string registry file name
if (!$channel || $this->_getChannelFromAlias ($channel) == 'pear.php.net') {
$ch = $this->_getChannelFromAlias ($channel);
function _openPackageFile ($package, $mode, $channel = false )
if (!$this->_assertStateDir ($channel)) {
if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
$fp = @fopen($file, $mode);
function _closePackageFile ($fp)
function _openChannelFile ($channel, $mode)
if (!$this->_assertChannelDir ()) {
$file = $this->_channelFileName ($channel);
if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
$fp = @fopen($file, $mode);
function _closeChannelFile ($fp)
function _rebuildFileMap ()
require_once 'PEAR/Installer/Role.php';
$channels = $this->_listAllPackages ();
foreach ($channels as $channel => $packages) {
foreach ($packages as $package) {
$version = $this->_packageInfo ($package, 'version', $channel);
$filelist = $this->_packageInfo ($package, 'filelist', $channel);
foreach ($filelist as $name => $attrs) {
if (isset ($attrs['attribs'])) {
$attrs = $attrs['attribs'];
// it is possible for conflicting packages in different channels to
// conflict with data files/doc files
if ($name == 'dirtree') {
if (isset ($attrs['role']) && !in_array($attrs['role'],
// these are not installed
if (isset ($attrs['role']) && !in_array($attrs['role'],
$attrs['baseinstalldir'] = $package;
if (isset ($attrs['baseinstalldir'])) {
$file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR. $name;
if ($channel != 'pear.php.net') {
if (!isset ($files[$attrs['role']])) {
$files[$attrs['role']] = array ();
$files[$attrs['role']][$file] = array (strtolower($channel),
if (!isset ($files[$attrs['role']])) {
$files[$attrs['role']] = array ();
$files[$attrs['role']][$file] = strtolower($package);
$this->_assertStateDir ();
if (!$tmp && $fsize > 7 ) {
* @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
* See flock manual for more information.
* @return bool TRUE on success, FALSE if locking failed, or a
* PEAR error if some other error occurs (such as the
* lock file not being writable).
function _lock ($mode = LOCK_EX )
// XXX does not check type of lock (LOCK_SH/LOCK_EX)
if (!$this->_assertStateDir ()) {
return $this->raiseError('Registry directory is not writeable by the current user');
// XXX People reported problems with LOCK_SH and 'w'
if ($mode === LOCK_SH || $mode === LOCK_UN ) {
return $this->raiseError("could not create lock file" .
(isset ($php_errormsg) ? ": " . $php_errormsg : ""));
case LOCK_SH: $str = 'shared'; break;
case LOCK_EX: $str = 'exclusive'; break;
case LOCK_UN: $str = 'unlock'; break;
default: $str = 'unknown'; break;
//is resource at this point, close it on error.
return $this->raiseError(" could not acquire $str lock ($this->lockfile)" ,
$ret = $this->_lock (LOCK_UN );
function _packageExists ($package, $channel = false )
* Determine whether a channel exists in the registry
* @param string Channel name
* @param bool if true, then aliases will be ignored
function _channelExists ($channel, $noaliases = false )
$a = file_exists($this->_channelFileName ($channel, $noaliases));
if (!$a && $channel == 'pear.php.net') {
if (!$a && $channel == 'pecl.php.net') {
if (!$a && $channel == 'doc.php.net') {
* Determine whether a mirror exists within the deafult channel in the registry
* @param string Channel name
* @param string Mirror name
function _mirrorExists ($channel, $mirror)
$data = $this->_channelInfo ($channel);
if (!isset ($data['servers']['mirror'])) {
foreach ($data['servers']['mirror'] as $m) {
if ($m['attribs']['host'] == $mirror) {
* @param PEAR_ChannelFile Channel object
* @param string Last-Modified HTTP tag from remote request
* @return boolean|PEAR_ErrorTrue on creation, false if it already exists
function _addChannel ($channel, $update = false , $lastmodified = false )
if (!is_a($channel, 'PEAR_ChannelFile')) {
if (!$channel->validate ()) {
if (file_exists($this->_channelFileName ($channel->getName ()))) {
$checker = $this->_getChannel ($channel->getName ());
if ($channel->getAlias () != $checker->getAlias ()) {
if (file_exists($this->_getChannelAliasFileName ($checker->getAlias ()))) {
@unlink($this->_getChannelAliasFileName ($checker->getAlias ()));
if ($update && !in_array($channel->getName (), array ('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
$ret = $this->_assertChannelDir ();
$ret = $this->_assertChannelStateDir ($channel->getName ());
if ($channel->getAlias () != $channel->getName ()) {
if (file_exists($this->_getChannelAliasFileName ($channel->getAlias ())) &&
$this->_getChannelFromAlias ($channel->getAlias ()) != $channel->getName ()) {
$channel->setAlias ($channel->getName ());
$fp = @fopen($this->_getChannelAliasFileName ($channel->getAlias ()), 'w');
fwrite($fp, $channel->getName ());
$fp = @fopen($this->_channelFileName ($channel->getName ()), 'wb');
$info = $channel->toArray ();
$info['_lastmodified'] = $lastmodified;
$info['_lastmodified'] = date('r');
* Deletion fails if there are any packages installed from the channel
* @param string|PEAR_ChannelFilechannel name
* @return boolean|PEAR_ErrorTrue on deletion, false if it doesn't exist
function _deleteChannel ($channel)
if (!is_a($channel, 'PEAR_ChannelFile')) {
if (!$channel->validate ()) {
$channel = $channel->getName ();
if ($this->_getChannelFromAlias ($channel) == '__uri') {
if ($this->_getChannelFromAlias ($channel) == 'pecl.php.net') {
if ($this->_getChannelFromAlias ($channel) == 'doc.php.net') {
if (!$this->_channelExists ($channel)) {
if (!$channel || $this->_getChannelFromAlias ($channel) == 'pear.php.net') {
$channel = $this->_getChannelFromAlias ($channel);
if ($channel == 'pear.php.net') {
$test = $this->_listChannelPackages ($channel);
$file = $this->_getChannelAliasFileName ($this->_getAlias ($channel));
$file = $this->_channelFileName ($channel);
* Determine whether a channel exists in the registry
* @param string Channel Alias
function _isChannelAlias ($alias)
return file_exists($this->_getChannelAliasFileName ($alias));
function _packageInfo ($package = null , $key = null , $channel = 'pear.php.net')
$channels = $this->_listChannels ();
foreach ($channels as $channel) {
$ret[$channel] = array ();
$packages = $this->_listPackages ($channel);
foreach ($packages as $package) {
$ret[$channel][] = $this->_packageInfo ($package, null , $channel);
$ps = $this->_listPackages ($channel);
return array_map(array (&$this, '_packageInfo'),
$fp = $this->_openPackageFile ($package, 'r', $channel);
$this->_closePackageFile ($fp);
// compatibility for package.xml version 2.0
if (isset ($data['old'][$key])) {
return $data['old'][$key];
if (isset ($data[$key])) {
* @param string Channel name
* @param bool whether to strictly retrieve info of channels, not just aliases
function _channelInfo ($channel, $noaliases = false )
if (!$this->_channelExists ($channel, $noaliases)) {
$fp = $this->_openChannelFile ($channel, 'r');
$this->_closeChannelFile ($fp);
return array ('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
if ($ent{0 } == '.' || substr($ent, -4 ) != '.reg') {
if ($ent == '__uri.reg') {
$channellist[] = '__uri';
if (!in_array('pear.php.net', $channellist)) {
$channellist[] = 'pear.php.net';
if (!in_array('pecl.php.net', $channellist)) {
$channellist[] = 'pecl.php.net';
if (!in_array('doc.php.net', $channellist)) {
$channellist[] = 'doc.php.net';
$channellist[] = '__uri';
function _listPackages ($channel = false )
if ($channel && $this->_getChannelFromAlias ($channel) != 'pear.php.net') {
return $this->_listChannelPackages ($channel);
if ($ent{0 } == '.' || substr($ent, -4 ) != '.reg') {
$pkglist[] = substr($ent, 0 , -4 );
function _listChannelPackages ($channel)
if ($ent{0 } == '.' || substr($ent, -4 ) != '.reg') {
$pkglist[] = substr($ent, 0 , -4 );
function _listAllPackages ()
foreach ($this->_listChannels () as $channel) {
$ret[$channel] = $this->_listPackages ($channel);
* Add an installed package to the registry
* @param string package name
* @param array package info (parsed by PEAR_Common::infoFrom*() methods)
* @return bool success of saving
function _addPackage ($package, $info)
if ($this->_packageExists ($package)) {
$fp = $this->_openPackageFile ($package, 'wb');
$info['_lastmodified'] = time();
$this->_closePackageFile ($fp);
if (isset ($info['filelist'])) {
$this->_rebuildFileMap ();
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
function _addPackage2 ($info)
if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
if (!$info->validate ()) {
foreach ($info->getValidationWarnings () as $err) {
$ui->log($err['message'], true );
if ($this->_packageExists ($package, $channel)) {
if (!$this->_channelExists ($channel, true )) {
$info = $info->toArray (true );
$fp = $this->_openPackageFile ($package, 'wb', $channel);
$info['_lastmodified'] = time();
$this->_closePackageFile ($fp);
$this->_rebuildFileMap ();
* @param string Package name
* @param array parsed package.xml 1.0
* @param bool this parameter is only here for BC. Don't use it.
function _updatePackage ($package, $info, $merge = true )
$oldinfo = $this->_packageInfo ($package);
$fp = $this->_openPackageFile ($package, 'w');
$info = $info->toArray ();
$info['_lastmodified'] = time();
$this->_closePackageFile ($fp);
if (isset ($newinfo['filelist'])) {
$this->_rebuildFileMap ();
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
function _updatePackage2 ($info)
$info = $save->getArray (true );
$info['_lastmodified'] = time();
$this->_closePackageFile ($fp);
$this->_rebuildFileMap ();
* @param string Package name
* @param string Channel name
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
function &_getPackage ($package, $channel = 'pear.php.net')
$info = $this->_packageInfo ($package, null , $channel);
$this->_config ->set ('php_dir', $this->statedir);
require_once 'PEAR/PackageFile.php';
$pf = &$pkg->fromArray ($info);
* @param string channel name
* @param bool whether to strictly retrieve channel names
* @return PEAR_ChannelFile|PEAR_Error
function &_getChannel ($channel, $noaliases = false )
if ($this->_channelExists ($channel, $noaliases)) {
$chinfo = $this->_channelInfo ($channel, $noaliases);
require_once 'PEAR/ChannelFile.php';
foreach ($ch->getErrors (true ) as $err) {
$message = $err['message'] . "\n";
if ($this->_getChannelFromAlias ($channel) == 'pear.php.net') {
// the registry is not properly set up, so use defaults
require_once 'PEAR/ChannelFile.php';
$pear_channel->setServer ('pear.php.net');
$pear_channel->setAlias ('pear');
$pear_channel->setSummary ('PHP Extension and Application Repository');
$pear_channel->setDefaultPEARProtocols ();
$pear_channel->setBaseURL ('REST1.0', 'http://pear.php.net/rest/');
$pear_channel->setBaseURL ('REST1.1', 'http://pear.php.net/rest/');
$pear_channel->setBaseURL ('REST1.3', 'http://pear.php.net/rest/');
if ($this->_getChannelFromAlias ($channel) == 'pecl.php.net') {
// the registry is not properly set up, so use defaults
require_once 'PEAR/ChannelFile.php';
$pear_channel->setServer ('pecl.php.net');
$pear_channel->setAlias ('pecl');
$pear_channel->setSummary ('PHP Extension Community Library');
$pear_channel->setDefaultPEARProtocols ();
$pear_channel->setBaseURL ('REST1.0', 'http://pecl.php.net/rest/');
$pear_channel->setBaseURL ('REST1.1', 'http://pecl.php.net/rest/');
$pear_channel->setValidationPackage ('PEAR_Validator_PECL', '1.0');
if ($this->_getChannelFromAlias ($channel) == 'doc.php.net') {
// the registry is not properly set up, so use defaults
require_once 'PEAR/ChannelFile.php';
$doc_channel->setServer ('doc.php.net');
$doc_channel->setAlias ('phpdocs');
$doc_channel->setSummary ('PHP Documentation Team');
$doc_channel->setDefaultPEARProtocols ();
$doc_channel->setBaseURL ('REST1.0', 'http://doc.php.net/rest/');
$doc_channel->setBaseURL ('REST1.1', 'http://doc.php.net/rest/');
$doc_channel->setBaseURL ('REST1.3', 'http://doc.php.net/rest/');
if ($this->_getChannelFromAlias ($channel) == '__uri') {
// the registry is not properly set up, so use defaults
require_once 'PEAR/ChannelFile.php';
$private->setName ('__uri');
$private->setDefaultPEARProtocols ();
$private->setBaseURL ('REST1.0', '****');
$private->setSummary ('Pseudo-channel for static packages');
* @param string Package name
* @param string Channel name
$ret = $this->_packageExists ($package, $channel);
* @param string channel name
* @param bool if true, then aliases will be ignored
$ret = $this->_channelExists ($channel, $noaliases);
* @param string channel name mirror is in
* @param string mirror name
$ret = $this->_mirrorExists ($channel, $mirror);
* Determines whether the parameter is an alias of a channel
$ret = $this->_isChannelAlias ($alias);
function packageInfo($package = null , $key = null , $channel = 'pear.php.net')
$ret = $this->_packageInfo ($package, $key, $channel);
* Retrieve a raw array of channel data.
* Do not use this, instead use {@link getChannel()} for normal
* operations. Array structure is undefined in this method
* @param string channel name
* @param bool whether to strictly retrieve information only on non-aliases
* @return array|null|PEAR_Error
function channelInfo($channel = null , $noaliases = false )
$ret = $this->_channelInfo ($channel, $noaliases);
$ret = $this->_getChannelFromAlias ($channel);
$ret = $this->_getAlias ($channel);
$ret = $this->_listPackages ($channel);
$ret = $this->_listAllPackages ();
$ret = $this->_listChannels ();
* Add an installed package to the registry
* @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2package name or object
* that will be passed to {@link addPackage2()}
* @param array package info (parsed by PEAR_Common::infoFrom*() methods)
* @return bool success of saving
$ret = $this->_addPackage ($package, $info);
require_once 'PEAR/PackageFile/v1.php';
$this->_dependencyDB ->uninstallPackage ($pf);
$this->_dependencyDB ->installPackage ($pf);
return $this->addPackage($info['package'], $info);
$ret = $this->_addPackage2 ($info);
$this->_dependencyDB ->uninstallPackage ($info);
$this->_dependencyDB ->installPackage ($info);
* For future expandibility purposes, separate this
* @param PEAR_ChannelFile
if ($channel->getName () == '__uri') {
return $this->addChannel($channel, $lastmodified, true );
* Deletion fails if there are any packages installed from the channel
* @param string|PEAR_ChannelFilechannel name
* @return boolean|PEAR_ErrorTrue on deletion, false if it doesn't exist
$ret = $this->_deleteChannel ($channel);
if ($ret && is_a($this->_config , 'PEAR_Config')) {
* @param PEAR_ChannelFile Channel object
* @param string Last-Modified header from HTTP for caching
* @return boolean|PEAR_ErrorTrue on creation, false if it already exists
function addChannel($channel, $lastmodified = false , $update = false )
if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate ()) {
$ret = $this->_addChannel ($channel, $update, $lastmodified);
if (!$update && $ret && is_a($this->_config , 'PEAR_Config')) {
$this->_rebuildFileMap ();
$p = array ('channel' => $channel, 'package' => $package);
$this->_dependencyDB ->uninstallPackage ($p);
$ret = $this->_updatePackage ($package, $info, $merge);
require_once 'PEAR/PackageFile/v1.php';
$this->_dependencyDB ->uninstallPackage ($pf);
$this->_dependencyDB ->installPackage ($pf);
$ret = $this->_updatePackage2 ($info);
$this->_dependencyDB ->uninstallPackage ($info);
$this->_dependencyDB ->installPackage ($info);
* @param string channel name
* @param bool whether to strictly return raw channels (no aliases)
* @return PEAR_ChannelFile|PEAR_Error
function &getChannel($channel, $noaliases = false )
$ret = &$this->_getChannel ($channel, $noaliases);
* @param string package name
* @param string channel name
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
function &getPackage($package, $channel = 'pear.php.net')
$pf = &$this->_getPackage ($package, $channel);
* Get PEAR_PackageFile_v[1/2] objects representing the contents of
* a dependency group that are installed.
* This is used at uninstall-time
if (isset ($group['package'])) {
if (!isset ($group['package'][0 ])) {
$group['package'] = array ($group['package']);
foreach ($group['package'] as $package) {
$depchannel = isset ($package['channel']) ? $package['channel'] : '__uri';
$p = &$this->getPackage($package['name'], $depchannel);
if (isset ($group['subpackage'])) {
if (!isset ($group['subpackage'][0 ])) {
$group['subpackage'] = array ($group['subpackage']);
foreach ($group['subpackage'] as $package) {
$depchannel = isset ($package['channel']) ? $package['channel'] : '__uri';
$p = &$this->getPackage($package['name'], $depchannel);
// {{{ getChannelValidator()
* @param string channel name
* @return PEAR_Validate|false
$val = $chan->getValidationObject ();
* @param string channel name
* @return array an array of PEAR_ChannelFile objects representing every installed channel
foreach ($this->_listChannels () as $channel) {
$e = &$this->_getChannel ($channel);
* Test whether a file or set of files belongs to a package.
* If an array is passed in
* @param string|arrayfile path, absolute or relative to the pear
* @param string|arrayname of PEAR package or array('package' => name, 'channel' =>
* channel) of a package that will be ignored
* @param string API version - 1.1 will exclude any files belonging to a package
* @param array private recursion variable
* @return array|falsewhich package and channel the file belongs to, or an empty
* string if the file does not belong to an installed package,
* or belongs to the second parameter's package
function checkFileMap($path, $package = false , $api = '1.0', $attrs = false )
require_once 'PEAR/Installer/Role.php';
foreach ($path as $name => $attrs) {
if (isset ($attrs['install-as'])) {
$name = $attrs['install-as'];
// these are not installed
$attrs['baseinstalldir'] = is_array($package) ? $package[1 ] : $package;
if (isset ($attrs['baseinstalldir'])) {
$name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
$pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
$err = $this->_readFileMap ();
$attrs = array ('role' => 'php'); // any old call would be for PHP role only
if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
$l = strlen($this->install_dir );
if (substr($path, 0 , $l) == $this->install_dir ) {
if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
* Force a reload of the filemap
clearstatcache(); // ensure that the next read gets the full, current filemap
* Get the expected API version. Channels API is version 1.1, as it is backwards
* Parse a package name, or validate a parsed package name array
* @param string|arraypass in an array of format
* ['channel' => 'channame',]
* ['version' => 'version',]
* ['group' => 'groupname'])
* [channel://][channame/]pname[-version|-state][/group=groupname]
* @return array|PEAR_Error
// convert to string for error messages
if (!isset ($param['package'])) {
'must contain a valid package name in index "param"',
'package', null , null , $param);
if (!isset ($param['uri'])) {
if (!isset ($param['channel'])) {
$param['channel'] = $defaultchannel;
$param['channel'] = '__uri';
if (isset ($components['scheme'])) {
if ($components['scheme'] == 'http') {
$param = array ('uri' => $param, 'channel' => '__uri');
} elseif ($components['scheme'] != 'channel') {
return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
'be downloaded, not "' . $param . '"', 'invalid', null , null , $param);
if (!isset ($components['path'])) {
'must contain a valid package name in "' . $param . '"',
'package', null , null , $param);
if (isset ($components['host'])) {
// remove the leading "/"
$components['path'] = substr($components['path'], 1 );
if (!isset ($components['scheme'])) {
if (strpos($components['path'], '/') !== false ) {
if ($components['path']{0 } == '/') {
'a package name, it begins with "/" in "' . $param . '"',
'invalid', null , null , $param);
$parts = explode('/', $components['path']);
$components['host'] .= '/' . implode('/', $parts);
$components['path'] = implode('/', $parts);
$components['host'] = $defaultchannel;
if (strpos($components['path'], '/')) {
$parts = explode('/', $components['path']);
$components['host'] .= '/' . implode('/', $parts);
$param['package'] = $components['path'];
'package' => $components['path']
if (isset ($components['host'])) {
$param['channel'] = $components['host'];
if (isset ($components['fragment'])) {
$param['group'] = $components['fragment'];
if (isset ($components['user'])) {
$param['user'] = $components['user'];
if (isset ($components['pass'])) {
$param['pass'] = $components['pass'];
if (isset ($components['query'])) {
parse_str($components['query'], $param['opts']);
$pathinfo = pathinfo($param['package']);
if (isset ($pathinfo['extension']) &&
$param['extension'] = $pathinfo['extension'];
$param['package'] = substr($pathinfo['basename'], 0 ,
strlen($pathinfo['basename']) - 4 );
if (strpos($param['package'], '-')) {
$test = explode('-', $param['package']);
return PEAR::raiseError('parsePackageName(): only one version/state ' .
'delimiter "-" is allowed in "' . $saveparam . '"',
'version', null , null , $param);
list ($param['package'], $param['version']) = $test;
'" in "' . $saveparam . '"', 'channel', null , null , $param);
"retrieve channel " . $param['channel'] . " information",
'registry', null , null , $param);
$param['channel'] = $chan->getName ();
$validate = $chan->getValidationObject ();
$vpackage = $chan->getValidationPackage ();
if (!$validate->validPackageName ($param['package'], $vpackage['_content'])) {
return PEAR::raiseError('parsePackageName(): invalid package name "' .
$param['package'] . '" in "' . $saveparam . '"',
'package', null , null , $param);
if (isset ($param['group'])) {
return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
'" is not a valid group name in "' . $saveparam . '"', 'group', null , null ,
if (isset ($param['state'])) {
return PEAR::raiseError('parsePackageName(): state "' . $param['state']
. '" is not a valid state in "' . $saveparam . '"',
'state', null , null , $param);
if (isset ($param['version'])) {
if (isset ($param['state'])) {
'a version and a stability (state) in "' . $saveparam . '"',
'version/state', null , null , $param);
// check whether version is actually a state
unset ($param['version']);
if (!$validate->validVersion ($param['version'])) {
'" is neither a valid version nor a valid state in "' .
$saveparam . '"', 'version/state', null , null , $param);
'version' => $p->getVersion (),
if (isset ($parsed['uri'])) {
return $channel . '/' . $parsed['package'];
if (isset ($parsed['user'])) {
$upass = $parsed['user'];
if (isset ($parsed['pass'])) {
$upass .= ':' . $parsed['pass'];
$ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
if (isset ($parsed['version']) || isset ($parsed['state'])) {
$ver = isset ($parsed['version']) ? $parsed['version'] : '';
$ver .= isset ($parsed['state']) ? $parsed['state'] : '';
if (isset ($parsed['extension'])) {
$ret .= '.' . $parsed['extension'];
if (isset ($parsed['opts'])) {
foreach ($parsed['opts'] as $name => $value) {
$parsed['opts'][$name] = " $name=$value";
$ret .= implode('&', $parsed['opts']);
if (isset ($parsed['group'])) {
$ret .= '#' . $parsed['group'];
Documentation generated on Wed, 06 Jul 2011 23:31:13 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.
|