home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / phing / tasks / ext / PearPackageTask.php < prev    next >
Encoding:
PHP Script  |  2007-02-05  |  12.9 KB  |  422 lines

  1. <?php
  2. /*
  3.  *  $Id: PearPackageTask.php 144 2007-02-05 15:19:00Z hans $
  4.  *
  5.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  *
  17.  * This software consists of voluntary contributions made by many individuals
  18.  * and is licensed under the LGPL. For more information please see
  19.  * <http://phing.info>.
  20.  */
  21.  
  22. require_once 'phing/tasks/system/MatchingTask.php';
  23. include_once 'phing/types/FileSet.php';
  24.  
  25. /**
  26.  * A task to create PEAR package.xml file.
  27.  * 
  28.  * This class uses the PEAR_PackageFileMaintainer class to perform the work.
  29.  * 
  30.  * This class is designed to be very flexible -- i.e. account for changes to the package.xml w/o
  31.  * requiring changes to this class.  We've accomplished this by having generic <option> and <mapping>
  32.  * nested elements.  All options are set using PEAR_PackageFileMaintainer::setOptions().
  33.  * 
  34.  * The <option> tag is used to set a simple option value.
  35.  * <code>
  36.  * <option name="option_name" value="option_value"/> 
  37.  * or <option name="option_name">option_value</option>
  38.  * </code>
  39.  * 
  40.  * The <mapping> tag represents a complex data type.  You can use nested <element> (and nested <element> with
  41.  * <element> tags) to represent the full complexity of the structure.  Bear in mind that what you are creating
  42.  * will be mapped to an associative array that will be passed in via PEAR_PackageFileMaintainer::setOptions().
  43.  * <code>
  44.  * <mapping name="option_name">
  45.  *  <element key="key_name" value="key_val"/>
  46.  *  <element key="key_name" value="key_val"/>
  47.  * </mapping>
  48.  * </code>
  49.  * 
  50.  * Here's an over-simple example of how this could be used:
  51.  * <code>
  52.  * <pearpkg name="phing" dir="${build.src.dir}" destFile="${build.base.dir}/package.xml">
  53.  *  <fileset>
  54.  *   <include name="**"/>
  55.  *  </fileset>
  56.  *  <option name="notes">Sample release notes here.</option>
  57.  *  <option name="description">Package description</option>
  58.  *  <option name="summary">Short description</option>
  59.  *  <option name="version" value="2.0.0b1"/>
  60.  *  <option name="state" value="beta"/>
  61.  *  <mapping name="maintainers">
  62.  *   <element>
  63.  *    <element key="handle" value="hlellelid"/>
  64.  *    <element key="name" value="Hans"/>
  65.  *    <element key="email" value="hans@xmpl.org"/>
  66.  *    <element key="role" value="lead"/>
  67.  *   </element>
  68.  *  </mapping>
  69.  * </pearpkg>
  70.  * </code>
  71.  *
  72.  * Look at the build.xml in the Phing base directory (assuming you have the full distro / CVS version of Phing) to
  73.  * see a more complete example of how to call this script.
  74.  * 
  75.  * @author   Hans Lellelid <hans@xmpl.org>
  76.  * @package  phing.tasks.ext
  77.  * @version  $Revision: 1.9 $
  78.  */
  79. class PearPackageTask extends MatchingTask {
  80.     
  81.     /** */        
  82.     protected $package;
  83.  
  84.     /** Base directory for reading files. */
  85.     protected $dir;
  86.     
  87.     /** Package file */
  88.     private $packageFile;
  89.     
  90.     /** @var array FileSet[] */
  91.     private $filesets = array();
  92.     
  93.     /** @var PEAR_PackageFileManager */
  94.     protected $pkg;
  95.     
  96.     private $preparedOptions = array();
  97.     
  98.     /** @var array PearPkgOption[] */
  99.     protected $options = array();
  100.     
  101.     /** Nested <mapping> (complex options) types. */
  102.     protected $mappings = array();
  103.     
  104.     public function init() {
  105.         include_once 'PEAR/PackageFileManager.php';
  106.         if (!class_exists('PEAR_PackageFileManager')) {
  107.             throw new BuildException("You must have installed PEAR_PackageFileManager in order to create a PEAR package.xml file.");
  108.         }
  109.     }
  110.     
  111.     /**
  112.      * Sets PEAR package.xml options, based on class properties.
  113.      * @return void
  114.      */
  115.     protected function setOptions() {
  116.     
  117.         // 1) first prepare/populate options        
  118.         $this->populateOptions();
  119.  
  120.         // 2) make any final adjustments (this could move into populateOptions() also)
  121.         
  122.         // default PEAR basedir would be the name of the package (e.g."phing")
  123.         if (!isset($this->preparedOptions['baseinstalldir'])) {
  124.             $this->preparedOptions['baseinstalldir'] = $this->package;
  125.         }
  126.         
  127.         // unless filelistgenerator has been overridden, we use Phing FileSet generator
  128.         if (!isset($this->preparedOptions['filelistgenerator'])) {
  129.             if (empty($this->filesets)) {
  130.                 throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml");
  131.             }
  132.             $this->preparedOptions['filelistgenerator'] = 'Fileset';
  133.             $this->preparedOptions['usergeneratordir'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pearpackage';
  134.             // Some PHING-specific options needed by our Fileset reader
  135.             $this->preparedOptions['phing_project'] = $this->project;
  136.             $this->preparedOptions['phing_filesets'] = $this->filesets;
  137.         } elseif ($this->preparedOptions['filelistgeneragor'] != 'Fileset' && !empty($this->filesets)) {
  138.             throw new BuildException("You cannot use <fileset> element if you have specified the \"filelistgenerator\" option.");
  139.         }                
  140.         
  141.         // 3) Set the options
  142.                 
  143.         // No need for excessive validation here, since the  PEAR class will do its own 
  144.         // validation & return errors
  145.         $e = $this->pkg->setOptions($this->preparedOptions);
  146.             
  147.         if (PEAR::isError($e)) {
  148.             throw new BuildException("Unable to set options.", new Exception($e->getMessage()));
  149.         }
  150.     }
  151.     
  152.     /**
  153.      * Fixes the boolean in optional dependencies
  154.      */
  155.     private function fixDeps($deps)
  156.     {
  157.         foreach (array_keys($deps) as $dep)
  158.         {
  159.             if (isset($deps[$dep]['optional']) && $deps[$dep]['optional'])
  160.             {
  161.                 $deps[$dep]['optional'] = "yes";
  162.             }
  163.         }
  164.         
  165.         return $deps;
  166.     }
  167.     
  168.     /**
  169.      * Adds the options that are set via attributes and the nested tags to the options array.
  170.      */
  171.     private function populateOptions() {
  172.         
  173.         // These values could be overridden if explicitly defined using nested tags    
  174.         $this->preparedOptions['package'] = $this->package;
  175.         $this->preparedOptions['packagedirectory'] = $this->dir->getAbsolutePath();
  176.         
  177.         if ($this->packageFile !== null) {
  178.             // create one w/ full path
  179.             $f = new PhingFile($this->packageFile->getAbsolutePath());
  180.             $this->preparedOptions['packagefile'] = $f->getName();
  181.             // must end in trailing slash
  182.             $this->preparedOptions['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR;
  183.             $this->log("Creating package file: " . $f->__toString(), Project::MSG_INFO);
  184.         } else {
  185.             $this->log("Creating [default] package.xml file in base directory.", Project::MSG_INFO);
  186.         }
  187.         
  188.         // converts option objects and mapping objects into 
  189.         // key => value options that can be passed to PEAR_PackageFileManager
  190.         
  191.         foreach($this->options as $opt) {
  192.             $this->preparedOptions[ $opt->getName() ] = $opt->getValue(); //no arrays yet. preg_split('/\s*,\s*/', $opt->getValue());
  193.         }
  194.         
  195.         foreach($this->mappings as $map) {
  196.             $value = $map->getValue(); // getValue returns complex value
  197.             
  198.             if ($map->getName() == 'deps')
  199.             {
  200.                 $value = $this->fixDeps($value);
  201.             }
  202.             
  203.             $this->preparedOptions[ $map->getName() ] = $value;
  204.         }
  205.     }
  206.     
  207.     /**
  208.      * Main entry point.
  209.      * @return void
  210.      */
  211.     public function main() {        
  212.         
  213.         if ($this->dir === null) {
  214.             throw new BuildException("You must specify the \"dir\" attribute for PEAR package task.");
  215.         }
  216.         
  217.         if ($this->package === null) {
  218.             throw new BuildException("You must specify the \"name\" attribute for PEAR package task.");
  219.         }
  220.         
  221.         $this->pkg = new PEAR_PackageFileManager();                
  222.         
  223.         $this->setOptions();
  224.         
  225.         $e = $this->pkg->writePackageFile();
  226.         if (PEAR::isError($e)) {
  227.             throw new BuildException("Unable to write package file.", new Exception($e->getMessage()));
  228.         }
  229.         
  230.     }
  231.     
  232.     /**
  233.      * Used by the PEAR_PackageFileManager_PhingFileSet lister.
  234.      * @return array FileSet[]
  235.      */
  236.     public function getFileSets() {
  237.         return $this->filesets;
  238.     }
  239.     
  240.     // -------------------------------
  241.     // Set properties from XML
  242.     // -------------------------------
  243.  
  244.     /**
  245.      * Nested creator, creates a FileSet for this task
  246.      *
  247.      * @return FileSet The created fileset object
  248.      */
  249.     function createFileSet() {
  250.         $num = array_push($this->filesets, new FileSet());
  251.         return $this->filesets[$num-1];
  252.     }
  253.     
  254.     /**
  255.      * Set "package" property from XML.
  256.      * @see setName()
  257.      * @param string $v
  258.      * @return void
  259.      */
  260.     public function setPackage($v) {
  261.         $this->package = $v;
  262.     }
  263.     
  264.     /**
  265.      * Sets "dir" property from XML.
  266.      * @param PhingFile $f
  267.      * @return void
  268.      */
  269.     public function setDir(PhingFile $f) {
  270.         $this->dir = $f;
  271.     }
  272.  
  273.     /**
  274.      * Sets "name" property from XML.
  275.      * @param string $v
  276.      * @return void
  277.      */
  278.     public function setName($v) {
  279.         $this->package = $v;
  280.     }
  281.     
  282.     /**
  283.      * Sets the file to use for generated package.xml
  284.      */
  285.     public function setDestFile(PhingFile $f) {
  286.         $this->packageFile = $f;
  287.     }
  288.     
  289.     /**
  290.      * Handles nested generic <option> elements.
  291.      */
  292.     function createOption() {
  293.         $o = new PearPkgOption();
  294.         $this->options[] = $o;
  295.         return $o;
  296.     }
  297.     
  298.     /**
  299.      * Handles nested generic <option> elements.
  300.      */
  301.     function createMapping() {
  302.         $o = new PearPkgMapping();
  303.         $this->mappings[] = $o;
  304.         return $o;
  305.     }
  306. }
  307.  
  308.  
  309.  
  310. /**
  311.  * Generic option class is used for non-complex options.
  312.  */
  313. class PearPkgOption {
  314.     
  315.     private    $name;
  316.     private $value;
  317.     
  318.     public function setName($v) { $this->name = $v; }
  319.     public function getName() { return $this->name; }
  320.     
  321.     public function setValue($v) { $this->value = $v; }
  322.     public function getValue() { return $this->value; }
  323.     public function addText($txt) { $this->value = trim($txt); }
  324.         
  325. }
  326.  
  327. /**
  328.  * Handles complex options <mapping> elements which are hashes (assoc arrays).
  329.  */
  330. class PearPkgMapping {
  331.  
  332.     private    $name;
  333.     private $elements = array();    
  334.     
  335.     public function setName($v) {
  336.         $this->name = $v;
  337.     }
  338.     
  339.     public function getName() { 
  340.         return $this->name;
  341.     }
  342.  
  343.     public function createElement() { 
  344.         $e = new PearPkgMappingElement();
  345.         $this->elements[] = $e;
  346.         return $e;
  347.     }
  348.         
  349.     public function    getElements() {
  350.         return $this->elements;
  351.     }
  352.     
  353.     /**
  354.      * Returns the PHP hash or array of hashes (etc.) that this mapping represents.
  355.      * @return array
  356.      */
  357.     public function getValue() {
  358.         $value = array();
  359.         foreach($this->getElements() as $el) {
  360.             if ($el->getKey() !== null) {
  361.                 $value[ $el->getKey() ] = $el->getValue();
  362.             } else {
  363.                 $value[] = $el->getValue();
  364.             }
  365.         }
  366.         return $value;
  367.     }
  368. }
  369.  
  370. /**
  371.  * Sub-element of <mapping>.
  372.  */
  373. class PearPkgMappingElement {
  374.  
  375.     private    $key;
  376.     private $value;
  377.     private $elements = array();
  378.     
  379.     public function setKey($v) {
  380.         $this->key = $v;
  381.     }
  382.     
  383.     public function getKey() {
  384.         return $this->key;
  385.     }
  386.     
  387.     public function setValue($v) {
  388.         $this->value = $v;
  389.     }
  390.     
  391.     /**
  392.      * Returns either the simple value or
  393.      * the calculated value (array) of nested elements.
  394.      * @return mixed
  395.      */
  396.     public function getValue() {    
  397.         if (!empty($this->elements)) {
  398.             $value = array();
  399.             foreach($this->elements as $el) {
  400.                 if ($el->getKey() !== null) {
  401.                     $value[ $el->getKey() ] = $el->getValue();
  402.                 } else {
  403.                     $value[] = $el->getValue();
  404.                 }
  405.             }            
  406.             return $value;
  407.         } else  {
  408.             return $this->value;        
  409.         }
  410.     }
  411.     
  412.     /**
  413.      * Handles nested <element> tags.
  414.      */
  415.     public function createElement() {
  416.         $e = new PearPkgMappingElement();
  417.         $this->elements[] = $e;
  418.         return $e;
  419.     }
  420.     
  421. }
  422.