675 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			675 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * PEAR_DependencyDB, advanced installed packages dependency database
 | |
|  *
 | |
|  * PHP versions 4 and 5
 | |
|  *
 | |
|  * LICENSE: This source file is subject to version 3.0 of the PHP license
 | |
|  * that is available through the world-wide-web at the following URI:
 | |
|  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 | |
|  * the PHP License and are unable to obtain it through the web, please
 | |
|  * send a note to license@php.net so we can mail you a copy immediately.
 | |
|  *
 | |
|  * @category   pear
 | |
|  * @package    PEAR
 | |
|  * @author     Tomas V. V. Cox <cox@idecnet.com>
 | |
|  * @author     Greg Beaver <cellog@php.net>
 | |
|  * @copyright  1997-2006 The PHP Group
 | |
|  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 | |
|  * @version    CVS: $Id: DependencyDB.php,v 1.30.2.1 2006/05/25 22:00:05 cellog Exp $
 | |
|  * @link       http://pear.php.net/package/PEAR
 | |
|  * @since      File available since Release 1.4.0a1
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Needed for error handling
 | |
|  */
 | |
| require_once 'PEAR.php';
 | |
| require_once 'PEAR/Config.php';
 | |
| 
 | |
| /**
 | |
|  * Track dependency relationships between installed packages
 | |
|  * @category   pear
 | |
|  * @package    PEAR
 | |
|  * @author     Greg Beaver <cellog@php.net>
 | |
|  * @author     Tomas V.V.Cox <cox@idec.net.com>
 | |
|  * @copyright  1997-2006 The PHP Group
 | |
|  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 | |
|  * @version    Release: 1.4.11
 | |
|  * @link       http://pear.php.net/package/PEAR
 | |
|  * @since      Class available since Release 1.4.0a1
 | |
|  */
 | |
| class PEAR_DependencyDB
 | |
| {
 | |
|     // {{{ properties
 | |
| 
 | |
|     /**
 | |
|      * This is initialized by {@link setConfig()}
 | |
|      * @var PEAR_Config
 | |
|      * @access private
 | |
|      */
 | |
|     var $_config;
 | |
|     /**
 | |
|      * This is initialized by {@link setConfig()}
 | |
|      * @var PEAR_Registry
 | |
|      * @access private
 | |
|      */
 | |
|     var $_registry;
 | |
|     /**
 | |
|      * Filename of the dependency DB (usually .depdb)
 | |
|      * @var string
 | |
|      * @access private
 | |
|      */
 | |
|     var $_depdb = false;
 | |
|     /**
 | |
|      * File name of the lockfile (usually .depdblock)
 | |
|      * @var string
 | |
|      * @access private
 | |
|      */
 | |
|     var $_lockfile = false;
 | |
|     /**
 | |
|      * Open file resource for locking the lockfile
 | |
|      * @var resource|false
 | |
|      * @access private
 | |
|      */
 | |
|     var $_lockFp = false;
 | |
|     /**
 | |
|      * API version of this class, used to validate a file on-disk
 | |
|      * @var string
 | |
|      * @access private
 | |
|      */
 | |
|     var $_version = '1.0';
 | |
|     /**
 | |
|      * Cached dependency database file
 | |
|      * @var array|null
 | |
|      * @access private
 | |
|      */
 | |
|     var $_cache;
 | |
| 
 | |
|     // }}}
 | |
|     // {{{ & singleton()
 | |
| 
 | |
|     /**
 | |
|      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
 | |
|      * @param PEAR_Config
 | |
|      * @param string|false full path to the dependency database, or false to use default
 | |
|      * @return PEAR_DependencyDB|PEAR_Error
 | |
|      * @static
 | |
|      */
 | |
|     function &singleton(&$config, $depdb = false)
 | |
|     {
 | |
|         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
 | |
|               [$config->get('php_dir', null, 'pear.php.net')])) {
 | |
|             $a = new PEAR_DependencyDB;
 | |
|             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
 | |
|               [$config->get('php_dir', null, 'pear.php.net')] = &$a;
 | |
|             $a->setConfig($config, $depdb);
 | |
|             if (PEAR::isError($e = $a->assertDepsDB())) {
 | |
|                 return $e;
 | |
|             }
 | |
|         }
 | |
