home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / tmp / PEAR-1.7.1 / PEAR / PackageFile / v2 / rw.php next >
Encoding:
PHP Script  |  2008-02-15  |  62.0 KB  |  1,603 lines

  1. <?php
  2. /**
  3.  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
  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-2008 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id: rw.php,v 1.22 2008/01/18 22:47:49 cellog Exp $
  19.  * @link       http://pear.php.net/package/PEAR
  20.  * @since      File available since Release 1.4.0a8
  21.  */
  22. /**
  23.  * For base class
  24.  */
  25. require_once 'PEAR/PackageFile/v2.php';
  26. /**
  27.  * @category   pear
  28.  * @package    PEAR
  29.  * @author     Greg Beaver <cellog@php.net>
  30.  * @copyright  1997-2008 The PHP Group
  31.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  32.  * @version    Release: 1.7.1
  33.  * @link       http://pear.php.net/package/PEAR
  34.  * @since      Class available since Release 1.4.0a8
  35.  */
  36. class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
  37. {
  38.     /**
  39.      * @param string Extension name
  40.      * @return bool success of operation
  41.      */
  42.     function setProvidesExtension($extension)
  43.     {
  44.         if (in_array($this->getPackageType(),
  45.               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
  46.             if (!isset($this->_packageInfo['providesextension'])) {
  47.                 // ensure that the channel tag is set up in the right location
  48.                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  49.                     array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
  50.                     'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
  51.                     'bundle', 'changelog'),
  52.                     $extension, 'providesextension');
  53.             }
  54.             $this->_packageInfo['providesextension'] = $extension;
  55.             return true;
  56.         }
  57.         return false;
  58.     }
  59.  
  60.     function setPackage($package)
  61.     {
  62.         $this->_isValid = 0;
  63.         if (!isset($this->_packageInfo['attribs'])) {
  64.             $this->_packageInfo = array_merge(array('attribs' => array(
  65.                                  'version' => '2.0',
  66.                                  'xmlns' => 'http://pear.php.net/dtd/package-2.0',
  67.                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
  68.                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  69.                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
  70.     http://pear.php.net/dtd/tasks-1.0.xsd
  71.     http://pear.php.net/dtd/package-2.0
  72.     http://pear.php.net/dtd/package-2.0.xsd',
  73.                              )), $this->_packageInfo);
  74.         }
  75.         if (!isset($this->_packageInfo['name'])) {
  76.             return $this->_packageInfo = array_merge(array('name' => $package),
  77.                 $this->_packageInfo);
  78.         }
  79.         $this->_packageInfo['name'] = $package;
  80.     }
  81.  
  82.     /**
  83.      * set this as a package.xml version 2.1
  84.      * @access private
  85.      */
  86.     function _setPackageVersion2_1()
  87.     {
  88.         $info = array(
  89.                                  'version' => '2.1',
  90.                                  'xmlns' => 'http://pear.php.net/dtd/package-2.1',
  91.                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
  92.                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  93.                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
  94.     http://pear.php.net/dtd/tasks-1.0.xsd
  95.     http://pear.php.net/dtd/package-2.1
  96.     http://pear.php.net/dtd/package-2.1.xsd',
  97.                              );
  98.         if (!isset($this->_packageInfo['attribs'])) {
  99.             $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
  100.         } else {
  101.             $this->_packageInfo['attribs'] = $info;
  102.         }
  103.     }
  104.  
  105.     function setUri($uri)
  106.     {
  107.         unset($this->_packageInfo['channel']);
  108.         $this->_isValid = 0;
  109.         if (!isset($this->_packageInfo['uri'])) {
  110.             // ensure that the uri tag is set up in the right location
  111.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, 
  112.                 array('extends', 'summary', 'description', 'lead',
  113.                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
  114.                 'stability', 'license', 'notes', 'contents', 'compatible',
  115.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  116.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  117.                 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
  118.         }
  119.         $this->_packageInfo['uri'] = $uri;
  120.     }
  121.  
  122.     function setChannel($channel)
  123.     {
  124.         unset($this->_packageInfo['uri']);
  125.         $this->_isValid = 0;
  126.         if (!isset($this->_packageInfo['channel'])) {
  127.             // ensure that the channel tag is set up in the right location
  128.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  129.                 array('extends', 'summary', 'description', 'lead',
  130.                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
  131.                 'stability', 'license', 'notes', 'contents', 'compatible',
  132.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  133.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  134.                 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
  135.         }
  136.         $this->_packageInfo['channel'] = $channel;
  137.     }
  138.  
  139.     function setExtends($extends)
  140.     {
  141.         $this->_isValid = 0;
  142.         if (!isset($this->_packageInfo['extends'])) {
  143.             // ensure that the extends tag is set up in the right location
  144.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  145.                 array('summary', 'description', 'lead',
  146.                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
  147.                 'stability', 'license', 'notes', 'contents', 'compatible',
  148.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  149.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  150.                 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
  151.         }
  152.         $this->_packageInfo['extends'] = $extends;
  153.     }
  154.  
  155.     function setSummary($summary)
  156.     {
  157.         $this->_isValid = 0;
  158.         if (!isset($this->_packageInfo['summary'])) {
  159.             // ensure that the summary tag is set up in the right location
  160.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  161.                 array('description', 'lead',
  162.                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
  163.                 'stability', 'license', 'notes', 'contents', 'compatible',
  164.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  165.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  166.                 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
  167.         }
  168.         $this->_packageInfo['summary'] = $summary;
  169.     }
  170.  
  171.     function setDescription($desc)
  172.     {
  173.         $this->_isValid = 0;
  174.         if (!isset($this->_packageInfo['description'])) {
  175.             // ensure that the description tag is set up in the right location
  176.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  177.                 array('lead',
  178.                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
  179.                 'stability', 'license', 'notes', 'contents', 'compatible',
  180.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  181.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  182.                 'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
  183.         }
  184.         $this->_packageInfo['description'] = $desc;
  185.     }
  186.  
  187.     /**
  188.      * Adds a new maintainer - no checking of duplicates is performed, use
  189.      * updatemaintainer for that purpose.
  190.      */
  191.     function addMaintainer($role, $handle, $name, $email, $active = 'yes')
  192.     {
  193.         if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
  194.             return false;
  195.         }
  196.         if (isset($this->_packageInfo[$role])) {
  197.             if (!isset($this->_packageInfo[$role][0])) {
  198.                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
  199.             }
  200.             $this->_packageInfo[$role][] =
  201.                 array(
  202.                     'name' => $name,
  203.                     'user' => $handle,
  204.                     'email' => $email,
  205.                     'active' => $active,
  206.                 );
  207.         } else {
  208.             $testarr = array('lead',
  209.                     'developer', 'contributor', 'helper', 'date', 'time', 'version',
  210.                     'stability', 'license', 'notes', 'contents', 'compatible',
  211.                     'dependencies', 'providesextension', 'usesrole', 'usestask',
  212.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
  213.                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
  214.             foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
  215.                 array_shift($testarr);
  216.                 if ($role == $testrole) {
  217.                     break;
  218.                 }
  219.             }
  220.             if (!isset($this->_packageInfo[$role])) {
  221.                 // ensure that the extends tag is set up in the right location
  222.                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
  223.                     array(), $role);
  224.             }
  225.             $this->_packageInfo[$role] =
  226.                 array(
  227.                     'name' => $name,
  228.                     'user' => $handle,
  229.                     'email' => $email,
  230.                     'active' => $active,
  231.                 );
  232.         }
  233.         $this->_isValid = 0;
  234.     }
  235.  
  236.     function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
  237.     {
  238.         $found = false;
  239.         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
  240.             if (!isset($this->_packageInfo[$role])) {
  241.                 continue;
  242.             }
  243.             $info = $this->_packageInfo[$role];
  244.             if (!isset($info[0])) {
  245.                 if ($info['user'] == $handle) {
  246.                     $found = true;
  247.                     break;
  248.                 }
  249.             }
  250.             foreach ($info as $i => $maintainer) {
  251.                 if ($maintainer['user'] == $handle) {
  252.                     $found = $i;
  253.                     break 2;
  254.                 }
  255.             }
  256.         }
  257.         if ($found === false) {
  258.             return $this->addMaintainer($newrole, $handle, $name, $email, $active);
  259.         }
  260.         if ($found !== false) {
  261.             if ($found === true) {
  262.                 unset($this->_packageInfo[$role]);
  263.             } else {
  264.                 unset($this->_packageInfo[$role][$found]);
  265.                 $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
  266.             }
  267.         }
  268.         $this->addMaintainer($newrole, $handle, $name, $email, $active);
  269.         $this->_isValid = 0;
  270.     }
  271.  
  272.     function deleteMaintainer($handle)
  273.     {
  274.         $found = false;
  275.         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
  276.             if (!isset($this->_packageInfo[$role])) {
  277.                 continue;
  278.             }
  279.             if (!isset($this->_packageInfo[$role][0])) {
  280.                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
  281.             }
  282.             foreach ($this->_packageInfo[$role] as $i => $maintainer) {
  283.                 if ($maintainer['user'] == $handle) {
  284.                     $found = $i;
  285.                     break;
  286.                 }
  287.             }
  288.             if ($found !== false) {
  289.                 unset($this->_packageInfo[$role][$found]);
  290.                 if (!count($this->_packageInfo[$role]) && $role == 'lead') {
  291.                     $this->_isValid = 0;
  292.                 }
  293.                 if (!count($this->_packageInfo[$role])) {
  294.                     unset($this->_packageInfo[$role]);
  295.                     return true;
  296.                 }
  297.                 $this->_packageInfo[$role] =
  298.                     array_values($this->_packageInfo[$role]);
  299.                 if (count($this->_packageInfo[$role]) == 1) {
  300.                     $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
  301.                 }
  302.                 return true;
  303.             }
  304.             if (count($this->_packageInfo[$role]) == 1) {
  305.                 $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
  306.             }
  307.         }
  308.         return false;
  309.     }
  310.  
  311.     function setReleaseVersion($version)
  312.     {
  313.         if (isset($this->_packageInfo['version']) &&
  314.               isset($this->_packageInfo['version']['release'])) {
  315.             unset($this->_packageInfo['version']['release']);
  316.         }
  317.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
  318.             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
  319.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  320.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  321.                 'extbinrelease', 'bundle', 'changelog'),
  322.             'release' => array('api')));
  323.         $this->_isValid = 0;
  324.     }
  325.  
  326.     function setAPIVersion($version)
  327.     {
  328.         if (isset($this->_packageInfo['version']) &&
  329.               isset($this->_packageInfo['version']['api'])) {
  330.             unset($this->_packageInfo['version']['api']);
  331.         }
  332.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
  333.             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
  334.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  335.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  336.                 'extbinrelease', 'bundle', 'changelog'),
  337.             'api' => array()));
  338.         $this->_isValid = 0;
  339.     }
  340.  
  341.     /**
  342.      * snapshot|devel|alpha|beta|stable
  343.      */
  344.     function setReleaseStability($state)
  345.     {
  346.         if (isset($this->_packageInfo['stability']) &&
  347.               isset($this->_packageInfo['stability']['release'])) {
  348.             unset($this->_packageInfo['stability']['release']);
  349.         }
  350.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
  351.             'stability' => array('license', 'notes', 'contents', 'compatible',
  352.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  353.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  354.                 'extbinrelease', 'bundle', 'changelog'),
  355.             'release' => array('api')));
  356.         $this->_isValid = 0;
  357.     }
  358.  
  359.     /**
  360.      * @param devel|alpha|beta|stable
  361.      */
  362.     function setAPIStability($state)
  363.     {
  364.         if (isset($this->_packageInfo['stability']) &&
  365.               isset($this->_packageInfo['stability']['api'])) {
  366.             unset($this->_packageInfo['stability']['api']);
  367.         }
  368.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
  369.             'stability' => array('license', 'notes', 'contents', 'compatible',
  370.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  371.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  372.                 'extbinrelease', 'bundle', 'changelog'),
  373.             'api' => array()));
  374.         $this->_isValid = 0;
  375.     }
  376.  
  377.     function setLicense($license, $uri = false, $filesource = false)
  378.     {
  379.         if (!isset($this->_packageInfo['license'])) {
  380.             // ensure that the license tag is set up in the right location
  381.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  382.                 array('notes', 'contents', 'compatible',
  383.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  384.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  385.                 'extbinrelease', 'bundle', 'changelog'), 0, 'license');
  386.         }
  387.         if ($uri || $filesource) {
  388.             $attribs = array();
  389.             if ($uri) {
  390.                 $attribs['uri'] = $uri;
  391.             }
  392.             $uri = true; // for test below
  393.             if ($filesource) {
  394.                 $attribs['filesource'] = $filesource;
  395.             }
  396.         }
  397.         $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
  398.         $this->_packageInfo['license'] = $license;
  399.         $this->_isValid = 0;
  400.     }
  401.  
  402.     function setNotes($notes)
  403.     {
  404.         $this->_isValid = 0;
  405.         if (!isset($this->_packageInfo['notes'])) {
  406.             // ensure that the notes tag is set up in the right location
  407.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  408.                 array('contents', 'compatible',
  409.                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
  410.                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
  411.                 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
  412.         }
  413.         $this->_packageInfo['notes'] = $notes;
  414.     }
  415.  
  416.     /**
  417.      * This is only used at install-time, after all serialization
  418.      * is over.
  419.      * @param string file name
  420.      * @param string installed path
  421.      */
  422.     function setInstalledAs($file, $path)
  423.     {
  424.         if ($path) {
  425.             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
  426.         }
  427.         unset($this->_packageInfo['filelist'][$file]['installed_as']);
  428.     }
  429.  
  430.     /**
  431.      * This is only used at install-time, after all serialization
  432.      * is over.
  433.      */
  434.     function installedFile($file, $atts)
  435.     {
  436.         if (isset($this->_packageInfo['filelist'][$file])) {
  437.             $this->_packageInfo['filelist'][$file] =
  438.                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
  439.         } else {
  440.             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
  441.         }
  442.     }
  443.  
  444.     /**
  445.      * Reset the listing of package contents
  446.      * @param string base installation dir for the whole package, if any
  447.      */
  448.     function clearContents($baseinstall = false)
  449.     {
  450.         $this->_filesValid = false;
  451.         $this->_isValid = 0;
  452.         if (!isset($this->_packageInfo['contents'])) {
  453.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  454.                 array('compatible',
  455.                     'dependencies', 'providesextension', 'usesrole', 'usestask',
  456.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
  457.                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
  458.                     'bundle', 'changelog'), array(), 'contents');
  459.         }
  460.         if ($this->getPackageType() != 'bundle') {
  461.             $this->_packageInfo['contents'] = 
  462.                 array('dir' => array('attribs' => array('name' => '/')));
  463.             if ($baseinstall) {
  464.                 $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
  465.             }
  466.         } else {
  467.             $this->_packageInfo['contents'] = array('bundledpackage' => array());
  468.         }
  469.     }
  470.  
  471.     /**
  472.      * @param string relative path of the bundled package.
  473.      */
  474.     function addBundledPackage($path)
  475.     {
  476.         if ($this->getPackageType() != 'bundle') {
  477.             return false;
  478.         }
  479.         $this->_filesValid = false;
  480.         $this->_isValid = 0;
  481.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
  482.                 'contents' => array('compatible', 'dependencies', 'providesextension',
  483.                 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
  484.                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
  485.                 'bundle', 'changelog'),
  486.                 'bundledpackage' => array()));
  487.     }
  488.  
  489.     /**
  490.      * @param string file name
  491.      * @param PEAR_Task_Common a read/write task
  492.      */
  493.     function addTaskToFile($filename, $task)
  494.     {
  495.         if (!method_exists($task, 'getXml')) {
  496.             return false;
  497.         }
  498.         if (!method_exists($task, 'getName')) {
  499.             return false;
  500.         }
  501.         if (!method_exists($task, 'validate')) {
  502.             return false;
  503.         }
  504.         if (!$task->validate()) {
  505.             return false;
  506.         }
  507.         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
  508.             return false;
  509.         }
  510.         $this->getTasksNs(); // discover the tasks namespace if not done already
  511.         $files = $this->_packageInfo['contents']['dir']['file'];
  512.         if (!isset($files[0])) {
  513.             $files = array($files);
  514.             $ind = false;
  515.         } else {
  516.             $ind = true;
  517.         }
  518.         foreach ($files as $i => $file) {
  519.             if (isset($file['attribs'])) {
  520.                 if ($file['attribs']['name'] == $filename) {
  521.                     if ($ind) {
  522.                         $t = isset($this->_packageInfo['contents']['dir']['file'][$i]
  523.                               ['attribs'][$this->_tasksNs .
  524.                               ':' . $task->getName()]) ?
  525.                               $this->_packageInfo['contents']['dir']['file'][$i]
  526.                               ['attribs'][$this->_tasksNs .
  527.                               ':' . $task->getName()] : false;
  528.                         if ($t && !isset($t[0])) {
  529.                             $this->_packageInfo['contents']['dir']['file'][$i]
  530.                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
  531.                         }
  532.                         $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
  533.                             ':' . $task->getName()][] = $task->getXml();
  534.                     } else {
  535.                         $t = isset($this->_packageInfo['contents']['dir']['file']
  536.                               ['attribs'][$this->_tasksNs .
  537.                               ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
  538.                               ['attribs'][$this->_tasksNs .
  539.                               ':' . $task->getName()] : false;
  540.                         if ($t && !isset($t[0])) {
  541.                             $this->_packageInfo['contents']['dir']['file']
  542.                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
  543.                         }
  544.                         $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
  545.                             ':' . $task->getName()][] = $task->getXml();
  546.                     }
  547.                     return true;
  548.                 }
  549.             }
  550.         }
  551.         return false;
  552.     }
  553.  
  554.     /**
  555.      * @param string path to the file
  556.      * @param string filename
  557.      * @param array extra attributes
  558.      */
  559.     function addFile($dir, $file, $attrs)
  560.     {
  561.         if ($this->getPackageType() == 'bundle') {
  562.             return false;
  563.         }
  564.         $this->_filesValid = false;
  565.         $this->_isValid = 0;
  566.         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
  567.         if ($dir == '/' || $dir == '') {
  568.             $dir = '';
  569.         } else {
  570.             $dir .= '/';
  571.         }
  572.         $attrs['name'] = $dir . $file;
  573.         if (!isset($this->_packageInfo['contents'])) {
  574.             // ensure that the contents tag is set up
  575.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  576.                 array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
  577.                 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
  578.                 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
  579.                 'bundle', 'changelog'), array(), 'contents');
  580.         }
  581.         if (isset($this->_packageInfo['contents']['dir']['file'])) {
  582.             if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
  583.                 $this->_packageInfo['contents']['dir']['file'] =
  584.                     array($this->_packageInfo['contents']['dir']['file']);
  585.             }
  586.             $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
  587.         } else {
  588.             $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
  589.         }
  590.     }
  591.  
  592.     /**
  593.      * @param string Dependent package name
  594.      * @param string Dependent package's channel name
  595.      * @param string minimum version of specified package that this release is guaranteed to be
  596.      *               compatible with
  597.      * @param string maximum version of specified package that this release is guaranteed to be
  598.      *               compatible with
  599.      * @param string versions of specified package that this release is not compatible with
  600.      */
  601.     function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
  602.     {
  603.         $this->_isValid = 0;
  604.         $set = array(
  605.             'name' => $name,
  606.             'channel' => $channel,
  607.             'min' => $min,
  608.             'max' => $max,
  609.         );
  610.         if ($exclude) {
  611.             $set['exclude'] = $exclude;
  612.         }
  613.         $this->_isValid = 0;
  614.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
  615.                 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
  616.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  617.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
  618.             ));
  619.     }
  620.  
  621.     /**
  622.      * Removes the <usesrole> tag entirely
  623.      */
  624.     function resetUsesrole()
  625.     {
  626.         if (isset($this->_packageInfo['usesrole'])) {
  627.             unset($this->_packageInfo['usesrole']);
  628.         }
  629.     }
  630.  
  631.     /**
  632.      * @param string
  633.      * @param string package name or uri
  634.      * @param string channel name if non-uri
  635.      */
  636.     function addUsesrole($role, $packageOrUri, $channel = false) {
  637.         $set = array('role' => $role);
  638.         if ($channel) {
  639.             $set['package'] = $packageOrUri;
  640.             $set['channel'] = $channel;
  641.         } else {
  642.             $set['uri'] = $packageOrUri;
  643.         }
  644.         $this->_isValid = 0;
  645.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
  646.                 'usesrole' => array('usestask', 'srcpackage', 'srcuri',
  647.                     'phprelease', 'extsrcrelease', 'extbinrelease',
  648.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
  649.             ));
  650.     }
  651.  
  652.     /**
  653.      * Removes the <usestask> tag entirely
  654.      */
  655.     function resetUsestask()
  656.     {
  657.         if (isset($this->_packageInfo['usestask'])) {
  658.             unset($this->_packageInfo['usestask']);
  659.         }
  660.     }
  661.  
  662.  
  663.     /**
  664.      * @param string
  665.      * @param string package name or uri
  666.      * @param string channel name if non-uri
  667.      */
  668.     function addUsestask($task, $packageOrUri, $channel = false) {
  669.         $set = array('task' => $task);
  670.         if ($channel) {
  671.             $set['package'] = $packageOrUri;
  672.             $set['channel'] = $channel;
  673.         } else {
  674.             $set['uri'] = $packageOrUri;
  675.         }
  676.         $this->_isValid = 0;
  677.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
  678.                 'usestask' => array('srcpackage', 'srcuri',
  679.                     'phprelease', 'extsrcrelease', 'extbinrelease',
  680.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
  681.             ));
  682.     }
  683.  
  684.     /**
  685.      * Remove all compatible tags
  686.      */
  687.     function clearCompatible()
  688.     {
  689.         unset($this->_packageInfo['compatible']);
  690.     }
  691.  
  692.     /**
  693.      * Reset dependencies prior to adding new ones
  694.      */
  695.     function clearDeps()
  696.     {
  697.         if (!isset($this->_packageInfo['dependencies'])) {
  698.             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
  699.                 array(
  700.                     'dependencies' => array('providesextension', 'usesrole', 'usestask',
  701.                         'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  702.                         'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
  703.         }
  704.         $this->_packageInfo['dependencies'] = array();
  705.     }
  706.  
  707.     /**
  708.      * @param string minimum PHP version allowed
  709.      * @param string maximum PHP version allowed
  710.      * @param array $exclude incompatible PHP versions
  711.      */
  712.     function setPhpDep($min, $max = false, $exclude = false)
  713.     {
  714.         $this->_isValid = 0;
  715.         $dep =
  716.             array(
  717.                 'min' => $min,
  718.             );
  719.         if ($max) {
  720.             $dep['max'] = $max;
  721.         }
  722.         if ($exclude) {
  723.             if (count($exclude) == 1) {
  724.                 $exclude = $exclude[0];
  725.             }
  726.             $dep['exclude'] = $exclude;
  727.         }
  728.         if (isset($this->_packageInfo['dependencies']['required']['php'])) {
  729.             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
  730.             $this->_packageInfo['dependencies']['required']['php']),
  731.                 'warning: PHP dependency already exists, overwriting');
  732.             unset($this->_packageInfo['dependencies']['required']['php']);
  733.         }
  734.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  735.             array(
  736.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  737.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  738.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  739.                 'required' => array('optional', 'group'),
  740.                 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
  741.             ));
  742.         return true;
  743.     }
  744.  
  745.     /**
  746.      * @param string minimum allowed PEAR installer version
  747.      * @param string maximum allowed PEAR installer version
  748.      * @param string recommended PEAR installer version
  749.      * @param array incompatible version of the PEAR installer
  750.      */
  751.     function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
  752.     {
  753.         $this->_isValid = 0;
  754.         $dep =
  755.             array(
  756.                 'min' => $min,
  757.             );
  758.         if ($max) {
  759.             $dep['max'] = $max;
  760.         }
  761.         if ($recommended) {
  762.             $dep['recommended'] = $recommended;
  763.         }
  764.         if ($exclude) {
  765.             if (count($exclude) == 1) {
  766.                 $exclude = $exclude[0];
  767.             }
  768.             $dep['exclude'] = $exclude;
  769.         }
  770.         if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
  771.             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
  772.             $this->_packageInfo['dependencies']['required']['pearinstaller']),
  773.                 'warning: PEAR Installer dependency already exists, overwriting');
  774.             unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
  775.         }
  776.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  777.             array(
  778.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  779.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  780.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  781.                 'required' => array('optional', 'group'),
  782.                 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
  783.             ));
  784.     }
  785.  
  786.     /**
  787.      * Mark a package as conflicting with this package
  788.      * @param string package name
  789.      * @param string package channel
  790.      * @param string extension this package provides, if any
  791.      * @param string|false minimum version required
  792.      * @param string|false maximum version allowed
  793.      * @param array|false versions to exclude from installation
  794.      */
  795.     function addConflictingPackageDepWithChannel($name, $channel,
  796.                 $providesextension = false, $min = false, $max = false, $exclude = false)
  797.     {
  798.         $this->_isValid = 0;
  799.         $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
  800.             $exclude, $providesextension, false, true);
  801.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  802.             array(
  803.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  804.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  805.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  806.                 'required' => array('optional', 'group'),
  807.                 'package' => array('subpackage', 'extension', 'os', 'arch')
  808.             ));
  809.     }
  810.  
  811.     /**
  812.      * Mark a package as conflicting with this package
  813.      * @param string package name
  814.      * @param string package channel
  815.      * @param string extension this package provides, if any
  816.      */
  817.     function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
  818.     {
  819.         $this->_isValid = 0;
  820.         $dep =
  821.             array(
  822.                 'name' => $name,
  823.                 'uri' => $uri,
  824.                 'conflicts' => '',
  825.             );
  826.         if ($providesextension) {
  827.             $dep['providesextension'] = $providesextension;
  828.         }
  829.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  830.             array(
  831.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  832.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  833.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  834.                 'required' => array('optional', 'group'),
  835.                 'package' => array('subpackage', 'extension', 'os', 'arch')
  836.             ));
  837.     }
  838.  
  839.     function addDependencyGroup($name, $hint)
  840.     {
  841.         $this->_isValid = 0;
  842.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo,
  843.             array('attribs' => array('name' => $name, 'hint' => $hint)),
  844.             array(
  845.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  846.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  847.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  848.                 'group' => array(),
  849.             ));
  850.     }
  851.  
  852.     /**
  853.      * @param string package name
  854.      * @param string|false channel name, false if this is a uri
  855.      * @param string|false uri name, false if this is a channel
  856.      * @param string|false minimum version required
  857.      * @param string|false maximum version allowed
  858.      * @param string|false recommended installation version
  859.      * @param array|false versions to exclude from installation
  860.      * @param string extension this package provides, if any
  861.      * @param bool if true, tells the installer to ignore the default optional dependency group
  862.      *             when installing this package
  863.      * @param bool if true, tells the installer to negate this dependency (conflicts)
  864.      * @return array
  865.      * @access private
  866.      */
  867.     function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
  868.                            $providesextension = false, $nodefault = false,
  869.                            $conflicts = false)
  870.     {
  871.         $dep =
  872.             array(
  873.                 'name' => $name,
  874.             );
  875.         if ($channel) {
  876.             $dep['channel'] = $channel;
  877.         } elseif ($uri) {
  878.             $dep['uri'] = $uri;
  879.         }
  880.         if ($min) {
  881.             $dep['min'] = $min;
  882.         }
  883.         if ($max) {
  884.             $dep['max'] = $max;
  885.         }
  886.         if ($recommended) {
  887.             $dep['recommended'] = $recommended;
  888.         }
  889.         if ($exclude) {
  890.             if (is_array($exclude) && count($exclude) == 1) {
  891.                 $exclude = $exclude[0];
  892.             }
  893.             $dep['exclude'] = $exclude;
  894.         }
  895.         if ($conflicts) {
  896.             $dep['conflicts'] = '';
  897.         }
  898.         if ($nodefault) {
  899.             $dep['nodefault'] = '';
  900.         }
  901.         if ($providesextension) {
  902.             $dep['providesextension'] = $providesextension;
  903.         }
  904.         return $dep;
  905.     }
  906.  
  907.     /**
  908.      * @param package|subpackage
  909.      * @param string group name
  910.      * @param string package name
  911.      * @param string package channel
  912.      * @param string minimum version
  913.      * @param string maximum version
  914.      * @param string recommended version
  915.      * @param array|false optional excluded versions
  916.      * @param string extension this package provides, if any
  917.      * @param bool if true, tells the installer to ignore the default optional dependency group
  918.      *             when installing this package
  919.      * @return bool false if the dependency group has not been initialized with
  920.      *              {@link addDependencyGroup()}, or a subpackage is added with
  921.      *              a providesextension
  922.      */
  923.     function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
  924.                                       $max = false, $recommended = false, $exclude = false,
  925.                                       $providesextension = false, $nodefault = false)
  926.     {
  927.         if ($type == 'subpackage' && $providesextension) {
  928.             return false; // subpackages must be php packages
  929.         }
  930.         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
  931.             $providesextension, $nodefault);
  932.         return $this->_addGroupDependency($type, $dep, $groupname);
  933.     }
  934.  
  935.     /**
  936.      * @param package|subpackage
  937.      * @param string group name
  938.      * @param string package name
  939.      * @param string package uri
  940.      * @param string extension this package provides, if any
  941.      * @param bool if true, tells the installer to ignore the default optional dependency group
  942.      *             when installing this package
  943.      * @return bool false if the dependency group has not been initialized with
  944.      *              {@link addDependencyGroup()}
  945.      */
  946.     function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
  947.                                        $nodefault = false)
  948.     {
  949.         if ($type == 'subpackage' && $providesextension) {
  950.             return false; // subpackages must be php packages
  951.         }
  952.         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
  953.             $providesextension, $nodefault);
  954.         return $this->_addGroupDependency($type, $dep, $groupname);
  955.     }
  956.  
  957.     /**
  958.      * @param string group name (must be pre-existing)
  959.      * @param string extension name
  960.      * @param string minimum version allowed
  961.      * @param string maximum version allowed
  962.      * @param string recommended version
  963.      * @param array incompatible versions
  964.      */
  965.     function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
  966.                                          $recommended = false, $exclude = false)
  967.     {
  968.         $this->_isValid = 0;
  969.         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
  970.         return $this->_addGroupDependency('extension', $dep, $groupname);
  971.     }
  972.  
  973.     /**
  974.      * @param package|subpackage|extension
  975.      * @param array dependency contents
  976.      * @param string name of the dependency group to add this to
  977.      * @return boolean
  978.      * @access private
  979.      */
  980.     function _addGroupDependency($type, $dep, $groupname)
  981.     {
  982.         $arr = array('subpackage', 'extension');
  983.         if ($type != 'package') {
  984.             array_shift($arr);
  985.         }
  986.         if ($type == 'extension') {
  987.             array_shift($arr);
  988.         }
  989.         if (!isset($this->_packageInfo['dependencies']['group'])) {
  990.             return false;
  991.         } else {
  992.             if (!isset($this->_packageInfo['dependencies']['group'][0])) {
  993.                 if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
  994.                     $this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
  995.                         $this->_packageInfo['dependencies']['group'], $dep,
  996.                         array(
  997.                             $type => $arr
  998.                         ));
  999.                     $this->_isValid = 0;
  1000.                     return true;
  1001.                 } else {
  1002.                     return false;
  1003.                 }
  1004.             } else {
  1005.                 foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
  1006.                     if ($group['attribs']['name'] == $groupname) {
  1007.                     $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
  1008.                         $this->_packageInfo['dependencies']['group'][$i], $dep,
  1009.                         array(
  1010.                             $type => $arr
  1011.                         ));
  1012.                         $this->_isValid = 0;
  1013.                         return true;
  1014.                     }
  1015.                 }
  1016.                 return false;
  1017.             }
  1018.         }
  1019.     }
  1020.  
  1021.     /**
  1022.      * @param optional|required
  1023.      * @param string package name
  1024.      * @param string package channel
  1025.      * @param string minimum version
  1026.      * @param string maximum version
  1027.      * @param string recommended version
  1028.      * @param string extension this package provides, if any
  1029.      * @param bool if true, tells the installer to ignore the default optional dependency group
  1030.      *             when installing this package
  1031.      * @param array|false optional excluded versions
  1032.      */
  1033.     function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
  1034.                                       $recommended = false, $exclude = false,
  1035.                                       $providesextension = false, $nodefault = false)
  1036.     {
  1037.         if (!in_array($type, array('optional', 'required'), true)) {
  1038.             $type = 'required';
  1039.         }
  1040.         $this->_isValid = 0;
  1041.         $arr = array('optional', 'group');
  1042.         if ($type != 'required') {
  1043.             array_shift($arr);
  1044.         }
  1045.         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
  1046.             $providesextension, $nodefault);
  1047.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1048.             array(
  1049.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1050.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1051.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1052.                 $type => $arr,
  1053.                 'package' => array('subpackage', 'extension', 'os', 'arch')
  1054.             ));
  1055.     }
  1056.  
  1057.     /**
  1058.      * @param optional|required
  1059.      * @param string name of the package
  1060.      * @param string uri of the package
  1061.      * @param string extension this package provides, if any
  1062.      * @param bool if true, tells the installer to ignore the default optional dependency group
  1063.      *             when installing this package
  1064.      */
  1065.     function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
  1066.                                   $nodefault = false)
  1067.     {
  1068.         $this->_isValid = 0;
  1069.         $arr = array('optional', 'group');
  1070.         if ($type != 'required') {
  1071.             array_shift($arr);
  1072.         }
  1073.         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
  1074.             $providesextension, $nodefault);
  1075.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1076.             array(
  1077.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1078.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1079.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1080.                 $type => $arr,
  1081.                 'package' => array('subpackage', 'extension', 'os', 'arch')
  1082.             ));
  1083.     }
  1084.  
  1085.     /**
  1086.      * @param optional|required optional, required
  1087.      * @param string package name
  1088.      * @param string package channel
  1089.      * @param string minimum version
  1090.      * @param string maximum version
  1091.      * @param string recommended version
  1092.      * @param array incompatible versions
  1093.      * @param bool if true, tells the installer to ignore the default optional dependency group
  1094.      *             when installing this package
  1095.      */
  1096.     function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
  1097.                                          $recommended = false, $exclude = false,
  1098.                                          $nodefault = false)
  1099.     {
  1100.         $this->_isValid = 0;
  1101.         $arr = array('optional', 'group');
  1102.         if ($type != 'required') {
  1103.             array_shift($arr);
  1104.         }
  1105.         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
  1106.             $nodefault);
  1107.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1108.             array(
  1109.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1110.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1111.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1112.                 $type => $arr,
  1113.                 'subpackage' => array('extension', 'os', 'arch')
  1114.             ));
  1115.     }
  1116.  
  1117.     /**
  1118.      * @param optional|required optional, required
  1119.      * @param string package name
  1120.      * @param string package uri for download
  1121.      * @param bool if true, tells the installer to ignore the default optional dependency group
  1122.      *             when installing this package
  1123.      */
  1124.     function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
  1125.     {
  1126.         $this->_isValid = 0;
  1127.         $arr = array('optional', 'group');
  1128.         if ($type != 'required') {
  1129.             array_shift($arr);
  1130.         }
  1131.         $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
  1132.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1133.             array(
  1134.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1135.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1136.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1137.                 $type => $arr,
  1138.                 'subpackage' => array('extension', 'os', 'arch')
  1139.             ));
  1140.     }
  1141.  
  1142.     /**
  1143.      * @param optional|required optional, required
  1144.      * @param string extension name
  1145.      * @param string minimum version
  1146.      * @param string maximum version
  1147.      * @param string recommended version
  1148.      * @param array incompatible versions
  1149.      */
  1150.     function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
  1151.                              $exclude = false)
  1152.     {
  1153.         $this->_isValid = 0;
  1154.         $arr = array('optional', 'group');
  1155.         if ($type != 'required') {
  1156.             array_shift($arr);
  1157.         }
  1158.         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
  1159.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1160.             array(
  1161.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1162.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1163.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1164.                 $type => $arr,
  1165.                 'extension' => array('os', 'arch')
  1166.             ));
  1167.     }
  1168.  
  1169.     /**
  1170.      * @param string Operating system name
  1171.      * @param boolean true if this package cannot be installed on this OS
  1172.      */
  1173.     function addOsDep($name, $conflicts = false)
  1174.     {
  1175.         $this->_isValid = 0;
  1176.         $dep = array('name' => $name);
  1177.         if ($conflicts) {
  1178.             $dep['conflicts'] = '';
  1179.         }
  1180.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1181.             array(
  1182.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1183.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1184.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1185.                 'required' => array('optional', 'group'),
  1186.                 'os' => array('arch')
  1187.             ));
  1188.     }
  1189.  
  1190.     /**
  1191.      * @param string Architecture matching pattern
  1192.      * @param boolean true if this package cannot be installed on this architecture
  1193.      */
  1194.     function addArchDep($pattern, $conflicts = false)
  1195.     {
  1196.         $this->_isValid = 0;
  1197.         $dep = array('pattern' => $pattern);
  1198.         if ($conflicts) {
  1199.             $dep['conflicts'] = '';
  1200.         }
  1201.         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
  1202.             array(
  1203.                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
  1204.                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
  1205.                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
  1206.                 'required' => array('optional', 'group'),
  1207.                 'arch' => array()
  1208.             ));
  1209.     }
  1210.  
  1211.     /**
  1212.      * Set the kind of package, and erase all release tags
  1213.      *
  1214.      * - a php package is a PEAR-style package
  1215.      * - an extbin package is a PECL-style extension binary
  1216.      * - an extsrc package is a PECL-style source for a binary
  1217.      * - an zendextbin package is a PECL-style zend extension binary
  1218.      * - an zendextsrc package is a PECL-style source for a zend extension binary
  1219.      * - a bundle package is a collection of other pre-packaged packages
  1220.      * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
  1221.      * @return bool success
  1222.      */
  1223.     function setPackageType($type)
  1224.     {
  1225.         $this->_isValid = 0;
  1226.         if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
  1227.                                    'zendextbin', 'bundle'))) {
  1228.             return false;
  1229.         }
  1230.         if (in_array($type, array('zendextsrc', 'zendextbin'))) {
  1231.             $this->_setPackageVersion2_1();
  1232.         }
  1233.         if ($type != 'bundle') {
  1234.             $type .= 'release';
  1235.         }
  1236.         foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
  1237.                        'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
  1238.             unset($this->_packageInfo[$test]);
  1239.         }
  1240.         if (!isset($this->_packageInfo[$type])) {
  1241.             // ensure that the release tag is set up
  1242.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
  1243.                 array(), $type);
  1244.         }
  1245.         $this->_packageInfo[$type] = array();
  1246.         return true;
  1247.     }
  1248.  
  1249.     /**
  1250.      * @return bool true if package type is set up
  1251.      */
  1252.     function addRelease()
  1253.     {
  1254.         if ($type = $this->getPackageType()) {
  1255.             if ($type != 'bundle') {
  1256.                 $type .= 'release';
  1257.             }
  1258.             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
  1259.                 array($type => array('changelog')));
  1260.             return true;
  1261.         }
  1262.         return false;
  1263.     }
  1264.  
  1265.     /**
  1266.      * Get the current release tag in order to add to it
  1267.      * @param bool returns only releases that have installcondition if true
  1268.      * @return array|null
  1269.      */
  1270.     function &_getCurrentRelease($strict = true)
  1271.     {
  1272.         if ($p = $this->getPackageType()) {
  1273.             if ($strict) {
  1274.                 if ($p == 'extsrc' || $p == 'zendextsrc') {
  1275.                     $a = null;
  1276.                     return $a;
  1277.                 }
  1278.             }
  1279.             if ($p != 'bundle') {
  1280.                 $p .= 'release';
  1281.             }
  1282.             if (isset($this->_packageInfo[$p][0])) {
  1283.                 return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
  1284.             } else {
  1285.                 return $this->_packageInfo[$p];
  1286.             }
  1287.         } else {
  1288.             $a = null;
  1289.             return $a;
  1290.         }
  1291.     }
  1292.  
  1293.     /**
  1294.      * Add a file to the current release that should be installed under a different name
  1295.      * @param string <contents> path to file
  1296.      * @param string name the file should be installed as
  1297.      */
  1298.     function addInstallAs($path, $as)
  1299.     {
  1300.         $r = &$this->_getCurrentRelease();
  1301.         if ($r === null) {
  1302.             return false;
  1303.         }
  1304.         $this->_isValid = 0;
  1305.         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
  1306.             array(
  1307.                 'filelist' => array(),
  1308.                 'install' => array('ignore')
  1309.             ));
  1310.     }
  1311.  
  1312.     /**
  1313.      * Add a file to the current release that should be ignored
  1314.      * @param string <contents> path to file
  1315.      * @return bool success of operation
  1316.      */
  1317.     function addIgnore($path)
  1318.     {
  1319.         $r = &$this->_getCurrentRelease();
  1320.         if ($r === null) {
  1321.             return false;
  1322.         }
  1323.         $this->_isValid = 0;
  1324.         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
  1325.             array(
  1326.                 'filelist' => array(),
  1327.                 'ignore' => array()
  1328.             ));
  1329.     }
  1330.  
  1331.     /**
  1332.      * Add an extension binary package for this extension source code release
  1333.      *
  1334.      * Note that the package must be from the same channel as the extension source package
  1335.      * @param string
  1336.      */
  1337.     function addBinarypackage($package)
  1338.     {
  1339.         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
  1340.             return false;
  1341.         }
  1342.         $r = &$this->_getCurrentRelease(false);
  1343.         if ($r === null) {
  1344.             return false;
  1345.         }
  1346.         $this->_isValid = 0;
  1347.         $r = $this->_mergeTag($r, $package,
  1348.             array(
  1349.                 'binarypackage' => array('filelist'),
  1350.             ));
  1351.     }
  1352.  
  1353.     /**
  1354.      * Add a configureoption to an extension source package
  1355.      * @param string
  1356.      * @param string
  1357.      * @param string
  1358.      */
  1359.     function addConfigureOption($name, $prompt, $default = null)
  1360.     {
  1361.         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
  1362.             return false;
  1363.         }
  1364.         $r = &$this->_getCurrentRelease(false);
  1365.         if ($r === null) {
  1366.             return false;
  1367.         }
  1368.         $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
  1369.         if ($default !== null) {
  1370.             $opt['attribs']['default'] = $default;
  1371.         }
  1372.         $this->_isValid = 0;
  1373.         $r = $this->_mergeTag($r, $opt,
  1374.             array(
  1375.                 'configureoption' => array('binarypackage', 'filelist'),
  1376.             ));
  1377.     }
  1378.  
  1379.     /**
  1380.      * Set an installation condition based on php version for the current release set
  1381.      * @param string minimum version
  1382.      * @param string maximum version
  1383.      * @param false|array incompatible versions of PHP
  1384.      */
  1385.     function setPhpInstallCondition($min, $max, $exclude = false)
  1386.     {
  1387.         $r = &$this->_getCurrentRelease();
  1388.         if ($r === null) {
  1389.             return false;
  1390.         }
  1391.         $this->_isValid = 0;
  1392.         if (isset($r['installconditions']['php'])) {
  1393.             unset($r['installconditions']['php']);
  1394.         }
  1395.         $dep = array('min' => $min, 'max' => $max);
  1396.         if ($exclude) {
  1397.             if (is_array($exclude) && count($exclude) == 1) {
  1398.                 $exclude = $exclude[0];
  1399.             }
  1400.             $dep['exclude'] = $exclude;
  1401.         }
  1402.         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
  1403.             $r = $this->_mergeTag($r, $dep,
  1404.                 array(
  1405.                     'installconditions' => array('configureoption', 'binarypackage',
  1406.                         'filelist'),
  1407.                     'php' => array('extension', 'os', 'arch')
  1408.                 ));
  1409.         } else {
  1410.             $r = $this->_mergeTag($r, $dep,
  1411.                 array(
  1412.                     'installconditions' => array('filelist'),
  1413.                     'php' => array('extension', 'os', 'arch')
  1414.                 ));
  1415.         }
  1416.     }
  1417.  
  1418.     /**
  1419.      * @param optional|required optional, required
  1420.      * @param string extension name
  1421.      * @param string minimum version
  1422.      * @param string maximum version
  1423.      * @param string recommended version
  1424.      * @param array incompatible versions
  1425.      */
  1426.     function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
  1427.                                           $exclude = false)
  1428.     {
  1429.         $r = &$this->_getCurrentRelease();
  1430.         if ($r === null) {
  1431.             return false;
  1432.         }
  1433.         $this->_isValid = 0;
  1434.         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
  1435.         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
  1436.             $r = $this->_mergeTag($r, $dep,
  1437.                 array(
  1438.                     'installconditions' => array('configureoption', 'binarypackage',
  1439.                         'filelist'),
  1440.                     'extension' => array('os', 'arch')
  1441.                 ));
  1442.         } else {
  1443.             $r = $this->_mergeTag($r, $dep,
  1444.                 array(
  1445.                     'installconditions' => array('filelist'),
  1446.                     'extension' => array('os', 'arch')
  1447.                 ));
  1448.         }
  1449.     }
  1450.  
  1451.     /**
  1452.      * Set an installation condition based on operating system for the current release set
  1453.      * @param string OS name
  1454.      * @param bool whether this OS is incompatible with the current release
  1455.      */
  1456.     function setOsInstallCondition($name, $conflicts = false)
  1457.     {
  1458.         $r = &$this->_getCurrentRelease();
  1459.         if ($r === null) {
  1460.             return false;
  1461.         }
  1462.         $this->_isValid = 0;
  1463.         if (isset($r['installconditions']['os'])) {
  1464.             unset($r['installconditions']['os']);
  1465.         }
  1466.         $dep = array('name' => $name);
  1467.         if ($conflicts) {
  1468.             $dep['conflicts'] = '';
  1469.         }
  1470.         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
  1471.             $r = $this->_mergeTag($r, $dep,
  1472.                 array(
  1473.                     'installconditions' => array('configureoption', 'binarypackage',
  1474.                         'filelist'),
  1475.                     'os' => array('arch')
  1476.                 ));
  1477.         } else {
  1478.             $r = $this->_mergeTag($r, $dep,
  1479.                 array(
  1480.                     'installconditions' => array('filelist'),
  1481.                     'os' => array('arch')
  1482.                 ));
  1483.         }
  1484.     }
  1485.  
  1486.     /**
  1487.      * Set an installation condition based on architecture for the current release set
  1488.      * @param string architecture pattern
  1489.      * @param bool whether this arch is incompatible with the current release
  1490.      */
  1491.     function setArchInstallCondition($pattern, $conflicts = false)
  1492.     {
  1493.         $r = &$this->_getCurrentRelease();
  1494.         if ($r === null) {
  1495.             return false;
  1496.         }
  1497.         $this->_isValid = 0;
  1498.         if (isset($r['installconditions']['arch'])) {
  1499.             unset($r['installconditions']['arch']);
  1500.         }
  1501.         $dep = array('pattern' => $pattern);
  1502.         if ($conflicts) {
  1503.             $dep['conflicts'] = '';
  1504.         }
  1505.         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
  1506.             $r = $this->_mergeTag($r, $dep,
  1507.                 array(
  1508.                     'installconditions' => array('configureoption', 'binarypackage',
  1509.                         'filelist'),
  1510.                     'arch' => array()
  1511.                 ));
  1512.         } else {
  1513.             $r = $this->_mergeTag($r, $dep,
  1514.                 array(
  1515.                     'installconditions' => array('filelist'),
  1516.                     'arch' => array()
  1517.                 ));
  1518.         }
  1519.     }
  1520.  
  1521.     /**
  1522.      * For extension binary releases, this is used to specify either the
  1523.      * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
  1524.      * package it is based on.
  1525.      * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
  1526.      */
  1527.     function setSourcePackage($packageOrUri)
  1528.     {
  1529.         $this->_isValid = 0;
  1530.         if (isset($this->_packageInfo['channel'])) {
  1531.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
  1532.                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
  1533.                 'bundle', 'changelog'),
  1534.                 $packageOrUri, 'srcpackage');
  1535.         } else {
  1536.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
  1537.                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
  1538.                 'bundle', 'changelog'), $packageOrUri, 'srcuri');
  1539.         }
  1540.     }
  1541.  
  1542.     /**
  1543.      * Generate a valid change log entry from the current package.xml
  1544.      * @param string|false
  1545.      */
  1546.     function generateChangeLogEntry($notes = false)
  1547.     {
  1548.         return array(
  1549.             'version' => 
  1550.                 array(
  1551.                     'release' => $this->getVersion('release'),
  1552.                     'api' => $this->getVersion('api'),
  1553.                     ),
  1554.             'stability' =>
  1555.                 $this->getStability(),
  1556.             'date' => $this->getDate(),
  1557.             'license' => $this->getLicense(true),
  1558.             'notes' => $notes ? $notes : $this->getNotes()
  1559.             );
  1560.     }
  1561.  
  1562.     /**
  1563.      * @param string release version to set change log notes for
  1564.      * @param array output of {@link generateChangeLogEntry()}
  1565.      */
  1566.     function setChangelogEntry($releaseversion, $contents)
  1567.     {
  1568.         if (!isset($this->_packageInfo['changelog'])) {
  1569.             $this->_packageInfo['changelog']['release'] = $contents;
  1570.             return;
  1571.         }
  1572.         if (!isset($this->_packageInfo['changelog']['release'][0])) {
  1573.             if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
  1574.                 $this->_packageInfo['changelog']['release'] = array(
  1575.                     $this->_packageInfo['changelog']['release']);
  1576.             } else {
  1577.                 $this->_packageInfo['changelog']['release'] = array(
  1578.                     $this->_packageInfo['changelog']['release']);
  1579.                 return $this->_packageInfo['changelog']['release'][] = $contents;
  1580.             }
  1581.         }
  1582.         foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
  1583.             if (isset($changelog['version']) &&
  1584.                   strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
  1585.                 $curlog = $index;
  1586.             }
  1587.         }
  1588.         if (isset($curlog)) {
  1589.             $this->_packageInfo['changelog']['release'][$curlog] = $contents;
  1590.         } else {
  1591.             $this->_packageInfo['changelog']['release'][] = $contents;
  1592.         }
  1593.     }
  1594.  
  1595.     /**
  1596.      * Remove the changelog entirely
  1597.      */
  1598.     function clearChangeLog()
  1599.     {
  1600.         unset($this->_packageInfo['changelog']);
  1601.     }
  1602. }
  1603. ?>