[ Index ]
 

Code source de PHP PEAR 1.4.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/PEAR/PackageFile/ -> v2.php (source)

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


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7