Viewing file: PearPackageTask.php (12.85 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php /* * $Id: PearPackageTask.php 59 2006-04-28 14:49:47Z mrook $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information please see * <http://phing.info>. */
require_once 'phing/tasks/system/MatchingTask.php'; include_once 'phing/types/FileSet.php';
/** * A task to create PEAR package.xml file. * * This class uses the PEAR_PackageFileMaintainer class to perform the work. * * This class is designed to be very flexible -- i.e. account for changes to the package.xml w/o * requiring changes to this class. We've accomplished this by having generic <option> and <mapping> * nested elements. All options are set using PEAR_PackageFileMaintainer::setOptions(). * * The <option> tag is used to set a simple option value. * <code> * <option name="option_name" value="option_value"/> * or <option name="option_name">option_value</option> * </code> * * The <mapping> tag represents a complex data type. You can use nested <element> (and nested <element> with * <element> tags) to represent the full complexity of the structure. Bear in mind that what you are creating * will be mapped to an associative array that will be passed in via PEAR_PackageFileMaintainer::setOptions(). * <code> * <mapping name="option_name"> * <element key="key_name" value="key_val"/> * <element key="key_name" value="key_val"/> * </mapping> * </code> * * Here's an over-simple example of how this could be used: * <code> * <pearpkg name="phing" dir="${build.src.dir}" destFile="${build.base.dir}/package.xml"> * <fileset> * <include name="**"/> * </fileset> * <option name="notes">Sample release notes here.</option> * <option name="description">Package description</option> * <option name="summary">Short description</option> * <option name="version" value="2.0.0b1"/> * <option name="state" value="beta"/> * <mapping name="maintainers"> * <element> * <element key="handle" value="hlellelid"/> * <element key="name" value="Hans"/> * <element key="email" value="hans@xmpl.org"/> * <element key="role" value="lead"/> * </element> * </mapping> * </pearpkg> * </code> * * Look at the build.xml in the Phing base directory (assuming you have the full distro / CVS version of Phing) to * see a more complete example of how to call this script. * * @author Hans Lellelid <hans@xmpl.org> * @package phing.tasks.ext * @version $Revision: 1.9 $ */ class PearPackageTask extends MatchingTask { /** */ private $package;
/** Base directory for reading files. */ private $dir; /** Package file */ private $packageFile; /** @var array FileSet[] */ private $filesets = array(); /** @var PEAR_PackageFileManager */ private $pkg; private $preparedOptions = array(); /** @var array PearPkgOption[] */ private $options = array(); /** Nested <mapping> (complex options) types. */ private $mappings = array(); public function init() { include_once 'PEAR/PackageFileManager.php'; if (!class_exists('PEAR_PackageFileManager')) { throw new BuildException("You must have installed PEAR_PackageFileManager in order to create a PEAR package.xml file."); } } /** * Sets PEAR package.xml options, based on class properties. * @return void */ private function setOptions() { // 1) first prepare/populate options $this->populateOptions();
// 2) make any final adjustments (this could move into populateOptions() also) // default PEAR basedir would be the name of the package (e.g."phing") if (!isset($this->preparedOptions['baseinstalldir'])) { $this->preparedOptions['baseinstalldir'] = $this->package; } // unless filelistgenerator has been overridden, we use Phing FileSet generator if (!isset($this->preparedOptions['filelistgenerator'])) { if (empty($this->filesets)) { throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml"); } $this->preparedOptions['filelistgenerator'] = 'Fileset'; $this->preparedOptions['usergeneratordir'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pearpackage'; // Some PHING-specific options needed by our Fileset reader $this->preparedOptions['phing_project'] = $this->project; $this->preparedOptions['phing_filesets'] = $this->filesets; } elseif ($this->preparedOptions['filelistgeneragor'] != 'Fileset' && !empty($this->filesets)) { throw new BuildException("You cannot use <fileset> element if you have specified the \"filelistgenerator\" option."); } // 3) Set the options // No need for excessive validation here, since the PEAR class will do its own // validation & return errors $e = $this->pkg->setOptions($this->preparedOptions); if (PEAR::isError($e)) { throw new BuildException("Unable to set options.", new Exception($e->getMessage())); } } /** * Fixes the boolean in optional dependencies */ private function fixDeps($deps) { foreach (array_keys($deps) as $dep) { if (isset($deps[$dep]['optional']) && $deps[$dep]['optional']) { $deps[$dep]['optional'] = "yes"; } } return $deps; } /** * Adds the options that are set via attributes and the nested tags to the options array. */ private function populateOptions() { // These values could be overridden if explicitly defined using nested tags $this->preparedOptions['package'] = $this->package; $this->preparedOptions['packagedirectory'] = $this->dir->getAbsolutePath(); if ($this->packageFile !== null) { // create one w/ full path $f = new PhingFile($this->packageFile->getAbsolutePath()); $this->preparedOptions['packagefile'] = $f->getName(); // must end in trailing slash $this->preparedOptions['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR; $this->log("Creating package file: " . $f->__toString(), PROJECT_MSG_INFO); } else { $this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO); } // converts option objects and mapping objects into // key => value options that can be passed to PEAR_PackageFileManager foreach($this->options as $opt) { $this->preparedOptions[ $opt->getName() ] = $opt->getValue(); //no arrays yet. preg_split('/\s*,\s*/', $opt->getValue()); } foreach($this->mappings as $map) { $value = $map->getValue(); // getValue returns complex value if ($map->getName() == 'deps') { $value = $this->fixDeps($value); } $this->preparedOptions[ $map->getName() ] = $value; } } /** * Main entry point. * @return void */ public function main() { if ($this->dir === null) { throw new BuildException("You must specify the \"dir\" attribute for PEAR package task."); } if ($this->package === null) { throw new BuildException("You must specify the \"name\" attribute for PEAR package task."); } $this->pkg = new PEAR_PackageFileManager(); $this->setOptions(); $e = $this->pkg->writePackageFile(); if (PEAR::isError($e)) { throw new BuildException("Unable to write package file.", new Exception($e->getMessage())); } } /** * Used by the PEAR_PackageFileManager_PhingFileSet lister. * @return array FileSet[] */ public function getFileSets() { return $this->filesets; } // ------------------------------- // Set properties from XML // -------------------------------
/** * Nested creator, creates a FileSet for this task * * @return FileSet The created fileset object */ function createFileSet() { $num = array_push($this->filesets, new FileSet()); return $this->filesets[$num-1]; } /** * Set "package" property from XML. * @see setName() * @param string $v * @return void */ public function setPackage($v) { $this->package = $v; } /** * Sets "dir" property from XML. * @param PhingFile $f * @return void */ public function setDir(PhingFile $f) { $this->dir = $f; }
/** * Sets "name" property from XML. * @param string $v * @return void */ public function setName($v) { $this->package = $v; } /** * Sets the file to use for generated package.xml */ public function setDestFile(PhingFile $f) { $this->packageFile = $f; } /** * Handles nested generic <option> elements. */ function createOption() { $o = new PearPkgOption(); $this->options[] = $o; return $o; } /** * Handles nested generic <option> elements. */ function createMapping() { $o = new PearPkgMapping(); $this->mappings[] = $o; return $o; } }
/** * Generic option class is used for non-complex options. */ class PearPkgOption { private $name; private $value; public function setName($v) { $this->name = $v; } public function getName() { return $this->name; } public function setValue($v) { $this->value = $v; } public function getValue() { return $this->value; } public function addText($txt) { $this->value = trim($txt); } }
/** * Handles complex options <mapping> elements which are hashes (assoc arrays). */ class PearPkgMapping {
private $name; private $elements = array(); public function setName($v) { $this->name = $v; } public function getName() { return $this->name; }
public function createElement() { $e = new PearPkgMappingElement(); $this->elements[] = $e; return $e; } public function getElements() { return $this->elements; } /** * Returns the PHP hash or array of hashes (etc.) that this mapping represents. * @return array */ public function getValue() { $value = array(); foreach($this->getElements() as $el) { if ($el->getKey() !== null) { $value[ $el->getKey() ] = $el->getValue(); } else { $value[] = $el->getValue(); } } return $value; } }
/** * Sub-element of <mapping>. */ class PearPkgMappingElement {
private $key; private $value; private $elements = array(); public function setKey($v) { $this->key = $v; } public function getKey() { return $this->key; } public function setValue($v) { $this->value = $v; } /** * Returns either the simple value or * the calculated value (array) of nested elements. * @return mixed */ public function getValue() { if (!empty($this->elements)) { $value = array(); foreach($this->elements as $el) { if ($el->getKey() !== null) { $value[ $el->getKey() ] = $el->getValue(); } else { $value[] = $el->getValue(); } } return $value; } else { return $this->value; } } /** * Handles nested <element> tags. */ public function createElement() { $e = new PearPkgMappingElement(); $this->elements[] = $e; return $e; } }
|