|         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
 | |
|               [$config->get('php_dir', null, 'pear.php.net')];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set up the registry/location of dependency DB
 | |
|      * @param PEAR_Config|false
 | |
|      * @param string|false full path to the dependency database, or false to use default
 | |
|      */
 | |
|     function setConfig(&$config, $depdb = false)
 | |
|     {
 | |
|         if (!$config) {
 | |
|             $this->_config = &PEAR_Config::singleton();
 | |
|         } else {
 | |
|             $this->_config = &$config;
 | |
|         }
 | |
|         $this->_registry = &$this->_config->getRegistry();
 | |
|         if (!$depdb) {
 | |
|             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
 | |
|                 DIRECTORY_SEPARATOR . '.depdb';
 | |
|         } else {
 | |
|             $this->_depdb = $depdb;
 | |
|         }
 | |
|         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
 | |
|     }
 | |
|     // }}}
 | |
| 
 | |
|     function hasWriteAccess()
 | |
|     {
 | |
|         if (!@file_exists($this->_depdb)) {
 | |
|             $dir = $this->_depdb;
 | |
|             while ($dir && $dir != '.') {
 | |
|                 $dir = dirname($dir); // cd ..
 | |
|                 if ($dir != '.' && @file_exists($dir)) {
 | |
|                     if (@is_writeable($dir)) {
 | |
|                         return true;
 | |
|                     } else {
 | |
|                         return false;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
|         return @is_writeable($this->_depdb);
 | |
|     }
 | |
| 
 | |
|     // {{{ assertDepsDB()
 | |
| 
 | |
|     /**
 | |
|      * Create the dependency database, if it doesn't exist.  Error if the database is
 | |
|      * newer than the code reading it.
 | |
|      * @return void|PEAR_Error
 | |
|      */
 | |
|     function assertDepsDB()
 | |
|     {
 | |
|         if (!is_file($this->_depdb)) {
 | |
|             $this->rebuildDB();
 | |
|         } else {
 | |
|             $depdb = $this->_getDepDB();
 | |
|             // Datatype format has been changed, rebuild the Deps DB
 | |
|             if ($depdb['_version'] < $this->_version) {
 | |
|                 $this->rebuildDB();
 | |
|             }
 | |
|             if ($depdb['_version']{0} > $this->_version{0}) {
 | |
|                 return PEAR::raiseError('Dependency database is version ' .
 | |
|                     $depdb['_version'] . ', and we are version ' .
 | |
|                     $this->_version . ', cannot continue');
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get a list of installed packages that depend on this package
 | |
|      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
 | |
|      * @return array|false
 | |
|      */
 | |
|     function getDependentPackages(&$pkg)
 | |
|     {
 | |
|         $data = $this->_getDepDB();
 | |
|         if (is_object($pkg)) {
 | |
|             $channel = strtolower($pkg->getChannel());
 | |
|             $package = strtolower($pkg->getPackage());
 | |
|         } else {
 | |
|             $channel = strtolower($pkg['channel']);
 | |
|             $package = strtolower($pkg['package']);
 | |
|         }
 | |
|         if (isset($data['packages'][$channel][$package])) {
 | |
|             return $data['packages'][$channel][$package];
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get a list of the actual dependencies of installed packages that depend on
 | |
|      * a package.
 | |
|      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
 | |
|      * @return array|false
 | |
|      */
 | |
|     function getDependentPackageDependencies(&$pkg)
 | |
|     {
 | |
|         $data = $this->_getDepDB();
 | |
|         if (is_object($pkg)) {
 | |
|             $channel = strtolower($pkg->getChannel());
 | |
|             $package = strtolower($pkg->getPackage());
 | |
|         } else {
 | |
|             $channel = strtolower($pkg['channel']);
 | |
|             $package = strtolower($pkg['package']);
 | |
|         }
 | |
|         $depend = $this->getDependentPackages($pkg);
 | |
|         if (!$depend) {
 | |
|             return false;
 | |
|         }
 | |
|         $dependencies = array();
 | |
|         foreach ($depend as $info) {
 | |
|             $temp = $this->getDependencies($info);
 | |
|             foreach ($temp as $dep) {
 | |
|                 if (strtolower($dep['dep']['channel']) == strtolower($channel) &&
 | |
|                       strtolower($dep['dep']['name']) == strtolower($package)) {
 | |
|                     $dependencies[$info['channel']][$info['package']][] = $dep;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return $dependencies;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get a list of dependencies of this installed package
 | |
|      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
 | |
|      * @return array|false
 | |
|      */
 | |
|     function getDependencies(&$pkg)
 | |
|     {
 | |
|         if (is_object($pkg)) {
 | |
|             $channel = strtolower($pkg->getChannel());
 | |
|             $package = strtolower($pkg->getPackage());
 | |
|         } else {
 | |
|             $channel = strtolower($pkg['channel']);
 | |
|             $package = strtolower($pkg['package']);
 | |
|         }
 | |
|         $data = $this->_getDepDB();
 | |
|         if (isset($data['dependencies'][$channel][$package])) {
 | |
|             return $data['dependencies'][$channel][$package];
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Determine whether $parent depends on $child, near or deep
 | |
|      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
 | |
|      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
 | |
|      */
 | |
|     function dependsOn($parent, $child)
 | |
|     {
 | |
|         $c = array();
 | |
|         $this->_getDepDB();
 | |
|         return $this->_dependsOn($parent, $child, $c);
 | |
|     }
 | |
|     
 | |
|     function _dependsOn($parent, $child, &$checked)
 | |
|     {
 | |
|         if (is_object($parent)) {
 | |
|             $channel = strtolower($parent->getChannel());
 | |
|             $package = strtolower($parent->getPackage());
 | |
|         } else {
 | |
|             $channel = strtolower($parent['channel']);
 | |
|             $package = strtolower($parent['package']);
 | |
|         }
 | |
|         if (is_object($child)) {
 | |
|             $depchannel = strtolower($child->getChannel());
 | |
|             $deppackage = strtolower($child->getPackage());
 | |
|         } else {
 | |
|             $depchannel = strtolower($child['channel']);
 | |
|             $deppackage = strtolower($child['package']);
 | |
|         }
 | |
|         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
 | |
|             return false; // avoid endless recursion
 | |
|         }
 | |
|         $checked[$channel][$package][$depchannel][$deppackage] = true;
 | |
|         if (!isset($this->_cache['dependencies'][$channel][$package])) {
 | |
|             return false;
 | |
|         }
 | |
|         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
 | |
|             if (isset($info['dep']['uri'])) {
 | |
|                 if (is_object($child)) {
 | |
|                     if ($info['dep']['uri'] == $child->getURI()) {
 | |
|                         return true;
 | |
|                     }
 | |
|                 } elseif (isset($child['uri'])) {
 | |
|                     if ($info['dep']['uri'] == $child['uri']) {
 | |
|                         return true;
 | |
|                     }
 | |
|                 }
 | |
|                 return false;
 | |
|             }
 | |
|             if (strtolower($info['dep']['channel']) == strtolower($depchannel) &&
 | |
|                   strtolower($info['dep']['name']) == strtolower($deppackage)) {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
 | |
|             if (isset($info['dep']['uri'])) {
 | |
|                 if ($this->_dependsOn(array(
 | |
|                         'uri' => $info['dep']['uri'],
 | |
|                         'package' => $info['dep']['name']), $child, $checked)) {
 | |
|                     return true;
 | |
|                 }
 | |
|             } else {
 | |
|                 if ($this->_dependsOn(array(
 | |
|                         'channel' => $info['dep']['channel'],
 | |
|                         'package' => $info['dep']['name']), $child, $checked)) {
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register dependencies of a package that is being installed or upgraded
 | |
|      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
 | |
|      */
 | |
|     function installPackage(&$package)
 | |
|     {
 | |
|         $data = $this->_getDepDB();
 | |
|         unset($this->_cache);
 | |
|         $this->_setPackageDeps($data, $package);
 | |
|         $this->_writeDepDB($data);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Remove dependencies of a package that is being uninstalled, or upgraded.
 | |
|      *
 | |
|      * Upgraded packages first uninstall, then install
 | |
|      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
 | |
|      *        indices 'channel' and 'package'
 | |
|      */
 | |
|     function uninstallPackage(&$pkg)
 | |
|     {
 | |
|         $data = $this->_getDepDB();
 | |
|         unset($this->_cache);
 | |
|         if (is_object($pkg)) {
 | |
|             $channel = strtolower($pkg->getChannel());
 | |
|             $package = strtolower($pkg->getPackage());
 | |
|         } else {
 | |
|             $channel = strtolower($pkg['channel']);
 | |
|             $package = strtolower($pkg['package']);
 | |
|         }
 | |
|         if (!isset($data['dependencies'][$channel][$package])) {
 | |
|             return true;
 | |
|         }
 | |
|         foreach ($data['dependencies'][$channel][$package] as $dep) {
 | |
|             $found = false;
 | |
|             if (isset($dep['dep']['uri'])) {
 | |
|                 $depchannel = '__uri';
 | |
|             } else {
 | |
|                 $depchannel = strtolower($dep['dep']['channel']);
 | |
|             }
 | |
|             if (isset($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
 | |
|                 foreach ($data['packages'][$depchannel][strtolower($dep['dep']['name'])] as
 | |
|                       $i => $info) {
 | |
|                     if ($info['channel'] == $channel &&
 | |
|                           $info['package'] == $package) {
 | |
|                         $found = true;
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             if ($found) {
 | |
|                 unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])][$i]);
 | |
|                 if (!count($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
 | |
|                     unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
 | |
|                     if (!count($data['packages'][$depchannel])) {
 | |
|                         unset($data['packages'][$depchannel]);
 | |
|                     }
 | |
|                 } else {
 | |
|                     $data['packages'][$depchannel][strtolower($dep['dep']['name'])] =
 | |
|                         array_values(
 | |
|                             $data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         unset($data['dependencies'][$channel][$package]);
 | |
|         if (!count($data['dependencies'][$channel])) {
 | |
|             unset($data['dependencies'][$channel]);
 | |
|         }
 | |
|         if (!count($data['dependencies'])) {
 | |
|             unset($data['dependencies']);
 | |
|         }
 | |
|         if (!count($data['packages'])) {
 | |
|             unset($data['packages']);
 | |
|         }
 | |
|         $this->_writeDepDB($data);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Rebuild the dependency DB by reading registry entries.
 | |
|      * @return true|PEAR_Error
 | |
|      */
 | |
|     function rebuildDB()
 | |
|     {
 | |
|         $depdb = array('_version' => $this->_version);
 | |
|         if (!$this->hasWriteAccess()) {
 | |
|             // allow startup for read-only with older Registry
 | |
|             return $depdb;
 | |
|         }
 | |
|         $packages = $this->_registry->listAllPackages();
 | |
|         foreach ($packages as $channel => $ps) {
 | |
|             foreach ($ps as $package) {
 | |
|                 $package = $this->_registry->getPackage($package, $channel);
 | |
|                 $this->_setPackageDeps($depdb, $package);
 | |
|             }
 | |
|         }
 | |
|         $error = $this->_writeDepDB($depdb);
 | |
|         if (PEAR::isError($error)) {
 | |
|             return $error;
 | |
|         }
 | |
|         $this->_cache = $depdb;
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register usage of the dependency DB to prevent race conditions
 | |
|      * @param int one of the LOCK_* constants
 | |
|      * @return true|PEAR_Error
 | |
|      * @access private
 | |
|      */
 | |
|     function _lock($mode = LOCK_EX)
 | |
|     {
 | |
|         if (!eregi('Windows 9', php_uname())) {
 | |
|             if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
 | |
|                 // XXX does not check type of lock (LOCK_SH/LOCK_EX)
 | |
|                 return true;
 | |
|             }
 | |
|             $open_mode = 'w';
 | |
|             // XXX People reported problems with LOCK_SH and 'w'
 | |
|             if ($mode === LOCK_SH) {
 | |
|                 if (@!is_file($this->_lockfile)) {
 | |
|                     touch($this->_lockfile);
 | |
|                 }
 | |
|                 $open_mode = 'r';
 | |
|             }
 | |
| 
 | |
|             if (!is_resource($this->_lockFp)) {
 | |
|                 $this->_lockFp = @fopen($this->_lockfile, $open_mode);
 | |
|             }
 | |
|             if (!is_resource($this->_lockFp)) {
 | |
|                 return PEAR::raiseError("could not create Dependency lock file" .
 | |
|                                          (isset($php_errormsg) ? ": " . $php_errormsg : ""));
 | |
|             }
 | |
|             if (!(int)flock($this->_lockFp, $mode)) {
 | |
|                 switch ($mode) {
 | |
|                     case LOCK_SH: $str = 'shared';    break;
 | |
|                     case LOCK_EX: $str = 'exclusive'; break;
 | |
|                     case LOCK_UN: $str = 'unlock';    break;
 | |
|                     default:      $str = 'unknown';   break;
 | |
|                 }
 | |
|                 return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
 | |
|             }
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Release usage of dependency DB
 | |
|      * @return true|PEAR_Error
 | |
|      * @access private
 | |
|      */
 | |
|     function _unlock()
 | |
|     {
 | |
|         $ret = $this->_lock(LOCK_UN);
 | |
|         if (is_resource($this->_lockFp)) {
 | |
|             fclose($this->_lockFp);
 | |
|         }
 | |
|         $this->_lockFp = null;
 | |
|         return $ret;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Load the dependency database from disk, or return the cache
 | |
|      * @return array|PEAR_Error
 | |
|      */
 | |
|     function _getDepDB()
 | |
|     {
 | |
|         if (!$this->hasWriteAccess()) {
 | |
|             return array('_version' => $this->_version);
 | |
|         }
 | |
|         if (isset($this->_cache)) {
 | |
|             return $this->_cache;
 | |
|         }
 | |
|         if (!$fp = fopen($this->_depdb, 'r')) {
 | |
|             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
 | |
|             return $err;
 | |
|         }
 | |
|         $rt = get_magic_quotes_runtime();
 | |
|         set_magic_quotes_runtime(0);
 | |
|         clearstatcache();
 | |
|         if (function_exists('file_get_contents')) {
 | |
|             fclose($fp);
 | |
|             $data = unserialize(file_get_contents($this->_depdb));
 | |
|         } else {
 | |
|             $data = unserialize(fread($fp, filesize($this->_depdb)));
 | |
|             fclose($fp);
 | |
|         }
 | |
|         set_magic_quotes_runtime($rt);
 | |
|         $this->_cache = $data;
 | |
|         return $data;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Write out the dependency database to disk
 | |
|      * @param array the database
 | |
|      * @return true|PEAR_Error
 | |
|      * @access private
 | |
|      */
 | |
|     function _writeDepDB(&$deps)
 | |
|     {
 | |
|         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
 | |
|             return $e;
 | |
|         }
 | |
|         if (!$fp = fopen($this->_depdb, 'wb')) {
 | |
|             $this->_unlock();
 | |
|             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
 | |
|         }
 | |
|         $rt = get_magic_quotes_runtime();
 | |
|         set_magic_quotes_runtime(0);
 | |
|         fwrite($fp, serialize($deps));
 | |
|         set_magic_quotes_runtime($rt);
 | |
|         fclose($fp);
 | |
|         $this->_unlock();
 | |
|         $this->_cache = $deps;
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register all dependencies from a package in the dependencies database, in essence
 | |
|      * "installing" the package's dependency information
 | |
|      * @param array the database
 | |
|      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
 | |
|      * @access private
 | |
|      */
 | |
|     function _setPackageDeps(&$data, &$pkg)
 | |
|     {
 | |
|         $pkg->setConfig($this->_config);
 | |
|         if ($pkg->getPackagexmlVersion() == '1.0') {
 | |
|             $gen = &$pkg->getDefaultGenerator();
 | |
|             $deps = $gen->dependenciesToV2();
 | |
|         } else {
 | |
|             $deps = $pkg->getDeps(true);
 | |
|         }
 | |
|         if (!$deps) {
 | |
|             return;
 | |
|         }
 | |
|         $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())]
 | |
|             = array();
 | |
|         if (isset($deps['required']['package'])) {
 | |
|             if (!isset($deps['required']['package'][0])) {
 | |
|                 $deps['required']['package'] = array($deps['required']['package']);
 | |
|             }
 | |
|             foreach ($deps['required']['package'] as $dep) {
 | |
|                 $this->_registerDep($data, $pkg, $dep, 'required');
 | |
|             }
 | |
|         }
 | |
|         if (isset($deps['optional']['package'])) {
 | |
|             if (!isset($deps['optional']['package'][0])) {
 | |
|                 $deps['optional']['package'] = array($deps['optional']['package']);
 | |
|             }
 | |
|             foreach ($deps['optional']['package'] as $dep) {
 | |
|                 $this->_registerDep($data, $pkg, $dep, 'optional');
 | |
|             }
 | |
|         }
 | |
|         if (isset($deps['required']['subpackage'])) {
 | |
|             if (!isset($deps['required']['subpackage'][0])) {
 | |
|                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
 | |
|             }
 | |
|             foreach ($deps['required']['subpackage'] as $dep) {
 | |
|                 $this->_registerDep($data, $pkg, $dep, 'required');
 | |
|             }
 | |
|         }
 | |
|         if (isset($deps['optional']['subpackage'])) {
 | |
|             if (!isset($deps['optional']['subpackage'][0])) {
 | |
|                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
 | |
|             }
 | |
|             foreach ($deps['optional']['subpackage'] as $dep) {
 | |
|                 $this->_registerDep($data, $pkg, $dep, 'optional');
 | |
|             }
 | |
|         }
 | |
|         if (isset($deps['group'])) {
 | |
|             if (!isset($deps['group'][0])) {
 | |
|                 $deps['group'] = array($deps['group']);
 | |
|             }
 | |
|             foreach ($deps['group'] as $group) {
 | |
|                 if (isset($group['package'])) {
 | |
|                     if (!isset($group['package'][0])) {
 | |
|                         $group['package'] = array($group['package']);
 | |
|                     }
 | |
|                     foreach ($group['package'] as $dep) {
 | |
|                         $this->_registerDep($data, $pkg, $dep, 'optional',
 | |
|                             $group['attribs']['name']);
 | |
|                     }
 | |
|                 }
 | |
|                 if (isset($group['subpackage'])) {
 | |
|                     if (!isset($group['subpackage'][0])) {
 | |
|                         $group['subpackage'] = array($group['subpackage']);
 | |
|                     }
 | |
|                     foreach ($group['subpackage'] as $dep) {
 | |
|                         $this->_registerDep($data, $pkg, $dep, 'optional',
 | |
|                             $group['attribs']['name']);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         if ($data['dependencies'][strtolower($pkg->getChannel())]
 | |
|               [strtolower($pkg->getPackage())] == array()) {
 | |
|             unset($data['dependencies'][strtolower($pkg->getChannel())]
 | |
|               [strtolower($pkg->getPackage())]);
 | |
|             if (!count($data['dependencies'][strtolower($pkg->getChannel())])) {
 | |
|                 unset($data['dependencies'][strtolower($pkg->getChannel())]);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param array the database
 | |
|      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
 | |
|      * @param array the specific dependency
 | |
|      * @param required|optional whether this is a required or an optional dep
 | |
|      * @param string|false dependency group this dependency is from, or false for ordinary dep
 | |
|      */
 | |
|     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
 | |
|     {
 | |
|         $info = array(
 | |
|             'dep' => $dep,
 | |
|             'type' => $type,
 | |
|             'group' => $group);
 | |
| 
 | |
|         if (isset($dep['channel'])) {
 | |
|             $depchannel = $dep['channel'];
 | |
|         } else {
 | |
|             $depchannel = '__uri';
 | |
|         }
 | |
|         $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())][]
 | |
|             = $info;
 | |
|         if (isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) {
 | |
|             $found = false;
 | |
|             foreach ($data['packages'][strtolower($depchannel)][strtolower($dep['name'])]
 | |
|                   as $i => $p) {
 | |
|                 if ($p['channel'] == strtolower($pkg->getChannel()) &&
 | |
|                       $p['package'] == strtolower($pkg->getPackage())) {
 | |
|                     $found = true;
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|             if (!$found) {
 | |
|                 $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
 | |
|                     = array('channel' => strtolower($pkg->getChannel()),
 | |
|                             'package' => strtolower($pkg->getPackage()));
 | |
|             }
 | |
|         } else {
 | |
|             $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
 | |
|                 = array('channel' => strtolower($pkg->getChannel()),
 | |
|                         'package' => strtolower($pkg->getPackage()));
 | |
|         }
 | |
|     }
 | |
| }
 | |
| ?>
 |