Code Coverage for /home/user/workspace/all/Pyrus/src/Pyrus/PackageFile/v2/Dependencies.php in PackageFile_v2/basic/maintainer2.phpt

Coverage: 40%

Aggregate Code Coverage for all tests

       1           : <?php
       2           : /**
       3           :  * PEAR2_Pyrus_PackageFile_v2_Dependencies
       4           :  *
       5           :  * PHP version 5
       6           :  *
       7           :  * @category  PEAR2
       8           :  * @package   PEAR2_Pyrus
       9           :  * @author    Greg Beaver <cellog@php.net>
      10           :  * @copyright 2008 The PEAR Group
      11           :  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
      12           :  * @version   SVN: $Id$
      13           :  * @link      http://svn.pear.php.net/wsvn/PEARSVN/Pyrus/
      14           :  */
      15           : 
      16           : /**
      17           :  * Manage dependencies
      18           :  *
      19           :  * To be used like:
      20           :  * <code>
      21           :  * // reset deps
      22           :  * $pf->dependencies = null;
      23           :  * // for PHP dep
      24           :  * // defaults to min
      25           :  * $pf->dependencies->required->php = '5.3.0';
      26           :  * $pf->dependencies->required->php = array('min' => '5.3.0', 'max' => '7.0.0',
      27           :  *      'exclude' => array('6.1.2'));
      28           :  * // for PEAR Installer dep
      29           :  * // defaults to min
      30           :  * $pf->dependencies->required->pearinstaller = '2.0.0';
      31           :  * $pf->dependencies->required->pearinstaller = array('min' => '2.0.0');
      32           :  * // for required/optional package deps or subpackage deps
      33           :  * $pf->dependencies->required->package['channel/PackageName'] =
      34           :  *      array('min' => '1.1.0', 'max' => '1.2.0', 'recommended' => '1.1.1',
      35           :  *            'exclude' => array('1.1.0a1', '1.1.0a2'));
      36           :  * $pf->dependencies->optional->package['channel/PackageName'] =
      37           :  *      array('min' => '1.1.0', 'max' => '1.2.0', 'recommended' => '1.1.1',
      38           :  *            'exclude' => array('1.1.0a1', '1.1.0a2'));
      39           :  * $pf->dependencies->required->subpackage['channel/PackageName'] =
      40           :  *      array('min' => '1.1.0', 'max' => '1.2.0', 'recommended' => '1.1.1',
      41           :  *            'exclude' => array('1.1.0a1', '1.1.0a2'));
      42           :  * // for conflicting package dep
      43           :  * $pf->dependencies->required->subpackage['channel/PackageName'] =
      44           :  *      array('min' => '1.1.0', 'max' => '1.2.0', 'recommended' => '1.1.1',
      45           :  *            'exclude' => array('1.1.0a1', '1.1.0a2'), 'conflicts' => '');
      46           :  * // for PECL extension deps (optional or required same as packages)
      47           :  * $pf->dependencies->required->package['channel/PackageName'] =
      48           :  *      array('min' => '1.1.0', 'max' => '1.2.0', 'recommended' => '1.1.1',
      49           :  *            'exclude' => array('1.1.0a1', '1.1.0a2'), 'providesextension' => 'packagename');
      50           :  * // for extension deps (required or optional same as packages)
      51           :  * $pf->dependencies->required->extension['extension'] =
      52           :  *      array('min' => '1.0.0', 'max' => '1.2.0', 'recommended' => '1.1.1');
      53           :  * // for regular arch deps
      54           :  * $pf->dependencies->required->arch['i386'] = true // only works on i386
      55           :  * // for conflicting arch deps
      56           :  * $pf->dependencies->required->arch['*(ix|ux)'] = false // doesn't work on unix/linux
      57           :  * // for regular OS deps
      58           :  * $pf->dependencies->required->os['windows'] = true; // only works on windows
      59           :  * // for conflicting OS deps
      60           :  * $pf->dependencies->required->os['freebsd'] = false; // doesn't work on FreeBSD
      61           :  *
      62           :  * // dependency group setup
      63           :  * $group = $pf->dependencies->group['name']->hint('Install optional stuff as a group');
      64           :  * $group->package['channel/PackageName1'] = array();
      65           :  * $group->package['channel/PackageName2'] = array('min' => '1.2.0');
      66           :  * $group->subpackage['channel/PackageName3'] = array('recommended' => '1.2.1');
      67           :  * $group->extension['extension'] = array();
      68           :  * </code>
      69           :  *
      70           :  * @category  PEAR2
      71           :  * @package   PEAR2_Pyrus
      72           :  * @author    Greg Beaver <cellog@php.net>
      73           :  * @copyright 2008 The PEAR Group
      74           :  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
      75           :  * @link      http://svn.pear.php.net/wsvn/PEARSVN/Pyrus/
      76           :  */
      77         1 : class PEAR2_Pyrus_PackageFile_v2_Dependencies implements ArrayAccess, Iterator, Countable
      78           : {
      79           :     private $_parent;
      80           :     private $_packageInfo;
      81           :     private $_required;
      82           :     private $_group = null;
      83           :     private $_package;
      84           :     private $_type;
      85           :     private $_pos = 0;
      86           :     private $_count = 0;
      87           :     private $_info = array();
      88           :     function __construct(array &$parent, array &$packageInfo, $required = null, $type = null,
      89           :                          $package = null, $group = null)
      90           :     {
      91         1 :         $this->_parent = &$parent;
      92         1 :         $this->_packageInfo = &$packageInfo;
      93         1 :         if (!$required) return;
      94         1 :         if (!in_array($required, array('required', 'optional', 'group'), true)) {
      95           :             throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
      96           :                 'Internal error: $required is not required/optional/group');
      97           :         }
      98         1 :         $this->_required = $required;
      99         1 :         if (!isset($parent[$required])) {
     100         1 :             $parent[$required] = array();
     101         1 :             $this->_packageInfo = &$parent;
     102         1 :         }
     103         1 :         if ($this->_required != 'group' && $group) {
     104           :             throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     105           :                 'Internal error: $group passed into required dependency');
     106         1 :         } elseif ($group) {
     107         1 :             if (!is_string($group)) {
     108           :                 throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     109           :                     'Internal error: $group must be a string');
     110           :             }
     111         1 :             $this->_packageInfo = &$parent['group'];
     112         1 :             $this->_group = $group;
     113           :             // locate group in the xml and initialize if not present
     114         1 :             if (!count($this->_packageInfo)) {
     115         1 :                 $this->_packageInfo =
     116         1 :                     array('attribs' => array('name' => $group, 'hint' => ''));
     117         1 :             } elseif (!isset($this->_packageInfo[0])) {
     118         1 :                 if ($this->_packageInfo['attribs']['name'] != $group) {
     119           :                     $this->_packageInfo = array($this->_packageInfo,
     120           :                         array('attribs' => array('name' => $group, 'hint' => '')));
     121           :                     $this->_packageInfo = &$this->_packageInfo[1];
     122           :                 }
     123         1 :             } else {
     124           :                 $found = false;
     125           :                 foreach ($this->_packageInfo as $i => $g) {
     126           :                     if ($g['attribs']['name'] == $group) {
     127           :                         $this->_packageInfo = &$this->_packageInfo[$i];
     128           :                         $found = true;
     129           :                         break;
     130           :                     }
     131           :                 }
     132           :                 if (!$found) {
     133           :                     $this->_packageInfo[$i = count($this->_packageInfo)] =
     134           :                         array('attribs' => array('name' => $group, 'hint' => ''));
     135           :                 }
     136           :             }
     137         1 :         } elseif (!$type) {
     138         1 :             $this->_packageInfo = &$this->_packageInfo[$this->_required];
     139         1 :         }
     140         1 :         if (!$type) {
     141         1 :             if (count($this->_packageInfo)) {
     142         1 :                 if (isset($this->_packageInfo[0])) {
     143           :                     $this->_count = count($this->_packageInfo);
     144           :                 } else {
     145         1 :                     $this->_count = 1;
     146           :                 }
     147         1 :             }
     148         1 :             return;
     149           :         }
     150         1 :         if (!is_string($type)) {
     151           :             throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     152           :                         'Internal error: $type is not a string, but is a ' . gettype($type));
     153           :         }
     154         1 :         if ($required == 'required') {
     155           :             switch ($type) {
     156         1 :                 case 'php' :
     157         1 :                 case 'pearinstaller' :
     158         1 :                 case 'package' :
     159         1 :                 case 'subpackage' :
     160         1 :                 case 'extension' :
     161         1 :                 case 'arch' :
     162         1 :                 case 'os' :
     163         1 :                     $this->_type = $type;
     164         1 :                     if (!isset($this->_packageInfo[$type])) {
     165         1 :                         $this->_packageInfo[$type] = array();
     166         1 :                     }
     167         1 :                     $this->_packageInfo = &$this->_packageInfo[$type];
     168         1 :                     break;
     169           :                 default :
     170           :                     throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     171           :                         'Unknown dependency type ' . $type);
     172           :             }
     173         1 :         } else {
     174           :             switch ($type) {
     175         1 :                 case 'package' :
     176         1 :                 case 'subpackage' :
     177         1 :                 case 'extension' :
     178         1 :                     $this->_type = $type;
     179         1 :                     if (!isset($this->_packageInfo[$type])) {
     180         1 :                         $this->_packageInfo[$type] = array();
     181         1 :                     }
     182         1 :                     $this->_packageInfo = &$this->_packageInfo[$type];
     183         1 :                     break;
     184           :                 case 'php' :
     185           :                 case 'pearinstaller' :
     186           :                 case 'arch' :
     187           :                 case 'os' :
     188           :                 default :
     189           :                     throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     190           :                         $type . ' dependency cannot be optional');
     191           :             }
     192           :         }
     193         1 :         if (count($this->_packageInfo)) {
     194         1 :             if (isset($this->_packageInfo[0])) {
     195         1 :                 $this->_count = count($this->_packageInfo);
     196         1 :             } else {
     197         1 :                 $this->_count = 1;
     198           :             }
     199         1 :         } else {
     200         1 :             $this->_count = 0;
     201           :         }
     202         1 :         if (!$package) return;
     203           :         switch ($this->_type) {
     204           :             case 'php' :
     205           :             case 'pearinstaller' :
     206           :                 throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     207           :                     'Internal error: $package passed into ' . $type . ' dependency');
     208           :             case 'package' :
     209           :             case 'subpackage' :
     210           :                 $channel = explode('/', $package);
     211           :                 $package = array_pop($channel);
     212           :                 $channel = implode('/', $channel);
     213           :                 $this->_info['name'] = $package;
     214           :                 $this->_info['channel'] = $channel;
     215           :                 $this->_package = true;
     216           :                 break;
     217           :             case 'os' :
     218           :             case 'extension' :
     219           :                 $this->_info['name'] = $package;
     220           :                 $this->_package = true;
     221           :                 break;
     222           :             case 'arch' :
     223           :                 $this->_info['pattern'] = $package;
     224           :                 $this->_package = true;
     225           :                 break;
     226           :         }
     227           :         if (!isset($this->_packageInfo[0])) {
     228           :             $name = ($this->_type == 'arch') ? 'pattern' : 'name';
     229           :             if ($this->_packageInfo[$name] != $package) {
     230           :                 $this->_packageInfo = array($this->_packageInfo, array($name => $package));
     231           :                 $this->_packageInfo = &$this->_packageInfo[1];
     232           :             }
     233           :         } else {
     234           :             foreach ($this->_packageInfo as $i => $dep) {
     235           :                 if ($dep[$name] == $package) {
     236           :                     $this->_packageInfo = &$this->_packageInfo[$i];
     237           :                     return;
     238           :                 }
     239           :             }
     240           :             $this->_packageInfo[$i = count($this->_packageInfo)] = array($name => $package);
     241           :             $this->_packageInfo = &$this->_packageInfo[$i];
     242           :         }
     243           :     }
     244           : 
     245           :     function __get($var)
     246           :     {
     247         1 :         if (!isset($this->_required)) {
     248         1 :             return new PEAR2_Pyrus_PackageFile_v2_Dependencies($this->_parent,
     249         1 :                 $this->_packageInfo, $var);
     250           :         }
     251         1 :         if (!isset($this->_type)) {
     252         1 :             if (isset($this->_group)) {
     253         1 :                 return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     254         1 :                     $this->_parent, $this->_packageInfo, $this->_required,
     255         1 :                     $var, null, $this->_group);
     256           :             } else {
     257         1 :                 return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     258         1 :                     $this->_parent, $this->_packageInfo, $this->_required,
     259         1 :                     $var);
     260           :             }
     261           :         }
     262           :         if ($this->_type == 'group' && !isset($this->_group)) {
     263           :             throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     264           :                 'Dependency group must be accessed like $pf->group[\'groupname\']');
     265           :         }
     266           :         if (!isset($this->_package) && $this->_type != 'php' && $this->_type != 'pearinstaller') {
     267           :             return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     268           :                 $this->_parent, $this->_packageInfo[$var], $this->_required,
     269           :                 $this->_type, $var);
     270           :         }
     271           :         if (!isset($this->_packageInfo[$var])) {
     272           :             return null;
     273           :         }
     274           :         return $this->_packageInfo[$var];
     275           :     }
     276           : 
     277           :     function __set($var, $value)
     278           :     {
     279           :         if (isset($this->_required) && $this->_required == 'required'
     280           :               && in_array($var, array('php', 'pearinstaller'), true)) {
     281           :             if (is_string($value)) {
     282           :                 $value = array('min' => $value);
     283           :             }
     284           :             if (!is_array($value)) {
     285           :                 throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     286           :                     $var . ' dependency must be an array, was a ' . gettype($value));
     287           :             }
     288           :             $info = array();
     289           :             foreach (array('min', 'max', 'exclude') as $index) {
     290           :                 if (isset($value[$index])) {
     291           :                     $info[$index] = $value[$index];
     292           :                 }
     293           :             }
     294           :             $this->_packageInfo[$var] = $info;
     295           :             return;
     296           :         }
     297           :         throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     298           :             'Cannot set ' . $var . ' directly');
     299           :     }
     300           : 
     301           :     function current()
     302           :     {
     303           :         if (!$this->valid()) return null;
     304           :         if ($this->_required === 'group' && !isset($this->_group)) {
     305           :             if (!isset($this->_type)) {
     306           :                 if (!isset($this->_packageInfo[0])) {
     307           :                     return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     308           :                         $this->_parent, $this->_packageInfo, $this->_required,
     309           :                         $this->_type, null, $this->_packageInfo['attribs']['name']);
     310           :                 } else {
     311           :                     return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     312           :                         $this->_parent, $this->_packageInfo, $this->_required,
     313           :                         $this->_type, null, $this->_packageInfo[$this->_pos]['attribs']['name']);
     314           :                 }
     315           :             }
     316           :         }
     317           :         if (!isset($this->_packageInfo[0])) {
     318           :             return $this->_packageInfo;
     319           :         }
     320           :         return $this->_packageInfo[$this->_pos];
     321           :     }
     322           : 
     323           :     function next()
     324           :     {
     325           :         $this->_pos++;
     326           :     }
     327           : 
     328           :     function key()
     329           :     {
     330           :         if (!$this->valid()) return null;
     331           :         return $this->_pos;
     332           :     }
     333           : 
     334           :     function valid()
     335           :     {
     336           :         if (!$this->_count) {
     337           :             return false;
     338           :         }
     339           :         return $this->_pos < $this->_count;
     340           :     }
     341           : 
     342           :     function rewind()
     343           :     {
     344           :         $this->_pos = 0;
     345           :     }
     346           : 
     347           :     function count()
     348           :     {
     349           :         return $this->_count;
     350           :     }
     351           : 
     352           :     function hint($hint)
     353           :     {
     354         1 :         if ($this->_required !== 'group' || !$this->_group) {
     355           :             throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     356           :                 'hint can only be set for dependency groups');
     357           :         }
     358         1 :         $this->_packageInfo['attribs']['hint'] = $hint;
     359         1 :         return $this;
     360           :     }
     361           : 
     362           :     function offsetGet($var)
     363           :     {
     364         1 :         if ($this->_required == 'group' && !isset($this->_group)) {
     365         1 :             return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     366         1 :                 $this->_parent, $this->_packageInfo, $this->_required,
     367         1 :                 $this->_type, null, $var);
     368           :         }
     369           :         if (isset($this->_type) && in_array($this->_type, array('php', 'pearinstaller', 'arch', 'os'))) {
     370           :             return $this->_packageInfo[$var];
     371           :         }
     372           :         return new PEAR2_Pyrus_PackageFile_v2_Dependencies(
     373           :             $this->_parent, $this->_packageInfo, $this->_required,
     374           :             $this->_type, $var, $this->_group);
     375           :     }
     376           : 
     377           :     function offsetSet($var, $value)
     378           :     {
     379         1 :         if (!isset($this->_required)) {
     380           :             throw new PEAR2_Pyrus_PackageFile_v2_Compatible_Exception(
     381           :                         'Cannot set ' . $var . ' directly, must specify required, optional, or group dependency first');
     382           :         }
     383         1 :         if (isset($this->_type) && in_array($this->_type, array('package', 'subpackage'))) {
     384         1 :             if (!is_array($value)) {
     385           :                 throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     386           :                     $this->_type . ' dependency must be an array, was a ' . gettype($value));
     387           :             }
     388         1 :             $channel = explode('/', $var);
     389         1 :             $package = array_pop($channel);
     390         1 :             $channel = implode('/', $channel);
     391         1 :             $info = array('name' => $package, 'channel' => $channel);
     392         1 :             foreach (array('min', 'max', 'recommended', 'exclude', 'nodefault',
     393         1 :                            'conflicts', 'providesextension') as $index) {
     394         1 :                 if (isset($value[$index])) {
     395         1 :                     $info[$index] = $value[$index];
     396         1 :                 }
     397         1 :             }
     398         1 :             if (isset($this->_packageInfo[0])) {
     399         1 :                 foreach ($this->_packageInfo as $i => $dep) {
     400         1 :                     if ($dep['name'] === $package && $dep['channel'] === $channel) {
     401           :                         $this->_packageInfo[$i] = $info;
     402           :                         return;
     403           :                     }
     404         1 :                 }
     405         1 :                 $this->_packageInfo[] = $info;
     406         1 :             } else {
     407         1 :                 if (!count($this->_packageInfo)) {
     408         1 :                     $this->_packageInfo = $info;
     409         1 :                     return;
     410           :                 }
     411         1 :                 if ($this->_packageInfo['name'] === $package
     412         1 :                       && $this->_packageInfo['channel'] === $channel) {
     413           :                     $this->_packageInfo = $info;
     414           :                 } else {
     415         1 :                     $this->_packageInfo = array($this->_packageInfo, $info);
     416           :                 }
     417           :             }
     418         1 :             return;
     419           :         }
     420         1 :         if (isset($this->_type) && $this->_type === 'extension') {
     421         1 :             if (!is_array($value)) {
     422           :                 throw new PEAR2_Pyrus_PackageFile_v2_Dependencies_Exception(
     423           :                     $this->_type . ' dependency must be an array, was a ' . gettype($value));
     424           :             }
     425         1 :             $info = array('name' => $var);
     426         1 :             foreach (array('min', 'max', 'recommended', 'exclude', 'conflicts') as $index) {
     427         1 :                 if (isset($value[$index])) {
     428         1 :                     $info[$index] = $value[$index];
     429         1 :                 }
     430         1 :             }
     431         1 :             if (isset($this->_packageInfo[0])) {
     432           :                 foreach ($this->_packageInfo as $i => $dep) {
     433           :                     if ($dep['name'] === $var) {
     434           :                         $this->_packageInfo[$i] = $info;
     435           :                         return;
     436           :                     }
     437           :                 }
     438           :                 $this->_packageInfo[] = $info;
     439           :             } else {
     440         1 :                 if (!count($this->_packageInfo)) {
     441         1 :                     $this->_packageInfo = $info;
     442         1 :                 } elseif ($this->_packageInfo['name'] === $var) {
     443           :                     $this->_packageInfo = $info;
     444           :                 } else {
     445           :                     $this->_packageInfo = array($this->_packageInfo, $info);
     446           :                 }
     447           :             }
     448         1 :             return;
     449           :         }
     450           :         // $var is the os name or the arch name
     451           :         // $value is true or false, for defining required (true) or conflicts (false)
     452         1 :         if (isset($this->_type) && in_array($this->_type, array('arch', 'os'))) {
     453         1 :             $val = (bool) $value;
     454         1 :             $name = ($this->_type === 'arch' ? 'pattern' : 'name');
     455         1 :             $info = array($name => $var);
     456         1 :             if (!$val) {
     457         1 :                 $info['conflicts'] = '';
     458         1 :             }
     459         1 :             if (isset($this->_packageInfo[0])) {
     460           :                 foreach ($this->_packageInfo as $index => $dep) {
     461           :                     if ($dep[$name] == $var) {
     462           :                         $this->_packageInfo[$index] = $info;
     463           :                         return;
     464           :                     }
     465           :                 }
     466           :                 $this->_packageInfo[] = $info;
     467           :             } else {
     468         1 :                 if (!count($this->_packageInfo) || $this->_packageInfo[$name] === $var) {
     469         1 :                     $this->_packageInfo = $info;
     470         1 :                 } else {
     471         1 :                     $this->_packageInfo = array($this->_packageInfo, $info);
     472           :                 }
     473           :             }
     474         1 :         }
     475         1 :     }
     476           : 
     477           :     /**
     478           :      * unimplemented
     479           :      * @param string $var
     480           :      */
     481           :     function offsetUnset($var)
     482           :     {
     483           :     }
     484           : 
     485           :     /**
     486           :      * unimplemented
     487           :      * @param string $var
     488           :      * @return bool
     489           :      */
     490           :     function offsetExists($var)
     491           :     {
     492           :         return isset($this->_packageInfo[$var]);
     493           :     }
     494         1 : }