home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / tmp / PEAR-1.7.1 / PEAR / DependencyDB.php < prev    next >
Encoding:
PHP Script  |  2008-02-15  |  25.1 KB  |  713 lines

  1. <?php
  2. /**
  3.  * PEAR_DependencyDB, advanced installed packages dependency database
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   pear
  14.  * @package    PEAR
  15.  * @author     Tomas V. V. Cox <cox@idecnet.com>
  16.  * @author     Greg Beaver <cellog@php.net>
  17.  * @copyright  1997-2008 The PHP Group
  18.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  19.  * @version    CVS: $Id: DependencyDB.php,v 1.37 2008/01/03 20:26:35 cellog Exp $
  20.  * @link       http://pear.php.net/package/PEAR
  21.  * @since      File available since Release 1.4.0a1
  22.  */
  23.  
  24. /**
  25.  * Needed for error handling
  26.  */
  27. require_once 'PEAR.php';
  28. require_once 'PEAR/Config.php';
  29.  
  30. $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
  31. /**
  32.  * Track dependency relationships between installed packages
  33.  * @category   pear
  34.  * @package    PEAR
  35.  * @author     Greg Beaver <cellog@php.net>
  36.  * @author     Tomas V.V.Cox <cox@idec.net.com>
  37.  * @copyright  1997-2008 The PHP Group
  38.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  39.  * @version    Release: 1.7.1
  40.  * @link       http://pear.php.net/package/PEAR
  41.  * @since      Class available since Release 1.4.0a1
  42.  */
  43. class PEAR_DependencyDB
  44. {
  45.     // {{{ properties
  46.  
  47.     /**
  48.      * This is initialized by {@link setConfig()}
  49.      * @var PEAR_Config
  50.      * @access private
  51.      */
  52.     var $_config;
  53.     /**
  54.      * This is initialized by {@link setConfig()}
  55.      * @var PEAR_Registry
  56.      * @access private
  57.      */
  58.     var $_registry;
  59.     /**
  60.      * Filename of the dependency DB (usually .depdb)
  61.      * @var string
  62.      * @access private
  63.      */
  64.     var $_depdb = false;
  65.     /**
  66.      * File name of the lockfile (usually .depdblock)
  67.      * @var string
  68.      * @access private
  69.      */
  70.     var $_lockfile = false;
  71.     /**
  72.      * Open file resource for locking the lockfile
  73.      * @var resource|false
  74.      * @access private
  75.      */
  76.     var $_lockFp = false;
  77.     /**
  78.      * API version of this class, used to validate a file on-disk
  79.      * @var string
  80.      * @access private
  81.      */
  82.     var $_version = '1.0';
  83.     /**
  84.      * Cached dependency database file
  85.      * @var array|null
  86.      * @access private
  87.      */
  88.     var $_cache;
  89.  
  90.     // }}}
  91.     // {{{ & singleton()
  92.  
  93.     /**
  94.      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
  95.      * @param PEAR_Config
  96.      * @param string|false full path to the dependency database, or false to use default
  97.      * @return PEAR_DependencyDB|PEAR_Error
  98.      * @static
  99.      */
  100.     function &singleton(&$config, $depdb = false)
  101.     {
  102.         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  103.               [$config->get('php_dir', null, 'pear.php.net')])) {
  104.             $a = new PEAR_DependencyDB;
  105.             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  106.               [$config->get('php_dir', null, 'pear.php.net')] = &$a;
  107.             $a->setConfig($config, $depdb);
  108.             if (PEAR::isError($e = $a->assertDepsDB())) {
  109.                 return $e;
  110.             }
  111.         }
  112.         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  113.               [$config->get('php_dir', null, 'pear.php.net')];
  114.     }
  115.  
  116.     /**
  117.      * Set up the registry/location of dependency DB
  118.      * @param PEAR_Config|false
  119.      * @param string|false full path to the dependency database, or false to use default
  120.      */
  121.     function setConfig(&$config, $depdb = false)
  122.     {
  123.         if (!$config) {
  124.             $this->_config = &PEAR_Config::singleton();
  125.         } else {
  126.             $this->_config = &$config;
  127.         }
  128.         $this->_registry = &$this->_config->getRegistry();
  129.         if (!$depdb) {
  130.             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
  131.                 DIRECTORY_SEPARATOR . '.depdb';
  132.         } else {
  133.             $this->_depdb = $depdb;
  134.         }
  135.         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
  136.     }
  137.     // }}}
  138.  
  139.     function hasWriteAccess()
  140.     {
  141.         if (!file_exists($this->_depdb)) {
  142.             $dir = $this->_depdb;
  143.             while ($dir && $dir != '.') {
  144.                 $dir = dirname($dir); // cd ..
  145.                 if ($dir != '.' && file_exists($dir)) {
  146.                     if (is_writeable($dir)) {
  147.                         return true;
  148.                     } else {
  149.                         return false;
  150.                     }
  151.                 }
  152.             }
  153.             return false;
  154.         }
  155.         return is_writeable($this->_depdb);
  156.     }
  157.  
  158.     // {{{ assertDepsDB()
  159.  
  160.     /**
  161.      * Create the dependency database, if it doesn't exist.  Error if the database is
  162.      * newer than the code reading it.
  163.      * @return void|PEAR_Error
  164.      */
  165.     function assertDepsDB()
  166.     {
  167.         if (!is_file($this->_depdb)) {
  168.             $this->rebuildDB();
  169.         } else {
  170.             $depdb = $this->_getDepDB();
  171.             // Datatype format has been changed, rebuild the Deps DB
  172.             if ($depdb['_version'] < $this->_version) {
  173.                 $this->rebuildDB();
  174.             }
  175.             if ($depdb['_version']{0} > $this->_version{0}) {
  176.                 return PEAR::raiseError('Dependency database is version ' .
  177.                     $depdb['_version'] . ', and we are version ' .
  178.                     $this->_version . ', cannot continue');
  179.             }
  180.         }
  181.     }
  182.  
  183.     /**
  184.      * Get a list of installed packages that depend on this package
  185.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  186.      * @return array|false
  187.      */
  188.     function getDependentPackages(&$pkg)
  189.     {
  190.         $data = $this->_getDepDB();
  191.         if (is_object($pkg)) {
  192.             $channel = strtolower($pkg->getChannel());
  193.             $package = strtolower($pkg->getPackage());
  194.         } else {
  195.             $channel = strtolower($pkg['channel']);
  196.             $package = strtolower($pkg['package']);
  197.         }
  198.         if (isset($data['packages'][$channel][$package])) {
  199.             return $data['packages'][$channel][$package];
  200.         }
  201.         return false;
  202.     }
  203.  
  204.     /**
  205.      * Get a list of the actual dependencies of installed packages that depend on
  206.      * a package.
  207.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  208.      * @return array|false
  209.      */
  210.     function getDependentPackageDependencies(&$pkg)
  211.     {
  212.         $data = $this->_getDepDB();
  213.         if (is_object($pkg)) {
  214.             $channel = strtolower($pkg->getChannel());
  215.             $package = strtolower($pkg->getPackage());
  216.         } else {
  217.             $channel = strtolower($pkg['channel']);
  218.             $package = strtolower($pkg['package']);
  219.         }
  220.         $depend = $this->getDependentPackages($pkg);
  221.         if (!$depend) {
  222.             return false;
  223.         }
  224.         $dependencies = array();
  225.         foreach ($depend as $info) {
  226.             $temp = $this->getDependencies($info);
  227.             foreach ($temp as $dep) {
  228.                 if (strtolower($dep['dep']['channel']) == strtolower($channel) &&
  229.                       strtolower($dep['dep']['name']) == strtolower($package)) {
  230.                     if (!isset($dependencies[$info['channel']])) {
  231.                         $dependencies[$info['channel']] = array();
  232.                     }
  233.                     if (!isset($dependencies[$info['channel']][$info['package']])) {
  234.                         $dependencies[$info['channel']][$info['package']] = array();
  235.                     }
  236.                     $dependencies[$info['channel']][$info['package']][] = $dep;
  237.                 }
  238.             }
  239.         }
  240.         return $dependencies;
  241.     }
  242.  
  243.     /**
  244.      * Get a list of dependencies of this installed package
  245.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  246.      * @return array|false
  247.      */
  248.     function getDependencies(&$pkg)
  249.     {
  250.         if (is_object($pkg)) {
  251.             $channel = strtolower($pkg->getChannel());
  252.             $package = strtolower($pkg->getPackage());
  253.         } else {
  254.             $channel = strtolower($pkg['channel']);
  255.             $package = strtolower($pkg['package']);
  256.         }
  257.         $data = $this->_getDepDB();
  258.         if (isset($data['dependencies'][$channel][$package])) {
  259.             return $data['dependencies'][$channel][$package];
  260.         }
  261.         return false;
  262.     }
  263.  
  264.     /**
  265.      * Determine whether $parent depends on $child, near or deep
  266.      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
  267.      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
  268.      */
  269.     function dependsOn($parent, $child)
  270.     {
  271.         $c = array();
  272.         $this->_getDepDB();
  273.         return $this->_dependsOn($parent, $child, $c);
  274.     }
  275.     
  276.     function _dependsOn($parent, $child, &$checked)
  277.     {
  278.         if (is_object($parent)) {
  279.             $channel = strtolower($parent->getChannel());
  280.             $package = strtolower($parent->getPackage());
  281.         } else {
  282.             $channel = strtolower($parent['channel']);
  283.             $package = strtolower($parent['package']);
  284.         }
  285.         if (is_object($child)) {
  286.             $depchannel = strtolower($child->getChannel());
  287.             $deppackage = strtolower($child->getPackage());
  288.         } else {
  289.             $depchannel = strtolower($child['channel']);
  290.             $deppackage = strtolower($child['package']);
  291.         }
  292.         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
  293.             return false; // avoid endless recursion
  294.         }
  295.         $checked[$channel][$package][$depchannel][$deppackage] = true;
  296.         if (!isset($this->_cache['dependencies'][$channel][$package])) {
  297.             return false;
  298.         }
  299.         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
  300.             if (isset($info['dep']['uri'])) {
  301.                 if (is_object($child)) {
  302.                     if ($info['dep']['uri'] == $child->getURI()) {
  303.                         return true;
  304.                     }
  305.                 } elseif (isset($child['uri'])) {
  306.                     if ($info['dep']['uri'] == $child['uri']) {
  307.                         return true;
  308.                     }
  309.                 }
  310.                 return false;
  311.             }
  312.             if (strtolower($info['dep']['channel']) == strtolower($depchannel) &&
  313.                   strtolower($info['dep']['name']) == strtolower($deppackage)) {
  314.                 return true;
  315.             }
  316.         }
  317.         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
  318.             if (isset($info['dep']['uri'])) {
  319.                 if ($this->_dependsOn(array(
  320.                         'uri' => $info['dep']['uri'],
  321.                         'package' => $info['dep']['name']), $child, $checked)) {
  322.                     return true;
  323.                 }
  324.             } else {
  325.                 if ($this->_dependsOn(array(
  326.                         'channel' => $info['dep']['channel'],
  327.                         'package' => $info['dep']['name']), $child, $checked)) {
  328.                     return true;
  329.                 }
  330.             }
  331.         }
  332.         return false;
  333.     }
  334.  
  335.     /**
  336.      * Register dependencies of a package that is being installed or upgraded
  337.      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
  338.      */
  339.     function installPackage(&$package)
  340.     {
  341.         $data = $this->_getDepDB();
  342.         unset($this->_cache);
  343.         $this->_setPackageDeps($data, $package);
  344.         $this->_writeDepDB($data);
  345.     }
  346.  
  347.     /**
  348.      * Remove dependencies of a package that is being uninstalled, or upgraded.
  349.      *
  350.      * Upgraded packages first uninstall, then install
  351.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
  352.      *        indices 'channel' and 'package'
  353.      */
  354.     function uninstallPackage(&$pkg)
  355.     {
  356.         $data = $this->_getDepDB();
  357.         unset($this->_cache);
  358.         if (is_object($pkg)) {
  359.             $channel = strtolower($pkg->getChannel());
  360.             $package = strtolower($pkg->getPackage());
  361.         } else {
  362.             $channel = strtolower($pkg['channel']);
  363.             $package = strtolower($pkg['package']);
  364.         }
  365.         if (!isset($data['dependencies'][$channel][$package])) {
  366.             return true;
  367.         }
  368.         foreach ($data['dependencies'][$channel][$package] as $dep) {
  369.             $found = false;
  370.             if (isset($dep['dep']['uri'])) {
  371.                 $depchannel = '__uri';
  372.             } else {
  373.                 $depchannel = strtolower($dep['dep']['channel']);
  374.             }
  375.             if (isset($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
  376.                 foreach ($data['packages'][$depchannel][strtolower($dep['dep']['name'])] as
  377.                       $i => $info) {
  378.                     if ($info['channel'] == $channel &&
  379.                           $info['package'] == $package) {
  380.                         $found = true;
  381.                         break;
  382.                     }
  383.                 }
  384.             }
  385.             if ($found) {
  386.                 unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])][$i]);
  387.                 if (!count($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
  388.                     unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
  389.                     if (!count($data['packages'][$depchannel])) {
  390.                         unset($data['packages'][$depchannel]);
  391.                     }
  392.                 } else {
  393.                     $data['packages'][$depchannel][strtolower($dep['dep']['name'])] =
  394.                         array_values(
  395.                             $data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
  396.                 }
  397.             }
  398.         }
  399.         unset($data['dependencies'][$channel][$package]);
  400.         if (!count($data['dependencies'][$channel])) {
  401.             unset($data['dependencies'][$channel]);
  402.         }
  403.         if (!count($data['dependencies'])) {
  404.             unset($data['dependencies']);
  405.         }
  406.         if (!count($data['packages'])) {
  407.             unset($data['packages']);
  408.         }
  409.         $this->_writeDepDB($data);
  410.     }
  411.  
  412.     /**
  413.      * Rebuild the dependency DB by reading registry entries.
  414.      * @return true|PEAR_Error
  415.      */
  416.     function rebuildDB()
  417.     {
  418.         $depdb = array('_version' => $this->_version);
  419.         if (!$this->hasWriteAccess()) {
  420.             // allow startup for read-only with older Registry
  421.             return $depdb;
  422.         }
  423.         $packages = $this->_registry->listAllPackages();
  424.         if (PEAR::isError($packages)) {
  425.             return $packages;
  426.         }
  427.         foreach ($packages as $channel => $ps) {
  428.             foreach ($ps as $package) {
  429.                 $package = $this->_registry->getPackage($package, $channel);
  430.                 if (PEAR::isError($package)) {
  431.                     return $package;
  432.                 }
  433.                 $this->_setPackageDeps($depdb, $package);
  434.             }
  435.         }
  436.         $error = $this->_writeDepDB($depdb);
  437.         if (PEAR::isError($error)) {
  438.             return $error;
  439.         }
  440.         $this->_cache = $depdb;
  441.         return true;
  442.     }
  443.  
  444.     /**
  445.      * Register usage of the dependency DB to prevent race conditions
  446.      * @param int one of the LOCK_* constants
  447.      * @return true|PEAR_Error
  448.      * @access private
  449.      */
  450.     function _lock($mode = LOCK_EX)
  451.     {
  452.         if (!eregi('Windows 9', php_uname())) {
  453.             if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
  454.                 // XXX does not check type of lock (LOCK_SH/LOCK_EX)
  455.                 return true;
  456.             }
  457.             $open_mode = 'w';
  458.             // XXX People reported problems with LOCK_SH and 'w'
  459.             if ($mode === LOCK_SH) {
  460.                 if (!file_exists($this->_lockfile)) {
  461.                     touch($this->_lockfile);
  462.                 } elseif (!is_file($this->_lockfile)) {
  463.                     return PEAR::raiseError('could not create Dependency lock file, ' .
  464.                         'it exists and is not a regular file');
  465.                 }
  466.                 $open_mode = 'r';
  467.             }
  468.  
  469.             if (!is_resource($this->_lockFp)) {
  470.                 $this->_lockFp = @fopen($this->_lockfile, $open_mode);
  471.             }
  472.             if (!is_resource($this->_lockFp)) {
  473.                 return PEAR::raiseError("could not create Dependency lock file" .
  474.                                          (isset($php_errormsg) ? ": " . $php_errormsg : ""));
  475.             }
  476.             if (!(int)flock($this->_lockFp, $mode)) {
  477.                 switch ($mode) {
  478.                     case LOCK_SH: $str = 'shared';    break;
  479.                     case LOCK_EX: $str = 'exclusive'; break;
  480.                     case LOCK_UN: $str = 'unlock';    break;
  481.                     default:      $str = 'unknown';   break;
  482.                 }
  483.                 return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
  484.             }
  485.         }
  486.         return true;
  487.     }
  488.  
  489.     /**
  490.      * Release usage of dependency DB
  491.      * @return true|PEAR_Error
  492.      * @access private
  493.      */
  494.     function _unlock()
  495.     {
  496.         $ret = $this->_lock(LOCK_UN);
  497.         if (is_resource($this->_lockFp)) {
  498.             fclose($this->_lockFp);
  499.         }
  500.         $this->_lockFp = null;
  501.         return $ret;
  502.     }
  503.  
  504.     /**
  505.      * Load the dependency database from disk, or return the cache
  506.      * @return array|PEAR_Error
  507.      */
  508.     function _getDepDB()
  509.     {
  510.         if (!$this->hasWriteAccess()) {
  511.             return array('_version' => $this->_version);
  512.         }
  513.         if (isset($this->_cache)) {
  514.             return $this->_cache;
  515.         }
  516.         if (!$fp = fopen($this->_depdb, 'r')) {
  517.             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
  518.             return $err;
  519.         }
  520.         $rt = get_magic_quotes_runtime();
  521.         set_magic_quotes_runtime(0);
  522.         clearstatcache();
  523.         fclose($fp);
  524.         $data = unserialize(file_get_contents($this->_depdb));
  525.         set_magic_quotes_runtime($rt);
  526.         $this->_cache = $data;
  527.         return $data;
  528.     }
  529.  
  530.     /**
  531.      * Write out the dependency database to disk
  532.      * @param array the database
  533.      * @return true|PEAR_Error
  534.      * @access private
  535.      */
  536.     function _writeDepDB(&$deps)
  537.     {
  538.         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
  539.             return $e;
  540.         }
  541.         if (!$fp = fopen($this->_depdb, 'wb')) {
  542.             $this->_unlock();
  543.             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
  544.         }
  545.         $rt = get_magic_quotes_runtime();
  546.         set_magic_quotes_runtime(0);
  547.         fwrite($fp, serialize($deps));
  548.         set_magic_quotes_runtime($rt);
  549.         fclose($fp);
  550.         $this->_unlock();
  551.         $this->_cache = $deps;
  552.         return true;
  553.     }
  554.  
  555.     /**
  556.      * Register all dependencies from a package in the dependencies database, in essence
  557.      * "installing" the package's dependency information
  558.      * @param array the database
  559.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  560.      * @access private
  561.      */
  562.     function _setPackageDeps(&$data, &$pkg)
  563.     {
  564.         $pkg->setConfig($this->_config);
  565.         if ($pkg->getPackagexmlVersion() == '1.0') {
  566.             $gen = &$pkg->getDefaultGenerator();
  567.             $deps = $gen->dependenciesToV2();
  568.         } else {
  569.             $deps = $pkg->getDeps(true);
  570.         }
  571.         if (!$deps) {
  572.             return;
  573.         }
  574.         if (!is_array($data)) {
  575.             $data = array();
  576.         }
  577.         if (!isset($data['dependencies'])) {
  578.             $data['dependencies'] = array();
  579.         }
  580.         if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) {
  581.             $data['dependencies'][strtolower($pkg->getChannel())] = array();
  582.         }
  583.         $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())]
  584.             = array();
  585.         if (isset($deps['required']['package'])) {
  586.             if (!isset($deps['required']['package'][0])) {
  587.                 $deps['required']['package'] = array($deps['required']['package']);
  588.             }
  589.             foreach ($deps['required']['package'] as $dep) {
  590.                 $this->_registerDep($data, $pkg, $dep, 'required');
  591.             }
  592.         }
  593.         if (isset($deps['optional']['package'])) {
  594.             if (!isset($deps['optional']['package'][0])) {
  595.                 $deps['optional']['package'] = array($deps['optional']['package']);
  596.             }
  597.             foreach ($deps['optional']['package'] as $dep) {
  598.                 $this->_registerDep($data, $pkg, $dep, 'optional');
  599.             }
  600.         }
  601.         if (isset($deps['required']['subpackage'])) {
  602.             if (!isset($deps['required']['subpackage'][0])) {
  603.                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
  604.             }
  605.             foreach ($deps['required']['subpackage'] as $dep) {
  606.                 $this->_registerDep($data, $pkg, $dep, 'required');
  607.             }
  608.         }
  609.         if (isset($deps['optional']['subpackage'])) {
  610.             if (!isset($deps['optional']['subpackage'][0])) {
  611.                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
  612.             }
  613.             foreach ($deps['optional']['subpackage'] as $dep) {
  614.                 $this->_registerDep($data, $pkg, $dep, 'optional');
  615.             }
  616.         }
  617.         if (isset($deps['group'])) {
  618.             if (!isset($deps['group'][0])) {
  619.                 $deps['group'] = array($deps['group']);
  620.             }
  621.             foreach ($deps['group'] as $group) {
  622.                 if (isset($group['package'])) {
  623.                     if (!isset($group['package'][0])) {
  624.                         $group['package'] = array($group['package']);
  625.                     }
  626.                     foreach ($group['package'] as $dep) {
  627.                         $this->_registerDep($data, $pkg, $dep, 'optional',
  628.                             $group['attribs']['name']);
  629.                     }
  630.                 }
  631.                 if (isset($group['subpackage'])) {
  632.                     if (!isset($group['subpackage'][0])) {
  633.                         $group['subpackage'] = array($group['subpackage']);
  634.                     }
  635.                     foreach ($group['subpackage'] as $dep) {
  636.                         $this->_registerDep($data, $pkg, $dep, 'optional',
  637.                             $group['attribs']['name']);
  638.                     }
  639.                 }
  640.             }
  641.         }
  642.         if ($data['dependencies'][strtolower($pkg->getChannel())]
  643.               [strtolower($pkg->getPackage())] == array()) {
  644.             unset($data['dependencies'][strtolower($pkg->getChannel())]
  645.               [strtolower($pkg->getPackage())]);
  646.             if (!count($data['dependencies'][strtolower($pkg->getChannel())])) {
  647.                 unset($data['dependencies'][strtolower($pkg->getChannel())]);
  648.             }
  649.         }
  650.     }
  651.  
  652.     /**
  653.      * @param array the database
  654.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  655.      * @param array the specific dependency
  656.      * @param required|optional whether this is a required or an optional dep
  657.      * @param string|false dependency group this dependency is from, or false for ordinary dep
  658.      */
  659.     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
  660.     {
  661.         $info = array(
  662.             'dep' => $dep,
  663.             'type' => $type,
  664.             'group' => $group);
  665.  
  666.         if (isset($dep['channel'])) {
  667.             $depchannel = $dep['channel'];
  668.         } else {
  669.             $depchannel = '__uri';
  670.         }
  671.         if (!isset($data['dependencies'])) {
  672.             $data['dependencies'] = array();
  673.         }
  674.         if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) {
  675.             $data['dependencies'][strtolower($pkg->getChannel())] = array();
  676.         }
  677.         if (!isset($data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())])) {
  678.             $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())] = array();
  679.         }
  680.         $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())][]
  681.             = $info;
  682.         if (isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) {
  683.             $found = false;
  684.             foreach ($data['packages'][strtolower($depchannel)][strtolower($dep['name'])]
  685.                   as $i => $p) {
  686.                 if ($p['channel'] == strtolower($pkg->getChannel()) &&
  687.                       $p['package'] == strtolower($pkg->getPackage())) {
  688.                     $found = true;
  689.                     break;
  690.                 }
  691.             }
  692.             if (!$found) {
  693.                 $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
  694.                     = array('channel' => strtolower($pkg->getChannel()),
  695.                             'package' => strtolower($pkg->getPackage()));
  696.             }
  697.         } else {
  698.             if (!isset($data['packages'])) {
  699.                 $data['packages'] = array();
  700.             }
  701.             if (!isset($data['packages'][strtolower($depchannel)])) {
  702.                 $data['packages'][strtolower($depchannel)] = array();
  703.             }
  704.             if (!isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) {
  705.                 $data['packages'][strtolower($depchannel)][strtolower($dep['name'])] = array();
  706.             }
  707.             $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
  708.                 = array('channel' => strtolower($pkg->getChannel()),
  709.                         'package' => strtolower($pkg->getPackage()));
  710.         }
  711.     }
  712. }
  713. ?>