PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file v2.php

Documentation is available at v2.php

  1. <?php
  2. /**
  3.  * PEAR_PackageFile_v2, package.xml version 2.0
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * @category   pear
  8.  * @package    PEAR
  9.  * @author     Greg Beaver <cellog@php.net>
  10.  * @copyright  1997-2009 The Authors
  11.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  12.  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
  13.  * @link       http://pear.php.net/package/PEAR
  14.  * @since      File available since Release 1.4.0a1
  15.  */
  16. /**
  17.  * For error handling
  18.  */
  19. require_once 'PEAR/ErrorStack.php';
  20. /**
  21.  * @category   pear
  22.  * @package    PEAR
  23.  * @author     Greg Beaver <cellog@php.net>
  24.  * @copyright  1997-2009 The Authors
  25.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  26.  * @version    Release: 1.9.4
  27.  * @link       http://pear.php.net/package/PEAR
  28.  * @since      Class available since Release 1.4.0a1
  29.  */
  30. {
  31.  
  32.     /**
  33.      * Parsed package information
  34.      * @var array 
  35.      * @access private
  36.      */
  37.     var $_packageInfo = array();
  38.  
  39.     /**
  40.      * path to package .tgz or false if this is a local/extracted package.xml
  41.      * @var string|false
  42.      * @access private
  43.      */
  44.     var $_archiveFile;
  45.  
  46.     /**
  47.      * path to package .xml or false if this is an abstract parsed-from-string xml
  48.      * @var string|false
  49.      * @access private
  50.      */
  51.     var $_packageFile;
  52.  
  53.     /**
  54.      * This is used by file analysis routines to log progress information
  55.      * @var PEAR_Common 
  56.      * @access protected
  57.      */
  58.     var $_logger;
  59.  
  60.     /**
  61.      * This is set to the highest validation level that has been validated
  62.      *
  63.      * If the package.xml is invalid or unknown, this is set to 0.  If
  64.      * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
  65.      * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
  66.      * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
  67.      * "caching" to occur, which is particularly important for package validation, so
  68.      * that PHP files are not validated twice
  69.      * @var int 
  70.      * @access private
  71.      */
  72.     var $_isValid = 0;
  73.  
  74.     /**
  75.      * True if the filelist has been validated
  76.      * @param bool 
  77.      */
  78.     var $_filesValid = false;
  79.  
  80.     /**
  81.      * @var PEAR_Registry 
  82.      * @access protected
  83.      */
  84.     var $_registry;
  85.  
  86.     /**
  87.      * @var PEAR_Config 
  88.      * @access protected
  89.      */
  90.     var $_config;
  91.  
  92.     /**
  93.      * Optional Dependency group requested for installation
  94.      * @var string 
  95.      * @access private
  96.      */
  97.     var $_requestedGroup = false;
  98.  
  99.     /**
  100.      * @var PEAR_ErrorStack 
  101.      * @access protected
  102.      */
  103.     var $_stack;
  104.  
  105.     /**
  106.      * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
  107.      */
  108.     var $_tasksNs;
  109.  
  110.     /**
  111.      * Determines whether this packagefile was initialized only with partial package info
  112.      *
  113.      * If this package file was constructed via parsing REST, it will only contain
  114.      *
  115.      * - package name
  116.      * - channel name
  117.      * - dependencies
  118.      * @var boolean 
  119.      * @access private
  120.      */
  121.     var $_incomplete = true;
  122.  
  123.     /**
  124.      * @var PEAR_PackageFile_v2_Validator 
  125.      */
  126.     var $_v2Validator;
  127.  
  128.     /**
  129.      * The constructor merely sets up the private error stack
  130.      */
  131.     function PEAR_PackageFile_v2()
  132.     {
  133.         $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2'falsenull);
  134.         $this->_isValid = false;
  135.     }
  136.  
  137.     /**
  138.      * To make unit-testing easier
  139.      * @param PEAR_Frontend_* 
  140.      * @param array options
  141.      * @param PEAR_Config 
  142.      * @return PEAR_Downloader 
  143.      * @access protected
  144.      */
  145.     function &getPEARDownloader(&$i$o&$c)
  146.     {
  147.         $z &new PEAR_Downloader($i$o$c);
  148.         return $z;
  149.     }
  150.  
  151.     /**
  152.      * To make unit-testing easier
  153.      * @param PEAR_Config 
  154.      * @param array options
  155.      * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
  156.      * @param int PEAR_VALIDATE_* constant
  157.      * @return PEAR_Dependency2 
  158.      * @access protected
  159.      */
  160.     function &getPEARDependency2(&$c$o$p$s = PEAR_VALIDATE_INSTALLING)
  161.     {
  162.         if (!class_exists('PEAR_Dependency2')) {
  163.             require_once 'PEAR/Dependency2.php';
  164.         }
  165.         $z &new PEAR_Dependency2($c$o$p$s);
  166.         return $z;
  167.     }
  168.  
  169.     function getInstalledBinary()
  170.     {
  171.         return isset($this->_packageInfo['#binarypackage']$this->_packageInfo['#binarypackage':
  172.             false;
  173.     }
  174.  
  175.     /**
  176.      * Installation of source package has failed, attempt to download and install the
  177.      * binary version of this package.
  178.      * @param PEAR_Installer 
  179.      * @return array|false
  180.      */
  181.     function installBinary(&$installer)
  182.     {
  183.         if (!OS_WINDOWS{
  184.             $a = false;
  185.             return $a;
  186.         }
  187.         if ($this->getPackageType(== 'extsrc' || $this->getPackageType(== 'zendextsrc'{
  188.             $releasetype $this->getPackageType('release';
  189.             if (!is_array($installer->getInstallPackages())) {
  190.                 $a = false;
  191.                 return $a;
  192.             }
  193.             foreach ($installer->getInstallPackages(as $p{
  194.                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
  195.                     if ($p->getPackageType(!= 'extsrc' && $p->getPackageType(!= 'zendextsrc'{
  196.                         $a = false;
  197.                         return $a// the user probably downloaded it separately
  198.                     }
  199.                 }
  200.             }
  201.             if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
  202.                 $installer->log(0'Attempting to download binary version of extension "' .
  203.                     $this->_packageInfo['providesextension''"');
  204.                 $params $this->_packageInfo[$releasetype]['binarypackage'];
  205.                 if (!is_array($params|| !isset($params[0])) {
  206.                     $params = array($params);
  207.                 }
  208.                 if (isset($this->_packageInfo['channel'])) {
  209.                     foreach ($params as $i => $param{
  210.                         $params[$i= array('channel' => $this->_packageInfo['channel'],
  211.                             'package' => $param'version' => $this->getVersion());
  212.                     }
  213.                 }
  214.                 $dl &$this->getPEARDownloader($installer->ui$installer->getOptions(),
  215.                     $installer->config);
  216.                 $verbose $dl->config->get('verbose');
  217.                 $dl->config->set('verbose'-1);
  218.                 foreach ($params as $param{
  219.                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  220.                     $ret $dl->download(array($param));
  221.                     PEAR::popErrorHandling();
  222.                     if (is_array($ret&& count($ret)) {
  223.                         break;
  224.                     }
  225.                 }
  226.                 $dl->config->set('verbose'$verbose);
  227.                 if (is_array($ret)) {
  228.                     if (count($ret== 1{
  229.                         $pf $ret[0]->getPackageFile();
  230.                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  231.                         $err $installer->install($ret[0]);
  232.                         PEAR::popErrorHandling();
  233.                         if (is_array($err)) {
  234.                             $this->_packageInfo['#binarypackage'$ret[0]->getPackage();
  235.                             // "install" self, so all dependencies will work transparently
  236.                             $this->_registry->addPackage2($this);
  237.                             $installer->log(0'Download and install of binary extension "' .
  238.                                 $this->_registry->parsedPackageNameToString(
  239.                                     array('channel' => $pf->getChannel(),
  240.                                           'package' => $pf->getPackage())true'" successful');
  241.                             $a = array($ret[0]$err);
  242.                             return $a;
  243.                         }
  244.                         $installer->log(0'Download and install of binary extension "' .
  245.                             $this->_registry->parsedPackageNameToString(
  246.                                     array('channel' => $pf->getChannel(),
  247.                                           'package' => $pf->getPackage())true'" failed');
  248.                     }
  249.                 }
  250.             }
  251.         }
  252.         $a = false;
  253.         return $a;
  254.     }
  255.  
  256.     /**
  257.      * @return string|falseExtension name
  258.      */
  259.     function getProvidesExtension()
  260.     {
  261.         if (in_array($this->getPackageType(),
  262.               array('extsrc''extbin''zendextsrc''zendextbin'))) {
  263.             if (isset($this->_packageInfo['providesextension'])) {
  264.                 return $this->_packageInfo['providesextension'];
  265.             }
  266.         }
  267.         return false;
  268.     }
  269.  
  270.     /**
  271.      * @param string Extension name
  272.      * @return bool 
  273.      */
  274.     function isExtension($extension)
  275.     {
  276.         if (in_array($this->getPackageType(),
  277.               array('extsrc''extbin''zendextsrc''zendextbin'))) {
  278.             return $this->_packageInfo['providesextension'== $extension;
  279.         }
  280.         return false;
  281.     }
  282.  
  283.     /**
  284.      * Tests whether every part of the package.xml 1.0 is represented in
  285.      * this package.xml 2.0
  286.      * @param PEAR_PackageFile_v1 
  287.      * @return bool 
  288.      */
  289.     function isEquivalent($pf1)
  290.     {
  291.         if (!$pf1{
  292.             return true;
  293.         }
  294.         if ($this->getPackageType(== 'bundle'{
  295.             return false;
  296.         }
  297.         $this->_stack->getErrors(true);
  298.         if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
  299.             return false;
  300.         }
  301.         $pass = true;
  302.         if ($pf1->getPackage(!= $this->getPackage()) {
  303.             $this->_differentPackage($pf1->getPackage());
  304.             $pass = false;
  305.         }
  306.         if ($pf1->getVersion(!= $this->getVersion()) {
  307.             $this->_differentVersion($pf1->getVersion());
  308.             $pass = false;
  309.         }
  310.         if (trim($pf1->getSummary()) != $this->getSummary()) {
  311.             $this->_differentSummary($pf1->getSummary());
  312.             $pass = false;
  313.         }
  314.         if (preg_replace('/\s+/'''$pf1->getDescription()) !=
  315.               preg_replace('/\s+/'''$this->getDescription())) {
  316.             $this->_differentDescription($pf1->getDescription());
  317.             $pass = false;
  318.         }
  319.         if ($pf1->getState(!= $this->getState()) {
  320.             $this->_differentState($pf1->getState());
  321.             $pass = false;
  322.         }
  323.         if (!strstr(preg_replace('/\s+/'''$this->getNotes()),
  324.               preg_replace('/\s+/'''$pf1->getNotes()))) {
  325.             $this->_differentNotes($pf1->getNotes());
  326.             $pass = false;
  327.         }
  328.         $mymaintainers $this->getMaintainers();
  329.         $yourmaintainers $pf1->getMaintainers();
  330.         for ($i1 = 0; $i1 count($yourmaintainers)$i1++{
  331.             $reset = false;
  332.             for ($i2 = 0; $i2 count($mymaintainers)$i2++{
  333.                 if ($mymaintainers[$i2]['handle'== $yourmaintainers[$i1]['handle']{
  334.                     if ($mymaintainers[$i2]['role'!= $yourmaintainers[$i1]['role']{
  335.                         $this->_differentRole($mymaintainers[$i2]['handle'],
  336.                             $yourmaintainers[$i1]['role']$mymaintainers[$i2]['role']);
  337.                         $pass = false;
  338.                     }
  339.                     if ($mymaintainers[$i2]['email'!= $yourmaintainers[$i1]['email']{
  340.                         $this->_differentEmail($mymaintainers[$i2]['handle'],
  341.                             $yourmaintainers[$i1]['email']$mymaintainers[$i2]['email']);
  342.                         $pass = false;
  343.                     }
  344.                     if ($mymaintainers[$i2]['name'!= $yourmaintainers[$i1]['name']{
  345.                         $this->_differentName($mymaintainers[$i2]['handle'],
  346.                             $yourmaintainers[$i1]['name']$mymaintainers[$i2]['name']);
  347.                         $pass = false;
  348.                     }
  349.                     unset($mymaintainers[$i2]);
  350.                     $mymaintainers array_values($mymaintainers);
  351.                     unset($yourmaintainers[$i1]);
  352.                     $yourmaintainers array_values($yourmaintainers);
  353.                     $reset = true;
  354.                     break;
  355.                 }
  356.             }
  357.             if ($reset{
  358.                 $i1 = -1;
  359.             }
  360.         }
  361.         $this->_unmatchedMaintainers($mymaintainers$yourmaintainers);
  362.         $filelist $this->getFilelist();
  363.         foreach ($pf1->getFilelist(as $file => $atts{
  364.             if (!isset($filelist[$file])) {
  365.                 $this->_missingFile($file);
  366.                 $pass = false;
  367.             }
  368.         }
  369.         return $pass;
  370.     }
  371.  
  372.     function _differentPackage($package)
  373.     {
  374.         $this->_stack->push(__FUNCTION__'error'array('package' => $package,
  375.             'self' => $this->getPackage()),
  376.             'package.xml 1.0 package "%package%" does not match "%self%"');
  377.     }
  378.  
  379.     function _differentVersion($version)
  380.     {
  381.         $this->_stack->push(__FUNCTION__'error'array('version' => $version,
  382.             'self' => $this->getVersion()),
  383.             'package.xml 1.0 version "%version%" does not match "%self%"');
  384.     }
  385.  
  386.     function _differentState($state)
  387.     {
  388.         $this->_stack->push(__FUNCTION__'error'array('state' => $state,
  389.             'self' => $this->getState()),
  390.             'package.xml 1.0 state "%state%" does not match "%self%"');
  391.     }
  392.  
  393.     function _differentRole($handle$role$selfrole)
  394.     {
  395.         $this->_stack->push(__FUNCTION__'error'array('handle' => $handle,
  396.             'role' => $role'self' => $selfrole),
  397.             'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
  398.     }
  399.  
  400.     function _differentEmail($handle$email$selfemail)
  401.     {
  402.         $this->_stack->push(__FUNCTION__'error'array('handle' => $handle,
  403.             'email' => $email'self' => $selfemail),
  404.             'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
  405.     }
  406.  
  407.     function _differentName($handle$name$selfname)
  408.     {
  409.         $this->_stack->push(__FUNCTION__'error'array('handle' => $handle,
  410.             'name' => $name'self' => $selfname),
  411.             'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
  412.     }
  413.  
  414.     function _unmatchedMaintainers($my$yours)
  415.     {
  416.         if ($my{
  417.             array_walk($mycreate_function('&$i, $k''$i = $i["handle"];'));
  418.             $this->_stack->push(__FUNCTION__'error'array('handles' => $my),
  419.                 'package.xml 2.0 has unmatched extra maintainers "%handles%"');
  420.         }
  421.         if ($yours{
  422.             array_walk($yourscreate_function('&$i, $k''$i = $i["handle"];'));
  423.             $this->_stack->push(__FUNCTION__'error'array('handles' => $yours),
  424.                 'package.xml 1.0 has unmatched extra maintainers "%handles%"');
  425.         }
  426.     }
  427.  
  428.     function _differentNotes($notes)
  429.     {
  430.         $truncnotes strlen($notes< 25 ? $notes substr($notes024'...';
  431.         $truncmynotes strlen($this->getNotes()) < 25 ? $this->getNotes(:
  432.             substr($this->getNotes()024'...';
  433.         $this->_stack->push(__FUNCTION__'error'array('notes' => $truncnotes,
  434.             'self' => $truncmynotes),
  435.             'package.xml 1.0 release notes "%notes%" do not match "%self%"');
  436.     }
  437.  
  438.     function _differentSummary($summary)
  439.     {
  440.         $truncsummary strlen($summary< 25 ? $summary substr($summary024'...';
  441.         $truncmysummary strlen($this->getsummary()) < 25 ? $this->getSummary(:
  442.             substr($this->getsummary()024'...';
  443.         $this->_stack->push(__FUNCTION__'error'array('summary' => $truncsummary,
  444.             'self' => $truncmysummary),
  445.             'package.xml 1.0 summary "%summary%" does not match "%self%"');
  446.     }
  447.  
  448.     function _differentDescription($description)
  449.     {
  450.         $truncdescription trim(strlen($description< 25 ? $description substr($description024'...');
  451.         $truncmydescription trim(strlen($this->getDescription()) < 25 ? $this->getDescription(:
  452.             substr($this->getdescription()024'...');
  453.         $this->_stack->push(__FUNCTION__'error'array('description' => $truncdescription,
  454.             'self' => $truncmydescription),
  455.             'package.xml 1.0 description "%description%" does not match "%self%"');
  456.     }
  457.  
  458.     function _missingFile($file)
  459.     {
  460.         $this->_stack->push(__FUNCTION__'error'array('file' => $file),
  461.             'package.xml 1.0 file "%file%" is not present in <contents>');
  462.     }
  463.  
  464.     /**
  465.      * WARNING - do not use this function unless you know what you're doing
  466.      */
  467.     function setRawState($state)
  468.     {
  469.         if (!isset($this->_packageInfo['stability'])) {
  470.             $this->_packageInfo['stability'= array();
  471.         }
  472.         $this->_packageInfo['stability']['release'$state;
  473.     }
  474.  
  475.     /**
  476.      * WARNING - do not use this function unless you know what you're doing
  477.      */
  478.     function setRawCompatible($compatible)
  479.     {
  480.         $this->_packageInfo['compatible'$compatible;
  481.     }
  482.  
  483.     /**
  484.      * WARNING - do not use this function unless you know what you're doing
  485.      */
  486.     function setRawPackage($package)
  487.     {
  488.         $this->_packageInfo['name'$package;
  489.     }
  490.  
  491.     /**
  492.      * WARNING - do not use this function unless you know what you're doing
  493.      */
  494.     function setRawChannel($channel)
  495.     {
  496.         $this->_packageInfo['channel'$channel;
  497.     }
  498.  
  499.     function setRequestedGroup($group)
  500.     {
  501.         $this->_requestedGroup $group;
  502.     }
  503.  
  504.     function getRequestedGroup()
  505.     {
  506.         if (isset($this->_requestedGroup)) {
  507.             return $this->_requestedGroup;
  508.         }
  509.         return false;
  510.     }
  511.  
  512.     /**
  513.      * For saving in the registry.
  514.      *
  515.      * Set the last version that was installed
  516.      * @param string 
  517.      */
  518.     function setLastInstalledVersion($version)
  519.     {
  520.         $this->_packageInfo['_lastversion'$version;
  521.     }
  522.  
  523.     /**
  524.      * @return string|false
  525.      */
  526.     function getLastInstalledVersion()
  527.     {
  528.         if (isset($this->_packageInfo['_lastversion'])) {
  529.             return $this->_packageInfo['_lastversion'];
  530.         }
  531.         return false;
  532.     }
  533.  
  534.     /**
  535.      * Determines whether this package.xml has post-install scripts or not
  536.      * @return array|false
  537.      */
  538.     function listPostinstallScripts()
  539.     {
  540.         $filelist $this->getFilelist();
  541.         $contents $this->getContents();
  542.         $contents $contents['dir']['file'];
  543.         if (!is_array($contents|| !isset($contents[0])) {
  544.             $contents = array($contents);
  545.         }
  546.         $taskfiles = array();
  547.         foreach ($contents as $file{
  548.             $atts $file['attribs'];
  549.             unset($file['attribs']);
  550.             if (count($file)) {
  551.                 $taskfiles[$atts['name']] $file;
  552.             }
  553.         }
  554.         $common = new PEAR_Common;
  555.         $common->debug = $this->_config->get('verbose');
  556.         $this->_scripts = array();
  557.         $ret = array();
  558.         foreach ($taskfiles as $name => $tasks{
  559.             if (!isset($filelist[$name])) {
  560.                 // ignored files will not be in the filelist
  561.                 continue;
  562.             }
  563.             $atts $filelist[$name];
  564.             foreach ($tasks as $tag => $raw{
  565.                 $task $this->getTask($tag);
  566.                 $task &new $task($this->_config$commonPEAR_TASK_INSTALL);
  567.                 if ($task->isScript()) {
  568.                     $ret[$filelist[$name]['installed_as'];
  569.                 }
  570.             }
  571.         }
  572.         if (count($ret)) {
  573.             return $ret;
  574.         }
  575.         return false;
  576.     }
  577.  
  578.     /**
  579.      * Initialize post-install scripts for running
  580.      *
  581.      * This method can be used to detect post-install scripts, as the return value
  582.      * indicates whether any exist
  583.      * @return bool 
  584.      */
  585.     function initPostinstallScripts()
  586.     {
  587.         $filelist $this->getFilelist();
  588.         $contents $this->getContents();
  589.         $contents $contents['dir']['file'];
  590.         if (!is_array($contents|| !isset($contents[0])) {
  591.             $contents = array($contents);
  592.         }
  593.         $taskfiles = array();
  594.         foreach ($contents as $file{
  595.             $atts $file['attribs'];
  596.             unset($file['attribs']);
  597.             if (count($file)) {
  598.                 $taskfiles[$atts['name']] $file;
  599.             }
  600.         }
  601.         $common = new PEAR_Common;
  602.         $common->debug = $this->_config->get('verbose');
  603.         $this->_scripts = array();
  604.         foreach ($taskfiles as $name => $tasks{
  605.             if (!isset($filelist[$name])) {
  606.                 // file was not installed due to installconditions
  607.                 continue;
  608.             }
  609.             $atts $filelist[$name];
  610.             foreach ($tasks as $tag => $raw{
  611.                 $taskname $this->getTask($tag);
  612.                 $task &new $taskname($this->_config$commonPEAR_TASK_INSTALL);
  613.                 if (!$task->isScript()) {
  614.                     continue; // scripts are only handled after installation
  615.                 }
  616.                 $lastversion = isset($this->_packageInfo['_lastversion']?
  617.                     $this->_packageInfo['_lastversion': null;
  618.                 $task->init($raw$atts$lastversion);
  619.                 $res $task->startSession($this$atts['installed_as']);
  620.                 if (!$res{
  621.                     continue; // skip this file
  622.                 }
  623.                 if (PEAR::isError($res)) {
  624.                     return $res;
  625.                 }
  626.                 $assign &$task;
  627.                 $this->_scripts[&$assign;
  628.             }
  629.         }
  630.         if (count($this->_scripts)) {
  631.             return true;
  632.         }
  633.         return false;
  634.     }
  635.  
  636.     function runPostinstallScripts()
  637.     {
  638.         if ($this->initPostinstallScripts()) {
  639.             $ui &PEAR_Frontend::singleton();
  640.             if ($ui{
  641.                 $ui->runPostinstallScripts($this->_scripts$this);
  642.             }
  643.         }
  644.     }
  645.  
  646.  
  647.     /**
  648.      * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
  649.      * <file> tags.
  650.      */
  651.     function flattenFilelist()
  652.     {
  653.         if (isset($this->_packageInfo['bundle'])) {
  654.             return;
  655.         }
  656.         $filelist = array();
  657.         if (isset($this->_packageInfo['contents']['dir']['dir'])) {
  658.             $this->_getFlattenedFilelist($filelist$this->_packageInfo['contents']['dir']);
  659.             if (!isset($filelist[1])) {
  660.                 $filelist $filelist[0];
  661.             }
  662.             $this->_packageInfo['contents']['dir']['file'$filelist;
  663.             unset($this->_packageInfo['contents']['dir']['dir']);
  664.         else {
  665.             // else already flattened but check for baseinstalldir propagation
  666.             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
  667.                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
  668.                     foreach ($this->_packageInfo['contents']['dir']['file'as $i => $file{
  669.                         if (isset($file['attribs']['baseinstalldir'])) {
  670.                             continue;
  671.                         }
  672.                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
  673.                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
  674.                     }
  675.                 else {
  676.                     if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
  677.                        $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
  678.                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
  679.                     }
  680.                 }
  681.             }
  682.         }
  683.     }
  684.  
  685.     /**
  686.      * @param array the final flattened file list
  687.      * @param array the current directory being processed
  688.      * @param string|falseany recursively inherited baeinstalldir attribute
  689.      * @param string private recursion variable
  690.      * @return array 
  691.      * @access protected
  692.      */
  693.     function _getFlattenedFilelist(&$files$dir$baseinstall = false$path '')
  694.     {
  695.         if (isset($dir['attribs']&& isset($dir['attribs']['baseinstalldir'])) {
  696.             $baseinstall $dir['attribs']['baseinstalldir'];
  697.         }
  698.         if (isset($dir['dir'])) {
  699.             if (!isset($dir['dir'][0])) {
  700.                 $dir['dir'= array($dir['dir']);
  701.             }
  702.             foreach ($dir['dir'as $subdir{
  703.                 if (!isset($subdir['attribs']|| !isset($subdir['attribs']['name'])) {
  704.                     $name '*unknown*';
  705.                 else {
  706.                     $name $subdir['attribs']['name'];
  707.                 }
  708.                 $newpath = empty($path$name :
  709.                     $path '/' $name;
  710.                 $this->_getFlattenedFilelist($files$subdir,
  711.                     $baseinstall$newpath);
  712.             }
  713.         }
  714.         if (isset($dir['file'])) {
  715.             if (!isset($dir['file'][0])) {
  716.                 $dir['file'= array($dir['file']);
  717.             }
  718.             foreach ($dir['file'as $file{
  719.                 $attrs $file['attribs'];
  720.                 $name $attrs['name'];
  721.                 if ($baseinstall && !isset($attrs['baseinstalldir'])) {
  722.                     $attrs['baseinstalldir'$baseinstall;
  723.                 }
  724.                 $attrs['name'= empty($path$name $path '/' $name;
  725.                 $attrs['name'preg_replace(array('!\\\\+!''!/+!')array('/''/'),
  726.                     $attrs['name']);
  727.                 $file['attribs'$attrs;
  728.                 $files[$file;
  729.             }
  730.         }
  731.     }
  732.  
  733.     function setConfig(&$config)
  734.     {
  735.         $this->_config = &$config;
  736.         $this->_registry = &$config->getRegistry();
  737.     }
  738.  
  739.     function setLogger(&$logger)
  740.     {
  741.         if (!is_object($logger|| !method_exists($logger'log')) {
  742.             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
  743.         }
  744.         $this->_logger = &$logger;
  745.     }
  746.  
  747.     /**
  748.      * WARNING - do not use this function directly unless you know what you're doing
  749.      */
  750.     function setDeps($deps)
  751.     {
  752.         $this->_packageInfo['dependencies'$deps;
  753.     }
  754.  
  755.     /**
  756.      * WARNING - do not use this function directly unless you know what you're doing
  757.      */
  758.     function setCompatible($compat)
  759.     {
  760.         $this->_packageInfo['compatible'$compat;
  761.     }
  762.  
  763.     function setPackagefile($file$archive = false)
  764.     {
  765.         $this->_packageFile $file;
  766.         $this->_archiveFile $archive $archive $file;
  767.     }
  768.  
  769.     /**
  770.      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
  771.      * @param boolean determines whether to purge the error stack after retrieving
  772.      * @return array 
  773.      */
  774.     function getValidationWarnings($purge = true)
  775.     {
  776.         return $this->_stack->getErrors($purge);
  777.     }
  778.  
  779.     function getPackageFile()
  780.     {
  781.         return $this->_packageFile;
  782.     }
  783.  
  784.     function getArchiveFile()
  785.     {
  786.         return $this->_archiveFile;
  787.     }
  788.  
  789.  
  790.     /**
  791.      * Directly set the array that defines this packagefile
  792.      *
  793.      * WARNING: no validation.  This should only be performed by internal methods
  794.      * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
  795.      * @param array 
  796.      */
  797.     function fromArray($pinfo)
  798.     {
  799.         unset($pinfo['old']);
  800.         unset($pinfo['xsdversion']);
  801.         // If the changelog isn't an array then it was passed in as an empty tag
  802.         if (isset($pinfo['changelog']&& !is_array($pinfo['changelog'])) {
  803.           unset($pinfo['changelog']);
  804.         }
  805.         $this->_incomplete = false;
  806.         $this->_packageInfo $pinfo;
  807.     }
  808.  
  809.     function isIncomplete()
  810.     {
  811.         return $this->_incomplete;
  812.     }
  813.  
  814.     /**
  815.      * @return array 
  816.      */
  817.     function toArray($forreg = false)
  818.     {
  819.         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
  820.             return false;
  821.         }
  822.         return $this->getArray($forreg);
  823.     }
  824.  
  825.     function getArray($forReg = false)
  826.     {
  827.         if ($forReg{
  828.             $arr $this->_packageInfo;
  829.             $arr['old'= array();
  830.             $arr['old']['version'$this->getVersion();
  831.             $arr['old']['release_date'$this->getDate();
  832.             $arr['old']['release_state'$this->getState();
  833.             $arr['old']['release_license'$this->getLicense();
  834.             $arr['old']['release_notes'$this->getNotes();
  835.             $arr['old']['release_deps'$this->getDeps();
  836.             $arr['old']['maintainers'$this->getMaintainers();
  837.             $arr['xsdversion''2.0';
  838.             return $arr;
  839.         else {
  840.             $info $this->_packageInfo;
  841.             unset($info['dirtree']);
  842.             if (isset($info['_lastversion'])) {
  843.                 unset($info['_lastversion']);
  844.             }
  845.             if (isset($info['#binarypackage'])) {
  846.                 unset($info['#binarypackage']);
  847.             }
  848.             return $info;
  849.         }
  850.     }
  851.  
  852.     function packageInfo($field)
  853.     {
  854.         $arr $this->getArray(true);
  855.         if ($field == 'state'{
  856.             return $arr['stability']['release'];
  857.         }
  858.         if ($field == 'api-version'{
  859.             return $arr['version']['api'];
  860.         }
  861.         if ($field == 'api-state'{
  862.             return $arr['stability']['api'];
  863.         }
  864.         if (isset($arr['old'][$field])) {
  865.             if (!is_string($arr['old'][$field])) {
  866.                 return null;
  867.             }
  868.             return $arr['old'][$field];
  869.         }
  870.         if (isset($arr[$field])) {
  871.             if (!is_string($arr[$field])) {
  872.                 return null;
  873.             }
  874.             return $arr[$field];
  875.         }
  876.         return null;
  877.     }
  878.  
  879.     function getName()
  880.     {
  881.         return $this->getPackage();
  882.     }
  883.  
  884.     function getPackage()
  885.     {
  886.         if (isset($this->_packageInfo['name'])) {
  887.             return $this->_packageInfo['name'];
  888.         }
  889.         return false;
  890.     }
  891.  
  892.     function getChannel()
  893.     {
  894.         if (isset($this->_packageInfo['uri'])) {
  895.             return '__uri';
  896.         }
  897.         if (isset($this->_packageInfo['channel'])) {
  898.             return strtolower($this->_packageInfo['channel']);
  899.         }
  900.         return false;
  901.     }
  902.  
  903.     function getUri()
  904.     {
  905.         if (isset($this->_packageInfo['uri'])) {
  906.             return $this->_packageInfo['uri'];
  907.         }
  908.         return false;
  909.     }
  910.  
  911.     function getExtends()
  912.     {
  913.         if (isset($this->_packageInfo['extends'])) {
  914.             return $this->_packageInfo['extends'];
  915.         }
  916.         return false;
  917.     }
  918.  
  919.     function getSummary()
  920.     {
  921.         if (isset($this->_packageInfo['summary'])) {
  922.             return $this->_packageInfo['summary'];
  923.         }
  924.         return false;
  925.     }
  926.  
  927.     function getDescription()
  928.     {
  929.         if (isset($this->_packageInfo['description'])) {
  930.             return $this->_packageInfo['description'];
  931.         }
  932.         return false;
  933.     }
  934.  
  935.     function getMaintainers($raw = false)
  936.     {
  937.         if (!isset($this->_packageInfo['lead'])) {
  938.             return false;
  939.         }
  940.         if ($raw{
  941.             $ret = array('lead' => $this->_packageInfo['lead']);
  942.             (isset($this->_packageInfo['developer'])) ?
  943.                 $ret['developer'$this->_packageInfo['developer':null;
  944.             (isset($this->_packageInfo['contributor'])) ?
  945.                 $ret['contributor'$this->_packageInfo['contributor':null;
  946.             (isset($this->_packageInfo['helper'])) ?
  947.                 $ret['helper'$this->_packageInfo['helper':null;
  948.             return $ret;
  949.         else {
  950.             $ret = array();
  951.             $leads = isset($this->_packageInfo['lead'][0]$this->_packageInfo['lead':
  952.                 array($this->_packageInfo['lead']);
  953.             foreach ($leads as $lead{
  954.                 $s $lead;
  955.                 $s['handle'$s['user'];
  956.                 unset($s['user']);
  957.                 $s['role''lead';
  958.                 $ret[$s;
  959.             }
  960.             if (isset($this->_packageInfo['developer'])) {
  961.                 $leads = isset($this->_packageInfo['developer'][0]?
  962.                     $this->_packageInfo['developer':
  963.                     array($this->_packageInfo['developer']);
  964.                 foreach ($leads as $maintainer{
  965.                     $s $maintainer;
  966.                     $s['handle'$s['user'];
  967.                     unset($s['user']);
  968.                     $s['role''developer';
  969.                     $ret[$s;
  970.                 }
  971.             }
  972.             if (isset($this->_packageInfo['contributor'])) {
  973.                 $leads = isset($this->_packageInfo['contributor'][0]?
  974.                     $this->_packageInfo['contributor':
  975.                     array($this->_packageInfo['contributor']);
  976.                 foreach ($leads as $maintainer{
  977.                     $s $maintainer;
  978.                     $s['handle'$s['user'];
  979.                     unset($s['user']);
  980.                     $s['role''contributor';
  981.                     $ret[$s;
  982.                 }
  983.             }
  984.             if (isset($this->_packageInfo['helper'])) {
  985.                 $leads = isset($this->_packageInfo['helper'][0]?
  986.                     $this->_packageInfo['helper':
  987.                     array($this->_packageInfo['helper']);
  988.                 foreach ($leads as $maintainer{
  989.                     $s $maintainer;
  990.                     $s['handle'$s['user'];
  991.                     unset($s['user']);
  992.                     $s['role''helper';
  993.                     $ret[$s;
  994.                 }
  995.             }
  996.             return $ret;
  997.         }
  998.         return false;
  999.     }
  1000.  
  1001.     function getLeads()
  1002.     {
  1003.         if (isset($this->_packageInfo['lead'])) {
  1004.             return $this->_packageInfo['lead'];
  1005.         }
  1006.         return false;
  1007.     }
  1008.  
  1009.     function getDevelopers()
  1010.     {
  1011.         if (isset($this->_packageInfo['developer'])) {
  1012.             return $this->_packageInfo['developer'];
  1013.         }
  1014.         return false;
  1015.     }
  1016.  
  1017.     function getContributors()
  1018.     {
  1019.         if (isset($this->_packageInfo['contributor'])) {
  1020.             return $this->_packageInfo['contributor'];
  1021.         }
  1022.         return false;
  1023.     }
  1024.  
  1025.     function getHelpers()
  1026.     {
  1027.         if (isset($this->_packageInfo['helper'])) {
  1028.             return $this->_packageInfo['helper'];
  1029.         }
  1030.         return false;
  1031.     }
  1032.  
  1033.     function setDate($date)
  1034.     {
  1035.         if (!isset($this->_packageInfo['date'])) {
  1036.             // ensure that the extends tag is set up in the right location
  1037.             $this->_packageInfo $this->_insertBefore($this->_packageInfo,
  1038.                 array('time''version',
  1039.                     'stability''license''notes''contents''compatible',
  1040.                     'dependencies''providesextension''srcpackage''srcuri',
  1041.                     'phprelease''extsrcrelease''extbinrelease''zendextsrcrelease',
  1042.                     'zendextbinrelease''bundle''changelog')array()'date');
  1043.         }
  1044.         $this->_packageInfo['date'$date;
  1045.         $this->_isValid = 0;
  1046.     }
  1047.  
  1048.     function setTime($time)
  1049.     {
  1050.         $this->_isValid = 0;
  1051.         if (!isset($this->_packageInfo['time'])) {
  1052.             // ensure that the time tag is set up in the right location
  1053.             $this->_packageInfo $this->_insertBefore($this->_packageInfo,
  1054.                     array('version',
  1055.                     'stability''license''notes''contents''compatible',
  1056.                     'dependencies''providesextension''srcpackage''srcuri',
  1057.                     'phprelease''extsrcrelease''extbinrelease''zendextsrcrelease',
  1058.                     'zendextbinrelease''bundle''changelog')$time'time');
  1059.         }
  1060.         $this->_packageInfo['time'$time;
  1061.     }
  1062.  
  1063.     function getDate()
  1064.     {
  1065.         if (isset($this->_packageInfo['date'])) {
  1066.             return $this->_packageInfo['date'];
  1067.         }
  1068.         return false;
  1069.     }
  1070.  
  1071.     function getTime()
  1072.     {
  1073.         if (isset($this->_packageInfo['time'])) {
  1074.             return $this->_packageInfo['time'];
  1075.         }
  1076.         return false;
  1077.     }
  1078.  
  1079.     /**
  1080.      * @param package|apiversion category to return
  1081.      */
  1082.     function getVersion($key 'release')
  1083.     {
  1084.         if (isset($this->_packageInfo['version'][$key])) {
  1085.             return $this->_packageInfo['version'][$key];
  1086.         }
  1087.         return false;
  1088.     }
  1089.  
  1090.     function getStability()
  1091.     {
  1092.         if (isset($this->_packageInfo['stability'])) {
  1093.             return $this->_packageInfo['stability'];
  1094.         }
  1095.         return false;
  1096.     }
  1097.  
  1098.     function getState($key 'release')
  1099.     {
  1100.         if (isset($this->_packageInfo['stability'][$key])) {
  1101.             return $this->_packageInfo['stability'][$key];
  1102.         }
  1103.         return false;
  1104.     }
  1105.  
  1106.     function getLicense($raw = false)
  1107.     {
  1108.         if (isset($this->_packageInfo['license'])) {
  1109.             if ($raw{
  1110.                 return $this->_packageInfo['license'];
  1111.             }
  1112.             if (is_array($this->_packageInfo['license'])) {
  1113.                 return $this->_packageInfo['license']['_content'];
  1114.             else {
  1115.                 return $this->_packageInfo['license'];
  1116.             }
  1117.         }
  1118.         return false;
  1119.     }
  1120.  
  1121.     function getLicenseLocation()
  1122.     {
  1123.         if (!isset($this->_packageInfo['license']|| !is_array($this->_packageInfo['license'])) {
  1124.             return false;
  1125.         }
  1126.         return $this->_packageInfo['license']['attribs'];
  1127.     }
  1128.  
  1129.     function getNotes()
  1130.     {
  1131.         if (isset($this->_packageInfo['notes'])) {
  1132.             return $this->_packageInfo['notes'];
  1133.         }
  1134.         return false;
  1135.     }
  1136.  
  1137.     /**
  1138.      * Return the <usesrole> tag contents, if any
  1139.      * @return array|false
  1140.      */
  1141.     function getUsesrole()
  1142.     {
  1143.         if (isset($this->_packageInfo['usesrole'])) {
  1144.             return $this->_packageInfo['usesrole'];
  1145.         }
  1146.         return false;
  1147.     }
  1148.  
  1149.     /**
  1150.      * Return the <usestask> tag contents, if any
  1151.      * @return array|false
  1152.      */
  1153.     function getUsestask()
  1154.     {
  1155.         if (isset($this->_packageInfo['usestask'])) {
  1156.             return $this->_packageInfo['usestask'];
  1157.         }
  1158.         return false;
  1159.     }
  1160.  
  1161.     /**
  1162.      * This should only be used to retrieve filenames and install attributes
  1163.      */
  1164.     function getFilelist($preserve = false)
  1165.     {
  1166.         if (isset($this->_packageInfo['filelist']&& !$preserve{
  1167.             return $this->_packageInfo['filelist'];
  1168.         }
  1169.         $this->flattenFilelist();
  1170.         if ($contents $this->getContents()) {
  1171.             $ret = array();
  1172.             if (!isset($contents['dir'])) {
  1173.                 return false;
  1174.             }
  1175.             if (!isset($contents['dir']['file'][0])) {
  1176.                 $contents['dir']['file'= array($contents['dir']['file']);
  1177.             }
  1178.             foreach ($contents['dir']['file'as $file{
  1179.                 $name $file['attribs']['name'];
  1180.                 if (!$preserve{
  1181.                     $file $file['attribs'];
  1182.                 }
  1183.                 $ret[$name$file;
  1184.             }
  1185.             if (!$preserve{
  1186.                 $this->_packageInfo['filelist'$ret;
  1187.             }
  1188.             return $ret;
  1189.         }
  1190.         return false;
  1191.     }
  1192.  
  1193.     /**
  1194.      * Return configure options array, if any
  1195.      *
  1196.      * @return array|false
  1197.      */
  1198.     function getConfigureOptions()
  1199.     {
  1200.         if ($this->getPackageType(!= 'extsrc' && $this->getPackageType(!= 'zendextsrc'{
  1201.             return false;
  1202.         }
  1203.  
  1204.         $releases $this->getReleases();
  1205.         if (isset($releases[0])) {
  1206.             $releases $releases[0];
  1207.         }
  1208.  
  1209.         if (isset($releases['configureoption'])) {
  1210.             if (!isset($releases['configureoption'][0])) {
  1211.                 $releases['configureoption'= array($releases['configureoption']);
  1212.             }
  1213.  
  1214.             for ($i = 0; $i count($releases['configureoption'])$i++{
  1215.                 $releases['configureoption'][$i$releases['configureoption'][$i]['attribs'];
  1216.             }
  1217.  
  1218.             return $releases['configureoption'];
  1219.         }
  1220.  
  1221.         return false;
  1222.     }
  1223.  
  1224.     /**
  1225.      * This is only used at install-time, after all serialization
  1226.      * is over.
  1227.      */
  1228.     function resetFilelist()
  1229.     {
  1230.         $this->_packageInfo['filelist'= array();
  1231.     }
  1232.  
  1233.     /**
  1234.      * Retrieve a list of files that should be installed on this computer
  1235.      * @return array 
  1236.      */
  1237.     function getInstallationFilelist($forfilecheck = false)
  1238.     {
  1239.         $contents $this->getFilelist(true);
  1240.         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
  1241.             $base $contents['dir']['attribs']['baseinstalldir'];
  1242.         }
  1243.         if (isset($this->_packageInfo['bundle'])) {
  1244.             return PEAR::raiseError(
  1245.                 'Exception: bundles should be handled in download code only');
  1246.         }
  1247.         $release $this->getReleases();
  1248.         if ($release{
  1249.             if (!isset($release[0])) {
  1250.                 if (!isset($release['installconditions']&& !isset($release['filelist'])) {
  1251.                     if ($forfilecheck{
  1252.                         return $this->getFilelist();
  1253.                     }
  1254.                     return $contents;
  1255.                 }
  1256.                 $release = array($release);
  1257.             }
  1258.             $depchecker &$this->getPEARDependency2($this->_configarray(),
  1259.                 array('channel' => $this->getChannel()'package' => $this->getPackage()),
  1260.                 PEAR_VALIDATE_INSTALLING);
  1261.             foreach ($release as $instance{
  1262.                 if (isset($instance['installconditions'])) {
  1263.                     $installconditions $instance['installconditions'];
  1264.                     if (is_array($installconditions)) {
  1265.                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1266.                         foreach ($installconditions as $type => $conditions{
  1267.                             if (!isset($conditions[0])) {
  1268.                                 $conditions = array($conditions);
  1269.                             }
  1270.                             foreach ($conditions as $condition{
  1271.                                 $ret $depchecker->{"validate{$type}Dependency"}($condition);
  1272.                                 if (PEAR::isError($ret)) {
  1273.                                     PEAR::popErrorHandling();
  1274.                                     continue 3; // skip this release
  1275.                                 }
  1276.                             }
  1277.                         }
  1278.                         PEAR::popErrorHandling();
  1279.                     }
  1280.                 }
  1281.                 // this is the release to use
  1282.                 if (isset($instance['filelist'])) {
  1283.                     // ignore files
  1284.                     if (isset($instance['filelist']['ignore'])) {
  1285.                         $ignore = isset($instance['filelist']['ignore'][0]?
  1286.                             $instance['filelist']['ignore':
  1287.                             array($instance['filelist']['ignore']);
  1288.                         foreach ($ignore as $ig{
  1289.                             unset ($contents[$ig['attribs']['name']]);
  1290.                         }
  1291.                     }
  1292.                     // install files as this name
  1293.                     if (isset($instance['filelist']['install'])) {
  1294.                         $installas = isset($instance['filelist']['install'][0]?
  1295.                             $instance['filelist']['install':
  1296.                             array($instance['filelist']['install']);
  1297.                         foreach ($installas as $as{
  1298.                             $contents[$as['attribs']['name']]['attribs']['install-as'=
  1299.                                 $as['attribs']['as'];
  1300.                         }
  1301.                     }
  1302.                 }
  1303.                 if ($forfilecheck{
  1304.                     foreach ($contents as $file => $attrs{
  1305.                         $contents[$file$attrs['attribs'];
  1306.                     }
  1307.                 }
  1308.                 return $contents;
  1309.             }
  1310.         else // simple release - no installconditions or install-as
  1311.             if ($forfilecheck{
  1312.                 return $this->getFilelist();
  1313.             }
  1314.             return $contents;
  1315.         }
  1316.         // no releases matched
  1317.         return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
  1318.             'system, extensions installed, or architecture, cannot install');
  1319.     }
  1320.  
  1321.     /**
  1322.      * This is only used at install-time, after all serialization
  1323.      * is over.
  1324.      * @param string file name
  1325.      * @param string installed path
  1326.      */
  1327.     function setInstalledAs($file$path)
  1328.     {
  1329.         if ($path{
  1330.             return $this->_packageInfo['filelist'][$file]['installed_as'$path;
  1331.         }
  1332.         unset($this->_packageInfo['filelist'][$file]['installed_as']);
  1333.     }
  1334.  
  1335.     function getInstalledLocation($file)
  1336.     {
  1337.         if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
  1338.             return $this->_packageInfo['filelist'][$file]['installed_as'];
  1339.         }
  1340.         return false;
  1341.     }
  1342.  
  1343.     /**
  1344.      * This is only used at install-time, after all serialization
  1345.      * is over.
  1346.      */
  1347.     function installedFile($file$atts)
  1348.     {
  1349.         if (isset($this->_packageInfo['filelist'][$file])) {
  1350.             $this->_packageInfo['filelist'][$file=
  1351.                 array_merge($this->_packageInfo['filelist'][$file]$atts['attribs']);
  1352.         else {
  1353.             $this->_packageInfo['filelist'][$file$atts['attribs'];
  1354.         }
  1355.     }
  1356.  
  1357.     /**
  1358.      * Retrieve the contents tag
  1359.      */
  1360.     function getContents()
  1361.     {
  1362.         if (isset($this->_packageInfo['contents'])) {
  1363.             return $this->_packageInfo['contents'];
  1364.         }
  1365.         return false;
  1366.     }
  1367.  
  1368.     /**
  1369.      * @param string full path to file
  1370.      * @param string attribute name
  1371.      * @param string attribute value
  1372.      * @param int risky but fast - use this to choose a file based on its position in the list
  1373.      *             of files.  Index is zero-based like PHP arrays.
  1374.      * @return bool success of operation
  1375.      */
  1376.     function setFileAttribute($filename$attr$value$index = false)
  1377.     {
  1378.         $this->_isValid = 0;
  1379.         if (in_array($attrarray('role''name''baseinstalldir'))) {
  1380.             $this->_filesValid = false;
  1381.         }
  1382.         if ($index !== false &&
  1383.               isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
  1384.             $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr$value;
  1385.             return true;
  1386.         }
  1387.         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
  1388.             return false;
  1389.         }
  1390.         $files $this->_packageInfo['contents']['dir']['file'];
  1391.         if (!isset($files[0])) {
  1392.             $files = array($files);
  1393.             $ind = false;
  1394.         else {
  1395.             $ind = true;
  1396.         }
  1397.         foreach ($files as $i => $file{
  1398.             if (isset($file['attribs'])) {
  1399.                 if ($file['attribs']['name'== $filename{
  1400.                     if ($ind{
  1401.                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr$value;
  1402.                     else {
  1403.                         $this->_packageInfo['contents']['dir']['file']['attribs'][$attr$value;
  1404.                     }
  1405.                     return true;
  1406.                 }
  1407.             }
  1408.         }
  1409.         return false;
  1410.     }
  1411.  
  1412.     function setDirtree($path)
  1413.     {
  1414.         if (!isset($this->_packageInfo['dirtree'])) {
  1415.             $this->_packageInfo['dirtree'= array();
  1416.         }
  1417.         $this->_packageInfo['dirtree'][$path= true;
  1418.     }
  1419.  
  1420.     function getDirtree()
  1421.     {
  1422.         if (isset($this->_packageInfo['dirtree']&& count($this->_packageInfo['dirtree'])) {
  1423.             return $this->_packageInfo['dirtree'];
  1424.         }
  1425.         return false;
  1426.     }
  1427.  
  1428.     function resetDirtree()
  1429.     {
  1430.         unset($this->_packageInfo['dirtree']);
  1431.     }
  1432.  
  1433.     /**
  1434.      * Determines whether this package claims it is compatible with the version of
  1435.      * the package that has a recommended version dependency
  1436.      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
  1437.      * @return boolean 
  1438.      */
  1439.     function isCompatible($pf)
  1440.     {
  1441.         if (!isset($this->_packageInfo['compatible'])) {
  1442.             return false;
  1443.         }
  1444.         if (!isset($this->_packageInfo['channel'])) {
  1445.             return false;
  1446.         }
  1447.         $me $pf->getVersion();
  1448.         $compatible $this->_packageInfo['compatible'];
  1449.         if (!isset($compatible[0])) {
  1450.             $compatible = array($compatible);
  1451.         }
  1452.         $found = false;
  1453.         foreach ($compatible as $info{
  1454.             if (strtolower($info['name']== strtolower($pf->getPackage())) {
  1455.                 if (strtolower($info['channel']== strtolower($pf->getChannel())) {
  1456.                     $found = true;
  1457.                     break;
  1458.                 }
  1459.             }
  1460.         }
  1461.         if (!$found{
  1462.             return false;
  1463.         }
  1464.         if (isset($info['exclude'])) {
  1465.             if (!isset($info['exclude'][0])) {
  1466.                 $info['exclude'= array($info['exclude']);
  1467.             }
  1468.             foreach ($info['exclude'as $exclude{
  1469.                 if (version_compare($me$exclude'==')) {
  1470.                     return false;
  1471.                 }
  1472.             }
  1473.         }
  1474.         if (version_compare($me$info['min']'>='&& version_compare($me$info['max']'<=')) {
  1475.             return true;
  1476.         }
  1477.         return false;
  1478.     }
  1479.  
  1480.     /**
  1481.      * @return array|false
  1482.      */
  1483.     function getCompatible()
  1484.     {
  1485.         if (isset($this->_packageInfo['compatible'])) {
  1486.             return $this->_packageInfo['compatible'];
  1487.         }
  1488.         return false;
  1489.     }
  1490.  
  1491.     function getDependencies()
  1492.     {
  1493.         if (isset($this->_packageInfo['dependencies'])) {
  1494.             return $this->_packageInfo['dependencies'];
  1495.         }
  1496.         return false;
  1497.     }
  1498.  
  1499.     function isSubpackageOf($p)
  1500.     {
  1501.         return $p->isSubpackage($this);
  1502.     }
  1503.  
  1504.     /**
  1505.      * Determines whether the passed in package is a subpackage of this package.
  1506.      *
  1507.      * No version checking is done, only name verification.
  1508.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  1509.      * @return bool 
  1510.      */
  1511.     function isSubpackage($p)
  1512.     {
  1513.         $sub = array();
  1514.         if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
  1515.             $sub $this->_packageInfo['dependencies']['required']['subpackage'];
  1516.             if (!isset($sub[0])) {
  1517.                 $sub = array($sub);
  1518.             }
  1519.         }
  1520.         if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
  1521.             $sub1 $this->_packageInfo['dependencies']['optional']['subpackage'];
  1522.             if (!isset($sub1[0])) {
  1523.                 $sub1 = array($sub1);
  1524.             }
  1525.             $sub array_merge($sub$sub1);
  1526.         }
  1527.         if (isset($this->_packageInfo['dependencies']['group'])) {
  1528.             $group $this->_packageInfo['dependencies']['group'];
  1529.             if (!isset($group[0])) {
  1530.                 $group = array($group);
  1531.             }
  1532.             foreach ($group as $deps{
  1533.                 if (isset($deps['subpackage'])) {
  1534.                     $sub2 $deps['subpackage'];
  1535.                     if (!isset($sub2[0])) {
  1536.                         $sub2 = array($sub2);
  1537.                     }
  1538.                     $sub array_merge($sub$sub2);
  1539.                 }
  1540.             }
  1541.         }
  1542.         foreach ($sub as $dep{
  1543.             if (strtolower($dep['name']== strtolower($p->getPackage())) {
  1544.                 if (isset($dep['channel'])) {
  1545.                     if (strtolower($dep['channel']== strtolower($p->getChannel())) {
  1546.                         return true;
  1547.                     }
  1548.                 else {
  1549.                     if ($dep['uri'== $p->getURI()) {
  1550.                         return true;
  1551.                     }
  1552.                 }
  1553.             }
  1554.         }
  1555.         return false;
  1556.     }
  1557.  
  1558.     function dependsOn($package$channel)
  1559.     {
  1560.         if (!($deps $this->getDependencies())) {
  1561.             return false;
  1562.         }
  1563.         foreach (array('package''subpackage'as $type{
  1564.             foreach (array('required''optional'as $needed{
  1565.                 if (isset($deps[$needed][$type])) {
  1566.                     if (!isset($deps[$needed][$type][0])) {
  1567.                         $deps[$needed][$type= array($deps[$needed][$type]);
  1568.                     }
  1569.                     foreach ($deps[$needed][$typeas $dep{
  1570.                         $depchannel = isset($dep['channel']$dep['channel''__uri';
  1571.                         if (strtolower($dep['name']== strtolower($package&&
  1572.                               $depchannel == $channel{
  1573.                             return true;
  1574.                         }
  1575.                     }
  1576.                 }
  1577.             }
  1578.             if (isset($deps['group'])) {
  1579.                 if (!isset($deps['group'][0])) {
  1580.                     $dep['group'= array($deps['group']);
  1581.                 }
  1582.                 foreach ($deps['group'as $group{
  1583.                     if (isset($group[$type])) {
  1584.                         if (!is_array($group[$type])) {
  1585.                             $group[$type= array($group[$type]);
  1586.                         }
  1587.                         foreach ($group[$typeas $dep{
  1588.                             $depchannel = isset($dep['channel']$dep['channel''__uri';
  1589.                             if (strtolower($dep['name']== strtolower($package&&
  1590.                                   $depchannel == $channel{
  1591.                                 return true;
  1592.                             }
  1593.                         }
  1594.                     }
  1595.                 }
  1596.             }
  1597.         }
  1598.         return false;
  1599.     }
  1600.  
  1601.     /**
  1602.      * Get the contents of a dependency group
  1603.      * @param string 
  1604.      * @return array|false
  1605.      */
  1606.     function getDependencyGroup($name)
  1607.     {
  1608.         $name strtolower($name);
  1609.         if (!isset($this->_packageInfo['dependencies']['group'])) {
  1610.             return false;
  1611.         }
  1612.         $groups $this->_packageInfo['dependencies']['group'];
  1613.         if (!isset($groups[0])) {
  1614.             $groups = array($groups);
  1615.         }
  1616.         foreach ($groups as $group{
  1617.             if (strtolower($group['attribs']['name']== $name{
  1618.                 return $group;
  1619.             }
  1620.         }
  1621.         return false;
  1622.     }
  1623.  
  1624.     /**
  1625.      * Retrieve a partial package.xml 1.0 representation of dependencies
  1626.      *
  1627.      * a very limited representation of dependencies is returned by this method.
  1628.      * The <exclude> tag for excluding certain versions of a dependency is
  1629.      * completely ignored.  In addition, dependency groups are ignored, with the
  1630.      * assumption that all dependencies in dependency groups are also listed in
  1631.      * the optional group that work with all dependency groups
  1632.      * @param boolean return package.xml 2.0 <dependencies> tag
  1633.      * @return array|false
  1634.      */
  1635.     function getDeps($raw = false$nopearinstaller = false)
  1636.     {
  1637.         if (isset($this->_packageInfo['dependencies'])) {
  1638.             if ($raw{
  1639.                 return $this->_packageInfo['dependencies'];
  1640.             }
  1641.             $ret = array();
  1642.             $map = array(
  1643.                 'php' => 'php',
  1644.                 'package' => 'pkg',
  1645.                 'subpackage' => 'pkg',
  1646.                 'extension' => 'ext',
  1647.                 'os' => 'os',
  1648.                 'pearinstaller' => 'pkg',
  1649.                 );
  1650.             foreach (array('required''optional'as $type{
  1651.                 $optional ($type == 'optional''yes' 'no';
  1652.                 if (!isset($this->_packageInfo['dependencies'][$type])
  1653.                     || empty($this->_packageInfo['dependencies'][$type])) {
  1654.                     continue;
  1655.                 }
  1656.                 foreach ($this->_packageInfo['dependencies'][$typeas $dtype => $deps{
  1657.                     if ($dtype == 'pearinstaller' && $nopearinstaller{
  1658.                         continue;
  1659.                     }
  1660.                     if (!isset($deps[0])) {
  1661.                         $deps = array($deps);
  1662.                     }
  1663.                     foreach ($deps as $dep{
  1664.                         if (!isset($map[$dtype])) {
  1665.                             // no support for arch type
  1666.                             continue;
  1667.                         }
  1668.                         if ($dtype == 'pearinstaller'{
  1669.                             $dep['name''PEAR';
  1670.                             $dep['channel''pear.php.net';
  1671.                         }
  1672.                         $s = array('type' => $map[$dtype]);
  1673.                         if (isset($dep['channel'])) {
  1674.                             $s['channel'$dep['channel'];
  1675.                         }
  1676.                         if (isset($dep['uri'])) {
  1677.                             $s['uri'$dep['uri'];
  1678.                         }
  1679.                         if (isset($dep['name'])) {
  1680.                             $s['name'$dep['name'];
  1681.                         }
  1682.                         if (isset($dep['conflicts'])) {
  1683.                             $s['rel''not';
  1684.                         else {
  1685.                             if (!isset($dep['min']&&
  1686.                                   !isset($dep['max'])) {
  1687.                                 $s['rel''has';
  1688.                                 $s['optional'$optional;
  1689.                             elseif (isset($dep['min']&&
  1690.                                   isset($dep['max'])) {
  1691.                                 $s['rel''ge';
  1692.                                 $s1 $s;
  1693.                                 $s1['rel''le';
  1694.                                 $s['version'$dep['min'];
  1695.                                 $s1['version'$dep['max'];
  1696.                                 if (isset($dep['channel'])) {
  1697.                                     $s1['channel'$dep['channel'];
  1698.                                 }
  1699.                                 if ($dtype != 'php'{
  1700.                                     $s['name'$dep['name'];
  1701.                                     $s1['name'$dep['name'];
  1702.                                 }
  1703.                                 $s['optional'$optional;
  1704.                                 $s1['optional'$optional;
  1705.                                 $ret[$s1;
  1706.                             elseif (isset($dep['min'])) {
  1707.                                 if (isset($dep['exclude']&&
  1708.                                       $dep['exclude'== $dep['min']{
  1709.                                     $s['rel''gt';
  1710.                                 else {
  1711.                                     $s['rel''ge';
  1712.                                 }
  1713.                                 $s['version'$dep['min'];
  1714.                                 $s['optional'$optional;
  1715.                                 if ($dtype != 'php'{
  1716.                                     $s['name'$dep['name'];
  1717.                                 }
  1718.                             elseif (isset($dep['max'])) {
  1719.                                 if (isset($dep['exclude']&&
  1720.                                       $dep['exclude'== $dep['max']{
  1721.                                     $s['rel''lt';
  1722.                                 else {
  1723.                                     $s['rel''le';
  1724.                                 }
  1725.                                 $s['version'$dep['max'];
  1726.                                 $s['optional'$optional;
  1727.                                 if ($dtype != 'php'{
  1728.                                     $s['name'$dep['name'];
  1729.                                 }
  1730.                             }
  1731.                         }
  1732.                         $ret[$s;
  1733.                     }
  1734.                 }
  1735.             }
  1736.             if (count($ret)) {
  1737.                 return $ret;
  1738.             }
  1739.         }
  1740.         return false;
  1741.     }
  1742.  
  1743.     /**
  1744.      * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
  1745.      */
  1746.     function getPackageType()
  1747.     {
  1748.         if (isset($this->_packageInfo['phprelease'])) {
  1749.             return 'php';
  1750.         }
  1751.         if (isset($this->_packageInfo['extsrcrelease'])) {
  1752.             return 'extsrc';
  1753.         }
  1754.         if (isset($this->_packageInfo['extbinrelease'])) {
  1755.             return 'extbin';
  1756.         }
  1757.         if (isset($this->_packageInfo['zendextsrcrelease'])) {
  1758.             return 'zendextsrc';
  1759.         }
  1760.         if (isset($this->_packageInfo['zendextbinrelease'])) {
  1761.             return 'zendextbin';
  1762.         }
  1763.         if (isset($this->_packageInfo['bundle'])) {
  1764.             return 'bundle';
  1765.         }
  1766.         return false;
  1767.     }
  1768.  
  1769.     /**
  1770.      * @return array|false
  1771.      */
  1772.     function getReleases()
  1773.     {
  1774.         $type $this->getPackageType();
  1775.         if ($type != 'bundle'{
  1776.             $type .= 'release';
  1777.         }
  1778.         if ($this->getPackageType(&& isset($this->_packageInfo[$type])) {
  1779.             return $this->_packageInfo[$type];
  1780.         }
  1781.         return false;
  1782.     }
  1783.  
  1784.     /**
  1785.      * @return array 
  1786.      */
  1787.     function getChangelog()
  1788.     {
  1789.         if (isset($this->_packageInfo['changelog'])) {
  1790.             return $this->_packageInfo['changelog'];
  1791.         }
  1792.         return false;
  1793.     }
  1794.  
  1795.     function hasDeps()
  1796.     {
  1797.         return isset($this->_packageInfo['dependencies']);
  1798.     }
  1799.  
  1800.     function getPackagexmlVersion()
  1801.     {
  1802.         if (isset($this->_packageInfo['zendextsrcrelease'])) {
  1803.             return '2.1';
  1804.         }
  1805.         if (isset($this->_packageInfo['zendextbinrelease'])) {
  1806.             return '2.1';
  1807.         }
  1808.         return '2.0';
  1809.     }
  1810.  
  1811.     /**
  1812.      * @return array|false
  1813.      */
  1814.     function getSourcePackage()
  1815.     {
  1816.         if (isset($this->_packageInfo['extbinrelease']||
  1817.               isset($this->_packageInfo['zendextbinrelease'])) {
  1818.             return array('channel' => $this->_packageInfo['srcchannel'],
  1819.                          'package' => $this->_packageInfo['srcpackage']);
  1820.         }
  1821.         return false;
  1822.     }
  1823.  
  1824.     function getBundledPackages()
  1825.     {
  1826.         if (isset($this->_packageInfo['bundle'])) {
  1827.             return $this->_packageInfo['contents']['bundledpackage'];
  1828.         }
  1829.         return false;
  1830.     }
  1831.  
  1832.     function getLastModified()
  1833.     {
  1834.         if (isset($this->_packageInfo['_lastmodified'])) {
  1835.             return $this->_packageInfo['_lastmodified'];
  1836.         }
  1837.         return false;
  1838.     }
  1839.  
  1840.     /**
  1841.      * Get the contents of a file listed within the package.xml
  1842.      * @param string 
  1843.      * @return string 
  1844.      */
  1845.     function getFileContents($file)
  1846.     {
  1847.         if ($this->_archiveFile == $this->_packageFile// unpacked
  1848.             $dir dirname($this->_packageFile);
  1849.             $file $dir . DIRECTORY_SEPARATOR . $file;
  1850.             $file str_replace(array('/''\\'),
  1851.                 array(DIRECTORY_SEPARATORDIRECTORY_SEPARATOR)$file);
  1852.             if (file_exists($file&& is_readable($file)) {
  1853.                 return implode(''file($file));
  1854.             }
  1855.         else // tgz
  1856.             $tar &new Archive_Tar($this->_archiveFile);
  1857.             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
  1858.             if ($file != 'package.xml' && $file != 'package2.xml'{
  1859.                 $file $this->getPackage('-' $this->getVersion('/' $file;
  1860.             }
  1861.             $file $tar->extractInString($file);
  1862.             $tar->popErrorHandling();
  1863.             if (PEAR::isError($file)) {
  1864.                 return PEAR::raiseError("Cannot locate file '$file' in archive");
  1865.             }
  1866.             return $file;
  1867.         }
  1868.     }
  1869.  
  1870.     function &getRW()
  1871.     {
  1872.         if (!class_exists('PEAR_PackageFile_v2_rw')) {
  1873.             require_once 'PEAR/PackageFile/v2/rw.php';
  1874.         }
  1875.         $a = new PEAR_PackageFile_v2_rw;
  1876.         foreach (get_object_vars($thisas $name => $unused{
  1877.             if (!isset($this->$name)) {
  1878.                 continue;
  1879.             }
  1880.             if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
  1881.                   $name == '_stack'{
  1882.                 $a->$name &$this->$name;
  1883.             else {
  1884.                 $a->$name $this->$name;
  1885.             }
  1886.         }
  1887.         return $a;
  1888.     }
  1889.  
  1890.     function &getDefaultGenerator()
  1891.     {
  1892.         if (!class_exists('PEAR_PackageFile_Generator_v2')) {
  1893.             require_once 'PEAR/PackageFile/Generator/v2.php';
  1894.         }
  1895.         $a &new PEAR_PackageFile_Generator_v2($this);
  1896.         return $a;
  1897.     }
  1898.  
  1899.     function analyzeSourceCode($file$string = false)
  1900.     {
  1901.         if (!isset($this->_v2Validator||
  1902.               !is_a($this->_v2Validator'PEAR_PackageFile_v2_Validator')) {
  1903.             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
  1904.                 require_once 'PEAR/PackageFile/v2/Validator.php';
  1905.             }
  1906.             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
  1907.         }
  1908.         return $this->_v2Validator->analyzeSourceCode($file$string);
  1909.     }
  1910.  
  1911.     function validate($state = PEAR_VALIDATE_NORMAL)
  1912.     {
  1913.         if (!isset($this->_packageInfo|| !is_array($this->_packageInfo)) {
  1914.             return false;
  1915.         }
  1916.         if (!isset($this->_v2Validator||
  1917.               !is_a($this->_v2Validator'PEAR_PackageFile_v2_Validator')) {
  1918.             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
  1919.                 require_once 'PEAR/PackageFile/v2/Validator.php';
  1920.             }
  1921.             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
  1922.         }
  1923.         if (isset($this->_packageInfo['xsdversion'])) {
  1924.             unset($this->_packageInfo['xsdversion']);
  1925.         }
  1926.         return $this->_v2Validator->validate($this$state);
  1927.     }
  1928.  
  1929.     function getTasksNs()
  1930.     {
  1931.         if (!isset($this->_tasksNs)) {
  1932.             if (isset($this->_packageInfo['attribs'])) {
  1933.                 foreach ($this->_packageInfo['attribs'as $name => $value{
  1934.                     if ($value == 'http://pear.php.net/dtd/tasks-1.0'{
  1935.                         $this->_tasksNs = str_replace('xmlns:'''$name);
  1936.                         break;
  1937.                     }
  1938.                 }
  1939.             }
  1940.         }
  1941.         return $this->_tasksNs;
  1942.     }
  1943.  
  1944.     /**
  1945.      * Determine whether a task name is a valid task.  Custom tasks may be defined
  1946.      * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
  1947.      *
  1948.      * Note that this method will auto-load the task class file and test for the existence
  1949.      * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
  1950.      * PEAR_Task_mycustom_task
  1951.      * @param string 
  1952.      * @return boolean 
  1953.      */
  1954.     function getTask($task)
  1955.     {
  1956.         $this->getTasksNs();
  1957.         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
  1958.         $task str_replace(array($this->_tasksNs . ':''-')array(''' ')$task);
  1959.         $taskfile str_replace(' ''/'ucwords($task));
  1960.         $task str_replace(array(' ''/')'_'ucwords($task));
  1961.         if (class_exists("PEAR_Task_$task")) {
  1962.             return "PEAR_Task_$task";
  1963.         }
  1964.         $fp @fopen("PEAR/Task/$taskfile.php"'r'true);
  1965.         if ($fp{
  1966.             fclose($fp);
  1967.             require_once "PEAR/Task/$taskfile.php";
  1968.             return "PEAR_Task_$task";
  1969.         }
  1970.         return false;
  1971.     }
  1972.  
  1973.     /**
  1974.      * Key-friendly array_splice
  1975.      * @param tagname to splice a value in before
  1976.      * @param mixed the value to splice in
  1977.      * @param string the new tag name
  1978.      */
  1979.     function _ksplice($array$key$value$newkey)
  1980.     {
  1981.         $offset array_search($keyarray_keys($array));
  1982.         $after array_slice($array$offset);
  1983.         $before array_slice($array0$offset);
  1984.         $before[$newkey$value;
  1985.         return array_merge($before$after);
  1986.     }
  1987.  
  1988.     /**
  1989.      * @param array a list of possible keys, in the order they may occur
  1990.      * @param mixed contents of the new package.xml tag
  1991.      * @param string tag name
  1992.      * @access private
  1993.      */
  1994.     function _insertBefore($array$keys$contents$newkey)
  1995.     {
  1996.         foreach ($keys as $key{
  1997.             if (isset($array[$key])) {
  1998.                 return $array $this->_ksplice($array$key$contents$newkey);
  1999.             }
  2000.         }
  2001.         $array[$newkey$contents;
  2002.         return $array;
  2003.     }
  2004.  
  2005.     /**
  2006.      * @param subsection of {@link $_packageInfo}
  2007.      * @param array|stringtag contents
  2008.      * @param array format:
  2009.      *  <pre>
  2010.      *  array(
  2011.      *    tagname => array(list of tag names that follow this one),
  2012.      *    childtagname => array(list of child tag names that follow this one),
  2013.      *  )
  2014.      *  </pre>
  2015.      *
  2016.      *  This allows construction of nested tags
  2017.      * @access private
  2018.      */
  2019.     function _mergeTag($manip$contents$order)
  2020.     {
  2021.         if (count($order)) {
  2022.             foreach ($order as $tag => $curorder{
  2023.                 if (!isset($manip[$tag])) {
  2024.                     // ensure that the tag is set up
  2025.                     $manip $this->_insertBefore($manip$curorderarray()$tag);
  2026.                 }
  2027.                 if (count($order> 1{
  2028.                     $manip[$tag$this->_mergeTag($manip[$tag]$contentsarray_slice($order1));
  2029.                     return $manip;
  2030.                 }
  2031.             }
  2032.         else {
  2033.             return $manip;
  2034.         }
  2035.         if (is_array($manip[$tag]&& !empty($manip[$tag]&& isset($manip[$tag][0])) {
  2036.             $manip[$tag][$contents;
  2037.         else {
  2038.             if (!count($manip[$tag])) {
  2039.                 $manip[$tag$contents;
  2040.             else {
  2041.                 $manip[$tag= array($manip[$tag]);
  2042.                 $manip[$tag][$contents;
  2043.             }
  2044.         }
  2045.         return $manip;
  2046.     }
  2047. }
  2048. ?>

Documentation generated on Wed, 06 Jul 2011 23:31:37 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.