diff options
Diffstat (limited to 'buildscripts/phing/classes')
377 files changed, 36331 insertions, 11361 deletions
diff --git a/buildscripts/phing/classes/phing/BuildEvent.php b/buildscripts/phing/classes/phing/BuildEvent.php index d4e1ea79..581f7cf4 100644..100755 --- a/buildscripts/phing/classes/phing/BuildEvent.php +++ b/buildscripts/phing/classes/phing/BuildEvent.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: BuildEvent.php,v 1.10 2005/12/22 22:44:46 hlellelid Exp $ + *  $Id: 47c800dd15c2367bb5890065f96ffceb7ae9ba55 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -37,61 +37,57 @@ require_once 'phing/system/lang/EventObject.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.10 $ + * @version   $Id$   * @package   phing   */  class BuildEvent extends EventObject {      /** -     *  A reference to the project -     *  @var Project +     * A reference to the project +     * @var Project       */      protected $project;      /** -     *  A reference to the target -     *  @var Target +     * A reference to the target +     * @var Target       */      protected $target;      /** -     *  A reference to the task +     * A reference to the task       * -     *  @var Task +     * @var Task       */      protected $task;      /** -     *  The message of this event, if the event is a message -     *  @var    string -     *  @access private +     * The message of this event, if the event is a message +     * @var string       */      protected $message = null;      /** -     *  The priority of the message +     * The priority of the message       * -     *  @var    string -     *  @see    $message -     *  @access private +     * @var    string +     * @see    $message       */ -    protected $priority = PROJECT_MSG_VERBOSE; +    protected $priority = Project::MSG_VERBOSE;      /** -     *  The execption that caused the event, if any +     * The execption that caused the event, if any       * -     *  @var    object -     *  @access private +     * @var    object       */      protected $exception = null;      /** -     *  Construct a BuildEvent for a project, task or target source event +     * Construct a BuildEvent for a project, task or target source event       * -     *  @param  object  project the project that emitted the event. -     *  @access public +     * @param  object  project the project that emitted the event.       */ -    function __construct($source) { +    public function __construct($source) {          parent::__construct($source);          if ($source instanceof Project) {              $this->project = $source; @@ -111,95 +107,92 @@ class BuildEvent extends EventObject {      }      /** -     *  Sets the message with details and the message priority for this event. +     * Sets the message with details and the message priority for this event.       * -     *  @param  string   The string message of the event -     *  @param  integer  The priority this message should have +     * @param  string   The string message of the event +     * @param  integer  The priority this message should have       */ -    function setMessage($message, $priority) { +    public function setMessage($message, $priority) {          $this->message = (string) $message;          $this->priority = (int) $priority;      }      /** -     *  Set the exception that was the cause of this event. +     * Set the exception that was the cause of this event.       * -     *  @param  Exception The exception that caused the event +     * @param  Exception The exception that caused the event       */ -    function setException($exception) { +    public function setException($exception) {          $this->exception = $exception;      }      /** -     *  Returns the project instance that fired this event. +     * Returns the project instance that fired this event.       * -     *  The reference to the project instance is set by the constructor if this -     *  event was fired from the project class. +     * The reference to the project instance is set by the constructor if this +     * event was fired from the project class.       * -     *  @return  Project  The project instance that fired this event +     * @return  Project  The project instance that fired this event       */ -    function getProject() { +    public function getProject() {          return $this->project;      }      /** -     *  Returns the target instance that fired this event. +     * Returns the target instance that fired this event.       * -     *  The reference to the target instance is set by the constructor if this -     *  event was fired from the target class. +     * The reference to the target instance is set by the constructor if this +     * event was fired from the target class.       * -     *  @return  object  The target that fired this event -     *  @access  public +     * @return Target The target that fired this event       */ -    function getTarget() { +    public function getTarget() {          return $this->target;      }      /** -     *  Returns the target instance that fired this event. +     * Returns the target instance that fired this event.       * -     *  The reference to the task instance is set by the constructor if this -     *  event was fired within a task. +     * The reference to the task instance is set by the constructor if this +     * event was fired within a task.       * -     *  @return  object  The task that fired this event -     *  @access  public +     * @return Task The task that fired this event       */ -    function getTask() { +    public function getTask() {          return $this->task;      }      /** -     *  Returns the logging message. This field will only be set for -     *  "messageLogged" events. +     * Returns the logging message. This field will only be set for +     * "messageLogged" events.       * -     *  @return  string   The log message -     *  @access  public +     * @return string The log message       */      function getMessage() {          return $this->message;      }      /** -     *  Returns the priority of the logging message. This field will only -     *  be set for "messageLogged" events. +     * Returns the priority of the logging message. This field will only +     * be set for "messageLogged" events.       * -     *  @return  integer  The message priority -     *  @access  public +     * @return integer The message priority       */      function getPriority() {          return $this->priority;      }      /** -     *  Returns the exception that was thrown, if any. -     *  This field will only be set for "taskFinished", "targetFinished", and -     *  "buildFinished" events. +     * Returns the exception that was thrown, if any. +     * This field will only be set for "taskFinished", "targetFinished", and +     * "buildFinished" events.       * -     *  @see BuildListener::taskFinished() -     *  @see BuildListener::targetFinished() -     *  @see BuildListener::buildFinished() +     * @see BuildListener::taskFinished() +     * @see BuildListener::targetFinished() +     * @see BuildListener::buildFinished() +     * @return Exception       */ -    function getException() { +    public function getException() {          return $this->exception;      }  } diff --git a/buildscripts/phing/classes/phing/BuildException.php b/buildscripts/phing/classes/phing/BuildException.php index 8c108130..dda1a05a 100644..100755 --- a/buildscripts/phing/classes/phing/BuildException.php +++ b/buildscripts/phing/classes/phing/BuildException.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: BuildException.php,v 1.12 2005/02/27 20:52:07 mrook Exp $ + *  $Id: 5edc6b90e055d23ecceac1b6fd7e5fa80e86e006 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,15 +23,21 @@   * BuildException is for when things go wrong in a build execution.   *   * @author   Andreas Aderhold <andi@binarycloud.com> - * @version  $Revision: 1.12 $ + * @version  $Id$   * @package  phing   */  class BuildException extends Exception { -    /** location in the xml file */ -    protected $location = null;  +    /** +     * Location in the xml file. +     * @var Location +     */ +    protected $location; -    /** The nested "cause" exception. */ +    /** +     * The nested "cause" exception. +     * @var Exception +     */      protected $cause;      /** @@ -43,8 +49,11 @@ class BuildException extends Exception {       *         throw new BuildException($msg, $causeExc);       *         throw new BuildException($msg, $loc);       *         throw new BuildException($msg, $causeExc, $loc); +     * @param Exception|string $p1 +     * @param Location|Exception|null $p2 +     * @param Location|null $p3       */ -    function __construct($p1, $p2 = null, $p3 = null) {         +    public function __construct($p1, $p2 = null, $p3 = null) {                  $cause = null;          $loc = null; @@ -84,15 +93,30 @@ class BuildException extends Exception {          }                      } -    function getCause() { +    /** +     * Gets the cause exception. +     * +     * @return Exception +     */ +    public function getCause() {          return $this->cause;      } -    function getLocation() { +    /** +     * Gets the location of error in XML file. +     * +     * @return Location +     */ +    public function getLocation() {          return $this->location;      } -    function setLocation($loc) {         +    /** +     * Sets the location of error in XML file. +     * +     * @param Location $loc +     */ +    public function setLocation(Location $loc) {                  $this->location = $loc;          $this->message = $loc->toString() . ': ' . $this->message;      } diff --git a/buildscripts/phing/classes/phing/BuildListener.php b/buildscripts/phing/classes/phing/BuildListener.php index 12a96c7b..a4086aa3 100644..100755 --- a/buildscripts/phing/classes/phing/BuildListener.php +++ b/buildscripts/phing/classes/phing/BuildListener.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: BuildListener.php,v 1.6 2003/12/22 18:05:38 hlellelid Exp $ + *  $Id: 46e871c830686838e509a3b0e173e7f4c0736ab3 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.6 $ + * @version   $Id$   * @see       BuildEvent   * @see       Project::addBuildListener()   * @package   phing @@ -37,55 +37,55 @@ interface BuildListener {      /**       * Fired before any targets are started.       * -     * @param BuildEvent The BuildEvent +     * @param BuildEvent $event The BuildEvent       */ -    function buildStarted(BuildEvent $event); +    public function buildStarted(BuildEvent $event);      /**       * Fired after the last target has finished.       * -     * @param BuildEvent The BuildEvent +     * @param BuildEvent $event The BuildEvent       * @see BuildEvent::getException()       */ -    function buildFinished(BuildEvent $event); +    public function buildFinished(BuildEvent $event);      /**       * Fired when a target is started.       * -     * @param BuildEvent The BuildEvent +     * @param BuildEvent $event The BuildEvent       * @see BuildEvent::getTarget()       */ -    function targetStarted(BuildEvent $event); +    public function targetStarted(BuildEvent $event);      /**       * Fired when a target has finished.       * -     * @param BuildEvent The BuildEvent +     * @param BuildEvent $event The BuildEvent       * @see BuildEvent#getException()       */ -    function targetFinished(BuildEvent $event); +    public function targetFinished(BuildEvent $event);      /**       * Fired when a task is started.       * -     * @param BuildEvent The BuildEvent +     * @param BuildEvent $event The BuildEvent       * @see BuildEvent::getTask()       */ -    function taskStarted(BuildEvent $event); +    public function taskStarted(BuildEvent $event);      /** -     *  Fired when a task has finished. +     * Fired when a task has finished.       * -     *  @param BuildEvent The BuildEvent -     *  @see BuildEvent::getException() +     * @param BuildEvent $event The BuildEvent +     * @see BuildEvent::getException()       */ -    function taskFinished(BuildEvent $event); +    public function taskFinished(BuildEvent $event);      /** -     *  Fired whenever a message is logged. +     * Fired whenever a message is logged.       * -     *  @param BuildEvent The BuildEvent -     *  @see BuildEvent::getMessage() +     * @param BuildEvent $event The BuildEvent +     * @see BuildEvent::getMessage()       */ -    function messageLogged(BuildEvent $event); +    public function messageLogged(BuildEvent $event);  } diff --git a/buildscripts/phing/classes/phing/BuildLogger.php b/buildscripts/phing/classes/phing/BuildLogger.php new file mode 100755 index 00000000..03458159 --- /dev/null +++ b/buildscripts/phing/classes/phing/BuildLogger.php @@ -0,0 +1,70 @@ +<?php +/* + *  $Id: 64eb45bf98f65e415da03c93c4f0d89573a5e29c $ + * + * 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/BuildListener.php'; + +/** + * Interface for build loggers. + *  + * Build loggers are build listeners but with some additional functionality: + *   - They can be configured with a log level (below which they will ignore messages) + *   - They have error and output streams  + * + * Classes that implement a listener must implement this interface. + * + * @author    Hans Lellelid <hans@xmpl.org> + * @version   $Id$ + * @see       BuildEvent + * @see       Project::addBuildListener() + * @package   phing + */ +interface BuildLogger extends BuildListener { + +    /** +     * Sets the min log level that this logger should respect. +     *  +     * Messages below this level are ignored. +     * +     * Constants for the message levels are in Project.php. The order of +     * the levels, from least to most verbose, is: +     *   - Project::MSG_ERR +     *   - Project::MSG_WARN +     *   - Project::MSG_INFO +     *   - Project::MSG_VERBOSE +     *   - Project::MSG_DEBUG +     * +     * @param int $level The log level integer (e.g. Project::MSG_VERBOSE, etc.). +     */ +    public function setMessageOutputLevel($level); + +    /** +     * Sets the standard output stream to use. +     * @param OutputStream $output Configured output stream (e.g. STDOUT) for standard output.  +     */ +    public function setOutputStream(OutputStream $output); + +    /** +     * Sets the output stream to use for errors. +     * @param OutputStream $err Configured output stream (e.g. STDERR) for errors. +     */ +    public function setErrorStream(OutputStream $err); + +} diff --git a/buildscripts/phing/classes/phing/ConfigurationException.php b/buildscripts/phing/classes/phing/ConfigurationException.php new file mode 100755 index 00000000..81735e1b --- /dev/null +++ b/buildscripts/phing/classes/phing/ConfigurationException.php @@ -0,0 +1,85 @@ +<?php +/* + *  $Id: 6070efdfa67cb145fd48525e88737d39c8eff4b2 $ + * + * 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>. + */ + +/** + * ConfigurationException is thrown by Phing during the configuration and setup phase of the project. + * + * @author   Hans Lellelid <hans@xmpl.org> + * @version  $Id$ + * @package  phing + */ +class ConfigurationException extends Exception { + +    /** +     * Location in the xml file. +     * @var Location +     */ +    protected $location; + +    /** +     * The nested "cause" exception. +     * @var Exception +     */ +    protected $cause; + +    /** +     * Construct a ConfigurationException. +     * Supported signatures: +     *         throw new BuildException($causeExc); +     *         throw new BuildException($msg); +     *         throw new BuildException($msg, $causeExc); +     * @param Exception|string $p1 +     * @param Exception|null $p2 +     */ +    public function __construct($p1, $p2 = null) { + +        $cause = null; +        $msg = ""; + +        if ($p2 !== null) { +            if ($p2 instanceof Exception) { +                $cause = $p2; +                $msg = $p1; +            } +        } elseif ($p1 instanceof Exception) { +            $cause = $p1; +        } else { +            $msg = $p1; +        } + +        parent::__construct($msg); + +        if ($cause !== null) { +            $this->cause = $cause; +            $this->message .= " [wrapped: " . $cause->getMessage() ."]"; +        } +    } +     +    /** +     * Gets the cause exception. +     * +     * @return Exception +     */ +    public function getCause() { +        return $this->cause; +    } +      +} diff --git a/buildscripts/phing/classes/phing/IntrospectionHelper.php b/buildscripts/phing/classes/phing/IntrospectionHelper.php index b4300950..8bcf2456 100644..100755 --- a/buildscripts/phing/classes/phing/IntrospectionHelper.php +++ b/buildscripts/phing/classes/phing/IntrospectionHelper.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: IntrospectionHelper.php,v 1.19 2005/11/08 20:45:59 hlellelid Exp $ + *  $Id: a5f2dbd71bafd2c363026d911132c3b47bf44239 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -36,8 +36,8 @@ include_once 'phing/util/StringHelper.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.19 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id: a5f2dbd71bafd2c363026d911132c3b47bf44239 $   * @package   phing   */  class IntrospectionHelper { @@ -123,9 +123,9 @@ class IntrospectionHelper {       * need to perform any introspection -- either the requested attribute setter/creator       * exists or it does not & a BuildException is thrown.       *  -     * @param string $bean The classname for this IH. +     * @param string $class The classname for this IH.       */ -    function __construct($class) { +    public function __construct($class) {          $this->bean = new ReflectionClass($class); @@ -178,7 +178,7 @@ class IntrospectionHelper {                  } elseif (strpos($name, "create") === 0) {                             -                    if (count($method->getParameters()) > 0) { +                    if ($method->getNumberOfRequiredParameters() > 0) {                          throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() may not take any parameters.");                      } @@ -266,8 +266,14 @@ class IntrospectionHelper {      } -    /** Sets the named attribute. */ -    function setAttribute(Project $project, $element, $attributeName, &$value) { +    /** +     * Sets the named attribute. +     * @param Project $project +     * @param string $element +     * @param string $attributeName +     * @param mixed $value +     */ +    public function setAttribute(Project $project, $element, $attributeName, &$value) {          // we want to check whether the value we are setting looks like          // a slot-listener variable:  %{task.current_file} @@ -309,10 +315,6 @@ class IntrospectionHelper {              if ($as == "setrefid") {                              $value = new Reference($value);              } else { -             -                // decode any html entities in string -                $value = html_entity_decode($value);                 -                                  // value is a string representation of a boolean type,                  // convert it to primitive                  if (StringHelper::isBoolean($value)) { @@ -352,7 +354,7 @@ class IntrospectionHelper {          } // if is slot-listener          try { -            $project->log("    -calling setter ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG); +            $project->log("    -calling setter ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);              $method->invoke($element, $value);          } catch(Exception $exc) {              throw new BuildException($exc); @@ -360,8 +362,14 @@ class IntrospectionHelper {      } -    /** Adds PCDATA areas.*/ -    function addText(Project $project, $element, $text) { +    /** +     * Adds PCDATA areas. +     * +     * @param Project $project +     * @param string $element +     * @param string $text +     */ +    public function addText(Project $project, $element, $text) {          if ($this->methodAddText === null) {              $msg = $this->getElementName($project, $element)." doesn't support nested text data.";              throw new BuildException($msg); @@ -378,10 +386,14 @@ class IntrospectionHelper {       * Creates a named nested element.        *        * Valid creators can be in the form createFoo() or addFoo(Bar). +     * +     * @param  Project $project +     * @param  string $element +     * @param  string $elementName       * @return object Returns the nested element.       * @throws BuildException       */ -    function createElement(Project $project, $element, $elementName) { +    public function createElement(Project $project, $element, $elementName) {          $addMethod = "add".strtolower($elementName);          $createMethod = "create".strtolower($elementName); @@ -391,7 +403,7 @@ class IntrospectionHelper {              $method = $this->nestedCreators[$createMethod];               try { // try to invoke the creator method on object -                $project->log("    -calling creator ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG); +                $project->log("    -calling creator ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);                  $nestedElement = $method->invoke($element);              } catch (Exception $exc) {                  throw new BuildException($exc); @@ -405,7 +417,7 @@ class IntrospectionHelper {              try { // try to invoke the adder method on object -                $project->log("    -calling adder ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG); +                $project->log("    -calling adder ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);                  // we've already assured that correct num of params                  // exist and that method is using class hints                                  $params = $method->getParameters(); @@ -438,10 +450,15 @@ class IntrospectionHelper {      /**       * Creates a named nested element. +     * +     * @param  Project $project +     * @param  string $element +     * @param  string $child +     * @param  string|null $elementName       * @return void       * @throws BuildException       */ -    function storeElement($project, $element, $child, $elementName = null) { +    public function storeElement($project, $element, $child, $elementName = null) {          if ($elementName === null) {              return; @@ -454,7 +471,7 @@ class IntrospectionHelper {              $method = $this->nestedStorers[$storer];              try {                                 -                $project->log("    -calling storer ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG);                     +                $project->log("    -calling storer ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);                                      $method->invoke($element, $child);                          } catch (Exception $exc) {                  throw new BuildException($exc); @@ -463,13 +480,19 @@ class IntrospectionHelper {      } -    /** Does the introspected class support PCDATA? */ -    function supportsCharacters() { +    /** +     * Does the introspected class support PCDATA? +     * @return boolean +     */ +    public function supportsCharacters() {          return ($this->methodAddText !== null);      } -    /** Return all attribues supported by the introspected class. */ -    function getAttributes() { +    /** +     * Return all attribues supported by the introspected class. +     * @return string[] +     */ +    public function getAttributes() {          $attribs = array();          foreach (array_keys($this->attributeSetters) as $setter) {              $attribs[] =$this->getPropertyName($setter, "set"); @@ -477,8 +500,11 @@ class IntrospectionHelper {          return $attribs;      } -    /** Return all nested elements supported by the introspected class. */ -    function getNestedElements() { +    /** +     * Return all nested elements supported by the introspected class. +     * @return string[] +     */ +    public function getNestedElements() {          return $this->nestedTypes;      } @@ -492,7 +518,7 @@ class IntrospectionHelper {       * @param object $element The Task or type element.       * @return string Fully qualified class name of element when possible.       */ -    function getElementName(Project $project, $element) { +    public function getElementName(Project $project, $element) {            $taskdefs = $project->getTaskDefinitions();          $typedefs = $project->getDataTypeDefinitions(); @@ -524,17 +550,24 @@ class IntrospectionHelper {          }              } -    /** extract the name of a property from a method name - subtracting  a given prefix. */ -    function getPropertyName($methodName, $prefix) { +    /** +     * Extract the name of a property from a method name - subtracting  a given prefix. +     * +     * @param  string $methodName +     * @param  string $prefix +     * @return string +     */ +    public function getPropertyName($methodName, $prefix) {          $start = strlen($prefix);          return strtolower(substr($methodName, $start));      }      /**       * Prints warning message to screen if -debug was used. +     * @param string $msg       */ -    function warn($msg) { -        if (Phing::getMsgOutputLevel() === PROJECT_MSG_DEBUG) { +    public function warn($msg) { +        if (Phing::getMsgOutputLevel() === Project::MSG_DEBUG) {              print("[IntrospectionHelper] " . $msg . "\n");          }      } diff --git a/buildscripts/phing/classes/phing/Phing.php b/buildscripts/phing/classes/phing/Phing.php index bb8d67f6..d663ee42 100644..100755 --- a/buildscripts/phing/classes/phing/Phing.php +++ b/buildscripts/phing/classes/phing/Phing.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: Phing.php,v 1.51 2006/01/06 15:12:33 hlellelid Exp $ + * $Id: 1ad418f51ac07c9afaadf1c1f4befd5535f5b390 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -18,13 +18,14 @@   * and is licensed under the LGPL. For more information please see   * <http://phing.info>.   */ -  +  require_once 'phing/Project.php';  require_once 'phing/ProjectComponent.php';  require_once 'phing/Target.php';  require_once 'phing/Task.php';  include_once 'phing/BuildException.php'; +include_once 'phing/ConfigurationException.php';  include_once 'phing/BuildEvent.php';  include_once 'phing/parser/Location.php'; @@ -41,11 +42,13 @@ include_once 'phing/parser/NestedElementHandler.php';  include_once 'phing/system/util/Properties.php';  include_once 'phing/util/StringHelper.php';  include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/system/io/OutputStream.php'; +include_once 'phing/system/io/FileOutputStream.php';  include_once 'phing/system/io/FileReader.php';  include_once 'phing/system/util/Register.php';  /** - * Entry point into Phing.  This class handles the full lifecycle of a build -- from  + * Entry point into Phing.  This class handles the full lifecycle of a build -- from   * parsing & handling commandline arguments to assembling the project to shutting down   * and cleaning up in the end.   * @@ -55,7 +58,7 @@ include_once 'phing/system/util/Register.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.51 $ + * @version   $Id: 1ad418f51ac07c9afaadf1c1f4befd5535f5b390 $   * @package   phing   */  class Phing { @@ -63,8 +66,8 @@ class Phing {      /** The default build file name */      const DEFAULT_BUILD_FILENAME = "build.xml"; -    /** Our current message output status. Follows PROJECT_MSG_XXX */ -    private static $msgOutputLevel = PROJECT_MSG_INFO; +    /** Our current message output status. Follows Project::MSG_XXX */ +    private static $msgOutputLevel = Project::MSG_INFO;      /** PhingFile that we are using for configuration */      private $buildFile = null; @@ -85,90 +88,166 @@ class Phing {      /** The class to handle input (can be only one). */      private $inputHandlerClassname; -     +      /** Indicates if this phing should be run */      private $readyToRun = false;      /** Indicates we should only parse and display the project help information */      private $projectHelp = false; -     +      /** Used by utility function getResourcePath() */      private static $importPaths; -     +      /** System-wide static properties (moved from System) */      private static $properties = array(); -     +      /** Static system timer. */      private static $timer; -     -	/** The current Project */ -	private static $currentProject; -	 -	/** Whether to capture PHP errors to buffer. */ -	private static $phpErrorCapture = false; -	 -	/** Array of captured PHP errors */ -	private static $capturedPhpErrors = array(); -	 + +    /** The current Project */ +    private static $currentProject; + +    /** Whether to capture PHP errors to buffer. */ +    private static $phpErrorCapture = false; + +    /** Array of captured PHP errors */ +    private static $capturedPhpErrors = array(); +      /** -     * Prints the message of the Exception if it's not null. +     * @var OUtputStream Stream for standard output.       */ -    function printMessage(Exception $t) { -        print($t->getMessage() . "\n"); -        if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) { -            print($t->getTraceAsString()."\n"); -            if ($t instanceof Exception) {                 -                $c = $t->getCause(); -                if ($c !== null) { -                    print("Wrapped exception trace:\n"); -                    print($c->getTraceAsString() . "\n"); -                } -            } -        } // if output level is DEBUG -    } +    private static $out; -    /**  +    /** +     * @var OutputStream Stream for error output. +     */ +    private static $err; + +    /** +     * @var boolean Whether we are using a logfile. +     */ +    private static $isLogFileUsed = false; + +    /** +     * Array to hold original ini settings that Phing changes (and needs +     * to restore in restoreIni() method). +     * +     * @var array Struct of array(setting-name => setting-value) +     * @see restoreIni() +     */ +    private static $origIniSettings = array(); + +    /**       * Entry point allowing for more options from other front ends. -     *  +     *       * This method encapsulates the complete build lifecycle. -     *  -     * @param array &$args The commandline args passed to phing shell script. +     * +     * @param array $args The commandline args passed to phing shell script.       * @param array $additionalUserProperties   Any additional properties to be passed to Phing (alternative front-end might implement this).       *                                          These additional properties will be available using the getDefinedProperty() method and will -     *                                          be added to the project's "user" properties. -     * @return void +     *                                          be added to the project's "user" properties       * @see execute()       * @see runBuild() +     * @throws Exception - if there is an error during build       */ -    public static function start(&$args, $additionalUserProperties = null) { +    public static function start($args, array $additionalUserProperties = null) {          try {              $m = new Phing();              $m->execute($args);          } catch (Exception $exc) { -            $m->printMessage($exc); -            self::halt(-1); // Parameter error +            self::handleLogfile(); +            throw $exc;          }          if ($additionalUserProperties !== null) { -            $keys = $m->additionalUserProperties->keys(); -            while(count($keys)) { -                $key = array_shift($keys); -                $property = $m->additionalUserProperties->getProperty($key); -                $m->setDefinedProperty($key, $property); +            foreach($additionalUserProperties as $key => $value) { +                $m->setDefinedProperty($key, $value);              }          }          try {              $m->runBuild();          } catch(Exception $exc) { -            self::halt(1); // Errors occured +            self::handleLogfile(); +            throw $exc;          } -         +          // everything fine, shutdown -        self::halt(0); // no errors, everything is cake +        self::handleLogfile();      } -     + +    /** +     * Prints the message of the Exception if it's not null. +     * @param Exception $t +     */ +    public static function printMessage(Exception $t) { +        if (self::$err === null) { // Make sure our error output is initialized +            self::initializeOutputStreams(); +        } +        if (self::getMsgOutputLevel() >= Project::MSG_VERBOSE) { +            self::$err->write($t->__toString() . PHP_EOL); +        } else { +            self::$err->write($t->getMessage() . PHP_EOL); +        } +    } + +    /** +     * Sets the stdout and stderr streams if they are not already set. +     */ +    private static function initializeOutputStreams() { +        if (self::$out === null) { +            self::$out = new OutputStream(fopen("php://stdout", "w")); +        } +        if (self::$err === null) { +            self::$err = new OutputStream(fopen("php://stderr", "w")); +        } +    } + +    /** +     * Sets the stream to use for standard (non-error) output. +     * @param OutputStream $stream The stream to use for standard output. +     */ +    public static function setOutputStream(OutputStream $stream) { +        self::$out = $stream; +    } + +    /** +     * Gets the stream to use for standard (non-error) output. +     * @return OutputStream +     */ +    public static function getOutputStream() { +        return self::$out; +    } + +    /** +     * Sets the stream to use for error output. +     * @param OutputStream $stream The stream to use for error output. +     */ +    public static function setErrorStream(OutputStream $stream) { +        self::$err = $stream; +    } + +    /** +     * Gets the stream to use for error output. +     * @return OutputStream +     */ +    public static function getErrorStream() { +        return self::$err; +    } + +    /** +     * Close logfiles, if we have been writing to them. +     * +     * @since Phing 2.3.0 +     */ +    private static function handleLogfile() { +        if (self::$isLogFileUsed) { +            self::$err->close(); +            self::$out->close(); +        } +    } +      /**       * Making output level a static property so that this property       * can be accessed by other parts of the system, enabling @@ -177,8 +256,8 @@ class Phing {       */      public static function getMsgOutputLevel() {          return self::$msgOutputLevel; -    }         -     +    } +      /**       * Command line entry point. This method kicks off the building       * of a project object and executes a build using either a given @@ -190,65 +269,92 @@ class Phing {      public static function fire($args) {          self::start($args, null);      } -     +      /**       * Setup/initialize Phing environment from commandline args.       * @param array $args commandline args passed to phing shell.       * @return void       */      public function execute($args) { -     +          self::$definedProps = new Properties();          $this->searchForThis = null; -        // cycle through given args -        for ($i = 0, $argcount = count($args); $i < $argcount; ++$i) {  -                            // ++$i intentional here, as first param is script name +        // 1) First handle any options which should always +        // Note: The order in which these are executed is important (if multiple of these options are specified) + +        if (in_array('-help', $args) || in_array('-h', $args)) { +            $this->printUsage(); +            return; +        } + +        if (in_array('-version', $args) || in_array('-v', $args)) { +            $this->printVersion(); +            return; +        } + +        // 2) Next pull out stand-alone args. +        // Note: The order in which these are executed is important (if multiple of these options are specified) + +        if (false !== ($key = array_search('-quiet', $args, true)) || false !== ($key = array_search('-q', $args, true))) { +            self::$msgOutputLevel = Project::MSG_WARN; +            unset($args[$key]); +        } + +        if (false !== ($key = array_search('-verbose', $args, true))) { +            self::$msgOutputLevel = Project::MSG_VERBOSE; +            unset($args[$key]); +        } + +        if (false !== ($key = array_search('-debug', $args, true))) { +            self::$msgOutputLevel = Project::MSG_DEBUG; +            unset($args[$key]); +        } + +        // 3) Finally, cycle through to parse remaining args +        // +        $keys = array_keys($args); // Use keys and iterate to max(keys) since there may be some gaps         +        $max = $keys ? max($keys) : -1; +        for($i=0; $i <= $max; $i++) { + +            if (!array_key_exists($i, $args)) { +                // skip this argument, since it must have been removed above. +                continue; +            } +              $arg = $args[$i]; -            if ($arg == "-help" || $arg == "-h") { -                $this->printUsage(); -                return; -            } elseif ($arg == "-version" || $arg == "-v") { -                $this->printVersion(); -                return; -            } elseif ($arg == "-quiet" || $arg == "-q") { -                self::$msgOutputLevel = PROJECT_MSG_WARN; -            } elseif ($arg == "-verbose") { -                $this->printVersion(); -                self::$msgOutputLevel = PROJECT_MSG_VERBOSE; -            } elseif ($arg == "-debug") { -                $this->printVersion(); -                self::$msgOutputLevel = PROJECT_MSG_DEBUG; -            } elseif ($arg == "-logfile") { -                try { // try to set logfile +            if ($arg == "-logfile") { +                try { +                    // see: http://phing.info/trac/ticket/65                      if (!isset($args[$i+1])) { -                        print("You must specify a log file when using the -logfile argument\n"); -                        return; +                        $msg = "You must specify a log file when using the -logfile argument\n"; +                        throw new ConfigurationException($msg);                      } else {                          $logFile = new PhingFile($args[++$i]); -                        $this->loggerClassname = 'phing.listener.PearLogger'; -                        $this->setDefinedProperty('pear.log.name', $logFile->getAbsolutePath()); +                        $out = new FileOutputStream($logFile); // overwrite +                        self::setOutputStream($out); +                        self::setErrorStream($out); +                        self::$isLogFileUsed = true;                      }                  } catch (IOException $ioe) { -                    print("Cannot write on the specified log file. Make sure the path exists and you have write permissions.\n"); -                    throw $ioe; +                    $msg = "Cannot write on the specified log file. Make sure the path exists and you have write permissions."; +                    throw new ConfigurationException($msg, $ioe);                  }              } elseif ($arg == "-buildfile" || $arg == "-file" || $arg == "-f") {                  if (!isset($args[$i+1])) { -                    print("You must specify a buildfile when using the -buildfile argument\n"); -                    return; +                    $msg = "You must specify a buildfile when using the -buildfile argument."; +                    throw new ConfigurationException($msg);                  } else {                      $this->buildFile = new PhingFile($args[++$i]);                  }              } elseif ($arg == "-listener") {                  if (!isset($args[$i+1])) { -                    print("You must specify a listener class when using the -listener argument\n"); -                    return; +                    $msg = "You must specify a listener class when using the -listener argument"; +                    throw new ConfigurationException($msg);                  } else {                      $this->listeners[] = $args[++$i];                  } -                              } elseif (StringHelper::startsWith("-D", $arg)) {                  $name = substr($arg, 2);                  $value = null; @@ -256,28 +362,41 @@ class Phing {                  if ($posEq !== false) {                      $value = substr($name, $posEq+1);                      $name  = substr($name, 0, $posEq); -                } elseif ($i < count($args)-1) { +                } elseif ($i < count($args)-1 && !StringHelper::startsWith("-D", $args[$i + 1])) {                      $value = $args[++$i];                  }                  self::$definedProps->setProperty($name, $value);              } elseif ($arg == "-logger") {                  if (!isset($args[$i+1])) { -                    print("You must specify a classname when using the -logger argument\n"); -                    return; +                    $msg = "You must specify a classname when using the -logger argument"; +                    throw new ConfigurationException($msg);                  } else {                      $this->loggerClassname = $args[++$i];                  }              } elseif ($arg == "-inputhandler") {                  if ($this->inputHandlerClassname !== null) { -                    throw new BuildException("Only one input handler class may be specified."); +                    throw new ConfigurationException("Only one input handler class may be specified.");                  }                  if (!isset($args[$i+1])) { -                    print("You must specify a classname when using the -inputhandler argument\n"); -                    return; +                    $msg = "You must specify a classname when using the -inputhandler argument"; +                    throw new ConfigurationException($msg);                  } else {                      $this->inputHandlerClassname = $args[++$i];                  } -            } elseif ($arg == "-projecthelp" || $arg == "-targets" || $arg == "-list" || $arg == "-l") { +            } elseif ($arg == "-propertyfile") { +                if (!isset($args[$i+1])) { +                    $msg = "You must specify a filename when using the -propertyfile argument"; +                    throw new ConfigurationException($msg); +                } else { +                    $p = new Properties(); +                    $p->load(new PhingFile($args[++$i])); +                    foreach ($p->getProperties() as $prop => $value) { +                        $this->setProperty($prop, $value); +                    } +                } +            } elseif ($arg == "-longtargets") { +                self::$definedProps->setProperty('phing.showlongtargets', 1); +            } elseif ($arg == "-projecthelp" || $arg == "-targets" || $arg == "-list" || $arg == "-l" || $arg == "-p") {                  // set the flag to display the targets and quit                  $this->projectHelp = true;              } elseif ($arg == "-find") { @@ -289,8 +408,8 @@ class Phing {                  }              } elseif (substr($arg,0,1) == "-") {                  // we don't have any more args -                print("Unknown argument: $arg\n"); -                $this->printUsage(); +                self::$err->write("Unknown argument: $arg" . PHP_EOL); +                self::printUsage();                  return;              } else {                  // if it's no other arg, it may be the target @@ -309,12 +428,12 @@ class Phing {          }          // make sure buildfile exists          if (!$this->buildFile->exists()) { -            throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " does not exist!"); +            throw new ConfigurationException("Buildfile: " . $this->buildFile->__toString() . " does not exist!");          }          // make sure it's not a directory -        if ($this->buildFile->isDirectory()) {    -            throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " is a dir!"); +        if ($this->buildFile->isDirectory()) { +            throw new ConfigurationException("Buildfile: " . $this->buildFile->__toString() . " is a dir!");          }          $this->readyToRun = true; @@ -326,15 +445,10 @@ class Phing {       * @param PhingFile $file       * @return PhingFile Parent file or null if none       */ -    function _getParentFile(PhingFile $file) { +    private function _getParentFile(PhingFile $file) {          $filename = $file->getAbsolutePath();          $file     = new PhingFile($filename);          $filename = $file->getParent(); - -        if ($filename !== null && self::$msgOutputLevel >= PROJECT_MSG_VERBOSE) { -            print("Searching in $filename\n"); -        } -          return ($filename === null) ? null : new PhingFile($filename);      } @@ -345,17 +459,14 @@ class Phing {       * parent directory in search of a build file.  Once the       * root of the file-system has been reached an exception       * is thrown. -     *  +     *       * @param string $start Start file path.       * @param string $suffix Suffix filename to look for in parents.       * @return PhingFile A handle to the build file       *       * @throws BuildException    Failed to locate a build file       */ -    function _findBuildFile($start, $suffix) { -        if (self::$msgOutputLevel >= PROJECT_MSG_INFO) { -            print("Searching for $suffix ...\n"); -        } +    private function _findBuildFile($start, $suffix) {          $startf = new PhingFile($start);          $parent = new PhingFile($startf->getAbsolutePath());          $file   = new PhingFile($parent, $suffix); @@ -368,7 +479,7 @@ class Phing {              // if parent is null, then we are at the root of the fs,              // complain that we can't find the build file.              if ($parent === null) { -                throw new BuildException("Could not locate a build file!"); +                throw new ConfigurationException("Could not locate a build file!");              }              // refresh our file handle              $file = new PhingFile($parent, $suffix); @@ -385,17 +496,17 @@ class Phing {          if (!$this->readyToRun) {              return;          } -         +          $project = new Project(); -		 -		self::setCurrentProject($project); -		set_error_handler(array('Phing', 'handlePhpError')); -		 + +        self::setCurrentProject($project); +        set_error_handler(array('Phing', 'handlePhpError')); +          $error = null;          $this->addBuildListeners($project);          $this->addInputHandler($project); -         +          // set this right away, so that it can be used in logging.          $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath()); @@ -404,7 +515,7 @@ class Phing {              $project->init();          } catch (Exception $exc) {              $project->fireBuildFinished($exc); -            throw $exc;         +            throw $exc;          }          $project->setUserProperty("phing.version", $this->getPhingVersion()); @@ -421,30 +532,40 @@ class Phing {          // first use the Configurator to create the project object          // from the given build file. -                 +          try {              ProjectConfigurator::configureProject($project, $this->buildFile);          } catch (Exception $exc) {              $project->fireBuildFinished($exc); -			restore_error_handler(); -			self::unsetCurrentProject(); +            restore_error_handler(); +            self::unsetCurrentProject();              throw $exc; -        }          +        }          // make sure that we have a target to execute          if (count($this->targets) === 0) {              $this->targets[] = $project->getDefaultTarget();          } +        // make sure that minimum required phing version is satisfied +        try { +            $this->comparePhingVersion($project->getPhingVersion());  +        } catch(Exception $exc) { +            $project->fireBuildFinished($exc); +            restore_error_handler(); +            self::unsetCurrentProject(); +            throw $exc; +        } +          // execute targets if help param was not given          if (!$this->projectHelp) { -             -            try {  + +            try {                  $project->executeTargets($this->targets);              } catch (Exception $exc) {                  $project->fireBuildFinished($exc); -				restore_error_handler(); -				self::unsetCurrentProject(); +                restore_error_handler(); +                self::unsetCurrentProject();                  throw $exc;              }          } @@ -455,32 +576,68 @@ class Phing {                  $this->printTargets($project);              } catch (Exception $exc) {                  $project->fireBuildFinished($exc); -				restore_error_handler(); -				self::unsetCurrentProject(); +                restore_error_handler(); +                self::unsetCurrentProject();                  throw $exc;              }          } -                 +          // finally {          if (!$this->projectHelp) {              $project->fireBuildFinished(null);          } -		 -		restore_error_handler(); -		self::unsetCurrentProject(); + +        restore_error_handler(); +        self::unsetCurrentProject();      } -     + +    private function comparePhingVersion($version) { +        $current = strtolower(self::getPhingVersion()); +        $current = trim(str_replace('phing', '', $current));  + +        // make sure that version checks are not applied to trunk +        if('dev' === $current) { +            return 1; +        } + +        if(-1 == version_compare($current, $version)) { +            throw new BuildException( +                sprintf('Incompatible Phing version (%s). Version "%s" required.', $current, $version)); +        } +    } +      /** -     * Bind any default build listeners to this project. -     * Currently this means adding the logger. +     * Bind any registered build listeners to this project. +     * +     * This means adding the logger and any build listeners that were specified +     * with -listener arg. +     *       * @param Project $project       * @return void       */      private function addBuildListeners(Project $project) {          // Add the default listener          $project->addBuildListener($this->createLogger()); + +        foreach($this->listeners as $listenerClassname) { +            try { +                $clz = Phing::import($listenerClassname); +            } catch (Exception $x) { +                $msg = "Unable to instantiate specified listener " +                . "class " . $listenerClassname . " : " +                . $e->getMessage(); +                throw new ConfigurationException($msg); +            } + +            $listener = new $clz(); + +            if ($listener instanceof StreamRequiredBuildLogger) { +                throw new ConfigurationException("Unable to add " . $listenerClassname . " as a listener, since it requires explicit error/output streams. (You can specify it as a -logger.)"); +            } +            $project->addBuildListener($listener); +        }      } -     +      /**       * Creates the InputHandler and adds it to the project.       * @@ -498,12 +655,12 @@ class Phing {                  $handler = new $clz();                  if ($project !== null && method_exists($handler, 'setProject')) {                      $handler->setProject($project); -                }  +                }              } catch (Exception $e) {                  $msg = "Unable to instantiate specified input handler " -                    . "class " . $this->inputHandlerClassname . " : " -                    . $e->getMessage(); -                throw new BuildException($msg); +                . "class " . $this->inputHandlerClassname . " : " +                . $e->getMessage(); +                throw new ConfigurationException($msg);              }          }          $project->setInputHandler($handler); @@ -511,165 +668,185 @@ class Phing {      /**       * Creates the default build logger for sending build events to the log. -     * @return BuildListener The created Logger +     * @return BuildLogger The created Logger       */      private function createLogger() {          if ($this->loggerClassname !== null) {              self::import($this->loggerClassname); -            // get class name part             +            // get class name part              $classname = self::import($this->loggerClassname);              $logger = new $classname; +            if (!($logger instanceof BuildLogger)) { +                throw new BuildException($classname . ' does not implement the BuildLogger interface.'); +            }          } else {              require_once 'phing/listener/DefaultLogger.php';              $logger = new DefaultLogger();          }          $logger->setMessageOutputLevel(self::$msgOutputLevel); +        $logger->setOutputStream(self::$out); +        $logger->setErrorStream(self::$err);          return $logger;      } -	 -	/** -	 * Sets the current Project -	 * @param Project $p -	 */ -	public static function setCurrentProject($p) { -		self::$currentProject = $p; -	} -	 -	/** -	 * Unsets the current Project -	 */ -	public static function unsetCurrentProject() { -		self::$currentProject = null; -	} -	 -	/** -	 * Gets the current Project. -	 * @return Project Current Project or NULL if none is set yet/still. -	 */ -	public static function getCurrentProject() { -		return self::$currentProject; -	} -	 -	/** -	 * A static convenience method to send a log to the current (last-setup) Project. -	 * If there is no currently-configured Project, then this will do nothing. -	 * @param string $message -	 * @param int $priority PROJECT_MSG_INFO, etc. -	 */ -	public static function log($message, $priority = PROJECT_MSG_INFO) { -		$p = self::getCurrentProject(); -		if ($p) { -			$p->log($message, $priority); -		} -	} -	 -	/** -	 * Error handler for PHP errors encountered during the build. -	 * This uses the logging for the currently configured project. -	 */ -	public static function handlePhpError($level, $message, $file, $line) { -		 + +    /** +     * Sets the current Project +     * @param Project $p +     */ +    public static function setCurrentProject($p) { +        self::$currentProject = $p; +    } + +    /** +     * Unsets the current Project +     */ +    public static function unsetCurrentProject() { +        self::$currentProject = null; +    } + +    /** +     * Gets the current Project. +     * @return Project Current Project or NULL if none is set yet/still. +     */ +    public static function getCurrentProject() { +        return self::$currentProject; +    } + +    /** +     * A static convenience method to send a log to the current (last-setup) Project. +     * If there is no currently-configured Project, then this will do nothing. +     * @param string $message +     * @param int $priority Project::MSG_INFO, etc. +     */ +    public static function log($message, $priority = Project::MSG_INFO) { +        $p = self::getCurrentProject(); +        if ($p) { +            $p->log($message, $priority); +        } +    } + +    /** +     * Error handler for PHP errors encountered during the build. +     * This uses the logging for the currently configured project. +     */ +    public static function handlePhpError($level, $message, $file, $line) { +          // don't want to print supressed errors          if (error_reporting() > 0) { -		 -			if (self::$phpErrorCapture) { -			 -				self::$capturedPhpErrors[] = array('message' => $message, 'level' => $level, 'line' => $line, 'file' => $file); -				 -			} else { -			 -				$message = '[PHP Error] ' . $message; -				$message .= ' [line ' . $line . ' of ' . $file . ']'; -		 -	            switch ($level) { -				 -					case E_STRICT: -					case E_NOTICE: -	                case E_USER_NOTICE: -						self::log($message, PROJECT_MSG_VERBOSE); -	                    break; -					case E_WARNING: -	                case E_USER_WARNING: -						self::log($message, PROJECT_MSG_WARN); -	                    break; -	                case E_ERROR: -					case E_USER_ERROR: -	                default: -						self::log($message, PROJECT_MSG_ERR); -	 -	            } // switch -				 -			} // if phpErrorCapture -			 + +            if (self::$phpErrorCapture) { + +                self::$capturedPhpErrors[] = array('message' => $message, 'level' => $level, 'line' => $line, 'file' => $file); + +            } else { + +                $message = '[PHP Error] ' . $message; +                $message .= ' [line ' . $line . ' of ' . $file . ']'; + +                switch ($level) { +                    case 16384: // E_USER_DEPRECATED +                    case 8192:  // E_DEPRECATED +                    case E_STRICT: +                    case E_NOTICE: +                    case E_USER_NOTICE: +                        self::log($message, Project::MSG_VERBOSE); +                        break; +                    case E_WARNING: +                    case E_USER_WARNING: +                        self::log($message, Project::MSG_WARN); +                        break; +                    case E_ERROR: +                    case E_USER_ERROR: +                    default: +                        self::log($message, Project::MSG_ERR); + +                } // switch + +            } // if phpErrorCapture +          } // if not @ -		 -	} -	 -	/** -	 * Begins capturing PHP errors to a buffer. -	 * While errors are being captured, they are not logged. -	 */ -	public static function startPhpErrorCapture() { -		self::$phpErrorCapture = true; -		self::$capturedPhpErrors = array(); -	} -	 -	/** -	 * Stops capturing PHP errors to a buffer. -	 * The errors will once again be logged after calling this method. -	 */ -	public static function stopPhpErrorCapture() { -		self::$phpErrorCapture = false; -	} -	 -	/** -	 * Clears the captured errors without affecting the starting/stopping of the capture. -	 */ -	public static function clearCapturedPhpErrors() { -		self::$capturedPhpErrors = array(); -	} -	 -	/** -	 * Gets any PHP errors that were captured to buffer. -	 * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level) -	 */ -	public static function getCapturedPhpErrors() { -		return self::$capturedPhpErrors; -	} -	 + +    } + +    /** +     * Begins capturing PHP errors to a buffer. +     * While errors are being captured, they are not logged. +     */ +    public static function startPhpErrorCapture() { +        self::$phpErrorCapture = true; +        self::$capturedPhpErrors = array(); +    } + +    /** +     * Stops capturing PHP errors to a buffer. +     * The errors will once again be logged after calling this method. +     */ +    public static function stopPhpErrorCapture() { +        self::$phpErrorCapture = false; +    } + +    /** +     * Clears the captured errors without affecting the starting/stopping of the capture. +     */ +    public static function clearCapturedPhpErrors() { +        self::$capturedPhpErrors = array(); +    } + +    /** +     * Gets any PHP errors that were captured to buffer. +     * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level) +     */ +    public static function getCapturedPhpErrors() { +        return self::$capturedPhpErrors; +    } +      /**  Prints the usage of how to use this class */ -    function printUsage() { -        $lSep = self::getProperty("line.separator"); +    public static function printUsage() { +          $msg = ""; -        $msg .= "phing [options] [target [target2 [target3] ...]]" . $lSep; -        $msg .= "Options: " . $lSep; -        $msg .= "  -h -help               print this message" . $lSep; -        $msg .= "  -l -list               list available targets in this project" . $lSep; -        $msg .= "  -v -version            print the version information and exit" . $lSep; -        $msg .= "  -q -quiet              be extra quiet" . $lSep; -        $msg .= "  -verbose               be extra verbose" . $lSep; -        $msg .= "  -debug                 print debugging information" . $lSep; -        $msg .= "  -logfile <file>        use given file for log" . $lSep; -        $msg .= "  -logger <classname>    the class which is to perform logging" . $lSep; -        $msg .= "  -f -buildfile <file>   use given buildfile" . $lSep; -        $msg .= "  -D<property>=<value>   use value for given property" . $lSep; -        $msg .= "  -find <file>           search for buildfile towards the root of the" . $lSep; -        $msg .= "                         filesystem and use it" . $lSep; -        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . $lSep; -        $msg .= $lSep; -        $msg .= "Report bugs to <dev@phing.tigris.org>".$lSep; -        print($msg); +        $msg .= "phing [options] [target [target2 [target3] ...]]" . PHP_EOL; +        $msg .= "Options: " . PHP_EOL; +        $msg .= "  -h -help               print this message" . PHP_EOL; +        $msg .= "  -l -list               list available targets in this project" . PHP_EOL; +        $msg .= "  -v -version            print the version information and exit" . PHP_EOL; +        $msg .= "  -q -quiet              be extra quiet" . PHP_EOL; +        $msg .= "  -verbose               be extra verbose" . PHP_EOL; +        $msg .= "  -debug                 print debugging information" . PHP_EOL; +        $msg .= "  -longtargets           show target descriptions during build" . PHP_EOL; +        $msg .= "  -logfile <file>        use given file for log" . PHP_EOL; +        $msg .= "  -logger <classname>    the class which is to perform logging" . PHP_EOL; +        $msg .= "  -f -buildfile <file>   use given buildfile" . PHP_EOL; +        $msg .= "  -D<property>=<value>   use value for given property" . PHP_EOL; +        $msg .= "  -propertyfile <file>   load all properties from file" . PHP_EOL; +        $msg .= "  -find <file>           search for buildfile towards the root of the" . PHP_EOL; +        $msg .= "                         filesystem and use it" . PHP_EOL; +        $msg .= "  -inputhandler <file>   the class to use to handle user input" . PHP_EOL; +        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . PHP_EOL; +        $msg .= PHP_EOL; +        $msg .= "Report bugs to <dev@phing.tigris.org>".PHP_EOL; +        self::$err->write($msg);      } -    function printVersion() { -        print(self::getPhingVersion()."\n"); +    /** +     * Prints the current Phing version. +     */ +    public static function printVersion() { +        self::$out->write(self::getPhingVersion().PHP_EOL);      } -    function getPhingVersion() { +    /** +     * Gets the current Phing version based on VERSION.TXT file. +     * @return string +     * @throws BuildException - if unable to find version file. +     */ +    public static function getPhingVersion() {          $versionPath = self::getResourcePath("phing/etc/VERSION.TXT"); -		if ($versionPath === null) { -		    $versionPath = self::getResourcePath("etc/VERSION.TXT"); -		} +        if ($versionPath === null) { +            $versionPath = self::getResourcePath("etc/VERSION.TXT"); +        } +        if ($versionPath === null) { +            throw new ConfigurationException("No VERSION.TXT file found; try setting phing.home environment variable."); +        }          try { // try to read file              $buffer = null;              $file = new PhingFile($versionPath); @@ -679,16 +856,17 @@ class Phing {              //$buffer = "PHING version 1.0, Released 2002-??-??";              $phingVersion = $buffer;          } catch (IOException $iox) { -            print("Can't read version information file\n"); -            throw new BuildException("Build failed"); -        }         +            throw new ConfigurationException("Can't read version information file"); +        }          return $phingVersion;      } -    /**  Print the project description, if any */ -    function printDescription(Project $project) { +    /** +     * Print the project description, if any +     */ +    public static function printDescription(Project $project) {          if ($project->getDescription() !== null) { -            print($project->getDescription()."\n"); +            self::$out->write($project->getDescription() . PHP_EOL);          }      } @@ -704,31 +882,34 @@ class Phing {          // split the targets in top-level and sub-targets depending          // on the presence of a description -         +          $subNames = array();          $topNameDescMap = array(); -         -        foreach($targets as $currentTarget) {         + +        foreach($targets as $currentTarget) {              $targetName = $currentTarget->getName(); -            $targetDescription = $currentTarget->getDescription();             -             +            $targetDescription = $currentTarget->getDescription(); +            if ($currentTarget->isHidden()) { +                continue; +            } +              // subtargets are targets w/o descriptions              if ($targetDescription === null) {                  $subNames[] = $targetName;              } else {                  // topNames and topDescriptions are handled later                  // here we store in hash map (for sorting purposes) -                $topNameDescMap[$targetName] = $targetDescription;                +                $topNameDescMap[$targetName] = $targetDescription;                  if (strlen($targetName) > $maxLength) {                      $maxLength = strlen($targetName);                  }              }          } -         +          // Sort the arrays -        sort($subNames); // sort array values, resetting keys (which are numeric)         +        sort($subNames); // sort array values, resetting keys (which are numeric)          ksort($topNameDescMap); // sort the keys (targetName) keeping key=>val associations -         +          $topNames = array_keys($topNameDescMap);          $topDescriptions = array_values($topNameDescMap); @@ -750,7 +931,7 @@ class Phing {          }          $this->_printTargets($topNames, $topDescriptions, "Main targets:", $maxLength);          $this->_printTargets($subNames, null, "Subtargets:", 0); -    }     +    }      /**       * Writes a formatted list of target names with an optional description. @@ -770,14 +951,14 @@ class Phing {       *               <i>are</i> shorter than this).       */      private function _printTargets($names, $descriptions, $heading, $maxlen) { -        $lSep = self::getProperty("line.separator"); +          $spaces = '  ';          while (strlen($spaces) < $maxlen) {              $spaces .= $spaces;          }          $msg = ""; -        $msg .= $heading . $lSep; -        $msg .= str_repeat("-",79) . $lSep; +        $msg .= $heading . PHP_EOL; +        $msg .= str_repeat("-",79) . PHP_EOL;          $total = count($names);          for($i=0; $i < $total; $i++) { @@ -787,58 +968,74 @@ class Phing {                  $msg .= substr($spaces, 0, $maxlen - strlen($names[$i]) + 2);                  $msg .= $descriptions[$i];              } -            $msg .= $lSep; +            $msg .= PHP_EOL;          }          if ($total > 0) { -          print $msg . $lSep; -        }  -   } -    -   /** -    * Import a dot-path notation class path. -    * @param string $dotPath -    * @param mixed $classpath String or object supporting __toString() -    * @return string The unqualified classname (which can be instantiated). -    * @throws BuildException - if cannot find the specified file -    */ -   public static function import($dotPath, $classpath = null) { +            self::$out->write($msg . PHP_EOL); +        } +    } + +    /** +     * Import a dot-path notation class path. +     * @param string $dotPath +     * @param mixed $classpath String or object supporting __toString() +     * @return string The unqualified classname (which can be instantiated). +     * @throws BuildException - if cannot find the specified file +     */ +    public static function import($dotPath, $classpath = null) { + +        /// check if this is a PEAR-style path (@link http://pear.php.net/manual/en/standards.naming.php) +        if (strpos($dotPath, '.') === false && strpos($dotPath, '_') !== false) { +            $classname = $dotPath; +            $dotPath = str_replace('_', '.', $dotPath); +        } else { +            $classname = StringHelper::unqualify($dotPath); +        }          // first check to see that the class specified hasn't already been included.          // (this also handles case where this method is called w/ a classname rather than dotpath) -        $classname = StringHelper::unqualify($dotPath); -        if (class_exists($classname, false)) { +        if (class_exists($classname)) {              return $classname;          } -         +          $dotClassname = basename($dotPath);          $dotClassnamePos = strlen($dotPath) - strlen($dotClassname); -        $classFile = strtr($dotClassname, '.', DIRECTORY_SEPARATOR) . ".php"; + +        // 1- temporarily replace escaped '.' with another illegal char (#) +        $tmp = str_replace('\.', '##', $dotClassname); +        // 2- swap out the remaining '.' with DIR_SEP +        $tmp = strtr($tmp, '.', DIRECTORY_SEPARATOR); +        // 3- swap back the escaped '.' +        $tmp = str_replace('##', '.', $tmp); + +        $classFile = $tmp . ".php"; +          $path = substr_replace($dotPath, $classFile, $dotClassnamePos); -         +          Phing::__import($path, $classpath); -         +          return $classname; -   } +    } + +    /** +     * Import a PHP file +     * @param string $path Path to the PHP file +     * @param mixed $classpath String or object supporting __toString() +     * @throws BuildException - if cannot find the specified file +     */ +    public static function __import($path, $classpath = null) { -   /** -    * Import a PHP file -    * @param string $path Path to the PHP file -    * @param mixed $classpath String or object supporting __toString() -    * @throws BuildException - if cannot find the specified file -    */ -   public static function __import($path, $classpath = null) { -                  if ($classpath) { -         +              // Apparently casting to (string) no longer invokes __toString() automatically.              if (is_object($classpath)) {                  $classpath = $classpath->__toString();              } -             +              // classpaths are currently additive, but we also don't want to just              // indiscriminantly prepand/append stuff to the include_path.  This means              // we need to parse current incldue_path, and prepend any -            // specified classpath locations that are not already in the include_path.               +            // specified classpath locations that are not already in the include_path.              //              // NOTE:  the reason why we do it this way instead of just changing include_path              // and then changing it back, is that in many cases applications (e.g. Propel) will @@ -848,88 +1045,89 @@ class Phing {              // be more expensive than switching & switching back (not sure, but maybe), it makes it              // possible to write far less expensive run-time applications (e.g. using Propel), which is              // really where speed matters more. -             -            $curr_parts = explode(PATH_SEPARATOR, ini_get('include_path')); + +            $curr_parts = explode(PATH_SEPARATOR, get_include_path());              $add_parts = explode(PATH_SEPARATOR, $classpath);              $new_parts = array_diff($add_parts, $curr_parts);              if ($new_parts) { -                if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) { -                    print("Phing::import() prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts) . "\n"); -                } -                ini_set('include_path', implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts))); +                set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));              }          } -        $ret = include_once($path);         -         +        $ret = include_once($path); +          if ($ret === false) { -            $e = new BuildException("Error importing $path"); -            if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) { -                // We can't log this because listeners belong -                // to projects.  We'll just print it -- of course -                // that isn't very compatible w/ other frontends (but -                // there aren't any right now, so I'm not stressing) -                print("Error importing $path\n"); -                print($e->getTraceAsString()."\n"); -            }         -            throw $e; +            $msg = "Error importing $path"; +            if (self::getMsgOutputLevel() >= Project::MSG_DEBUG) { +                $x = new Exception("for-path-trace-only"); +                $msg .= $x->getTraceAsString(); +            } +            throw new ConfigurationException($msg);          } -         -        return; -   } -    -   /** -    * Looks on include path for specified file. -    * @return string File found (null if no file found). -    */ -   public static function getResourcePath($path) { -         +    } + +    /** +     * Looks on include path for specified file. +     * @return string File found (null if no file found). +     */ +    public static function getResourcePath($path) { +          if (self::$importPaths === null) { -            $paths = ini_get("include_path");             +            $paths = get_include_path();              self::$importPaths = explode(PATH_SEPARATOR, ini_get("include_path"));          } -         +          $path = str_replace('\\', DIRECTORY_SEPARATOR, $path);          $path = str_replace('/', DIRECTORY_SEPARATOR, $path);          foreach (self::$importPaths as $prefix) { -            $foo_path = $prefix . DIRECTORY_SEPARATOR . $path; -            if (file_exists($foo_path)) { -                return $foo_path; +            $testPath = $prefix . DIRECTORY_SEPARATOR . $path; +            if (file_exists($testPath)) { +                return $testPath;              }          } -         +          // Check for the property phing.home -        $home_dir = self::getProperty('phing.home'); -         -        if ($home_dir) -        { -			$home_path = $home_dir . DIRECTORY_SEPARATOR . $path; -			 -			if (file_exists($home_path)) -			{ -				return $home_path; -			} -		} -         +        $homeDir = self::getProperty('phing.home'); +        if ($homeDir) { +            $testPath = $homeDir . DIRECTORY_SEPARATOR . $path; +            if (file_exists($testPath)) { +                return $testPath; +            } +        } +          // If we are using this via PEAR then check for the file in the data dir          // This is a bit of a hack, but works better than previous solution of assuming          // data_dir is on the include_path. -        $data_dir = '@DATA-DIR@'; -        if ($data_dir{0} != '@') { // if we're using PEAR then the @ DATA-DIR @ token will have been substituted. -            $data_path = $data_dir . DIRECTORY_SEPARATOR . $path; -            if (file_exists($data_path)) { -                   return $data_path; -               } +        $dataDir = '@DATA-DIR@'; +        if ($dataDir{0} != '@') { // if we're using PEAR then the @ DATA-DIR @ token will have been substituted. +            if (!file_exists($dataDir)) { +            	self::log("The PEAR data_dir setting is incorrect: {$dataDir}.", Project::MSG_ERR); +            	self::log("Please edit using 'pear config-set data_dir ...' and re-install Phing.", Project::MSG_ERR); +            	return null; +            } +             +            $testPath = $dataDir . DIRECTORY_SEPARATOR . $path; +            if (file_exists($testPath)) { +                return $testPath; +            } +        } else { +            // We're not using PEAR, so do one additional check based on path of +            // current file (Phing.php) +            $maybeHomeDir = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR  . '..'); +            $testPath = $maybeHomeDir . DIRECTORY_SEPARATOR . $path; +            if (file_exists($testPath)) { +                return $testPath; +            }          } -         +          return null; -   } -    -   // ------------------------------------------------------------------------------------------- -   // System-wide methods (moved from System class, which had namespace conflicts w/ PEAR System) -   // ------------------------------------------------------------------------------------------- -              +    } + +    // ------------------------------------------------------------------------------------------- +    // System-wide methods (moved from System class, which had namespace conflicts w/ PEAR System) +    // ------------------------------------------------------------------------------------------- +      /**       * Set System constants which can be retrieved by calling Phing::getProperty($propName).       * @return void @@ -944,20 +1142,20 @@ class Phing {           *   Windows 98SE     => WIN32           *   FreeBSD 4.5p7    => FreeBSD           *   Redhat Linux     => Linux -		 *   Mac OS X		  => Darwin +         *   Mac OS X         => Darwin           */          self::setProperty('host.os', PHP_OS); -		 -		// this is used by some tasks too + +        // this is used by some tasks too          self::setProperty('os.name', PHP_OS); -		 +          // it's still possible this won't be defined,          // e.g. if Phing is being included in another app w/o          // using the phing.php script.          if (!defined('PHP_CLASSPATH')) {              define('PHP_CLASSPATH', get_include_path());          } -         +          self::setProperty('php.classpath', PHP_CLASSPATH);          // try to determine the host filesystem and set system property @@ -976,24 +1174,26 @@ class Phing {                  break;          } +        self::setProperty('php.interpreter', getenv('PHP_COMMAND')); +        self::setProperty('line.separator', PHP_EOL);          self::setProperty('php.version', PHP_VERSION);          self::setProperty('user.home', getenv('HOME'));          self::setProperty('application.startdir', getcwd()); -        self::setProperty('line.separator', "\n"); +        self::setProperty('phing.startTime', gmdate('D, d M Y H:i:s', time()) . ' GMT');          // try to detect machine dependent information          $sysInfo = array();          if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' && function_exists("posix_uname")) { -              $sysInfo = posix_uname(); +            $sysInfo = posix_uname();          } else { -              $sysInfo['nodename'] = php_uname('n'); -              $sysInfo['machine']= php_uname('m') ; -              //this is a not so ideal substition, but maybe better than nothing -              $sysInfo['domain'] = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : "unknown"; -              $sysInfo['release'] = php_uname('r'); -              $sysInfo['version'] = php_uname('v'); -        }               -      +            $sysInfo['nodename'] = php_uname('n'); +            $sysInfo['machine']= php_uname('m') ; +            //this is a not so ideal substition, but maybe better than nothing +            $sysInfo['domain'] = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : "unknown"; +            $sysInfo['release'] = php_uname('r'); +            $sysInfo['version'] = php_uname('v'); +        } +          self::setProperty("host.name", isset($sysInfo['nodename']) ? $sysInfo['nodename'] : "unknown");          self::setProperty("host.arch", isset($sysInfo['machine']) ? $sysInfo['machine'] : "unknown"); @@ -1002,55 +1202,55 @@ class Phing {          self::setProperty("host.os.version", isset($sysInfo['version']) ? $sysInfo['version'] : "unknown");          unset($sysInfo);      } -     +      /**       * This gets a property that was set via command line or otherwise passed into Phing.       * "Defined" in this case means "externally defined".  The reason this method exists is to -     * provide a public means of accessing commandline properties for (e.g.) logger or listener  +     * provide a public means of accessing commandline properties for (e.g.) logger or listener       * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access       * the pear.log.name property. -     *  +     *       * @param string $name       * @return string value of found property (or null, if none found).       */      public static function getDefinedProperty($name) {          return self::$definedProps->getProperty($name);      } -     +      /**       * This sets a property that was set via command line or otherwise passed into Phing. -     *  +     *       * @param string $name       * @return string value of found property (or null, if none found).       */      public static function setDefinedProperty($name, $value) {          return self::$definedProps->setProperty($name, $value);      } -     +      /**       * Returns property value for a System property. -     * System properties are "global" properties like line.separator, +     * System properties are "global" properties like application.startdir,       * and user.dir.  Many of these correspond to similar properties in Java       * or Ant. -     *  +     *       * @param string $paramName       * @return string Value of found property (or null, if none found).       */      public static function getProperty($propName) { -     +          // some properties are detemined on each access          // some are cached, see below          // default is the cached value:          $val = isset(self::$properties[$propName]) ? self::$properties[$propName] : null; -     -        // special exceptions         + +        // special exceptions          switch($propName) {              case 'user.dir':                  $val = getcwd(); -            break;             +                break;          } -         +          return $val;      } @@ -1059,56 +1259,106 @@ class Phing {          return self::$properties;      } -    public static function setProperty($propName, $propValue) {     +    public static function setProperty($propName, $propValue) {          $propName = (string) $propName;          $oldValue = self::getProperty($propName);          self::$properties[$propName] = $propValue;          return $oldValue;      } -     +      public static function currentTimeMillis() {          list($usec, $sec) = explode(" ",microtime());          return ((float)$usec + (float)$sec);      } -     +      /** -     * Sets the include path based on PHP_CLASSPATH constant (set in phing.php). +     * Sets the include path to PHP_CLASSPATH constant (if this has been defined).       * @return void +     * @throws ConfigurationException - if the include_path could not be set (for some bizarre reason)       */      private static function setIncludePaths() { -        $success = false; -                  if (defined('PHP_CLASSPATH')) { -            $success = ini_set('include_path', PHP_CLASSPATH); -        } else { -            // don't do anything, just assume that include_path has been properly set. -            $success = true; +            $result = set_include_path(PHP_CLASSPATH); +            if ($result === false) { +                throw new ConfigurationException("Could not set PHP include_path."); +            } +            self::$origIniSettings['include_path'] = $result; // save original value for setting back later          } +    } +     +    /** +     * Converts shorthand notation values as returned by ini_get()  +     * @see http://www.php.net/ini_get +     * @param string $val +     */ +    private static function convertShorthand($val) +    { +        $val = trim($val); +        $last = strtolower($val[strlen($val) - 1]); -        if ($success === false) { -            print("SYSTEM FAILURE: Could not set PHP include path\n"); -            self::halt(-1); +        switch($last) { +            // The 'G' modifier is available since PHP 5.1.0 +            case 'g': +                $val *= 1024; +            case 'm': +                $val *= 1024; +            case 'k': +                $val *= 1024;          } -    } +        return $val; +    } +      /**       * Sets PHP INI values that Phing needs.       * @return void       */      private static function setIni() { -        error_reporting(E_ALL); + +        self::$origIniSettings['error_reporting'] = error_reporting(E_ALL); + +        // We won't bother storing original max_execution_time, since 1) the value in +        // php.ini may be wrong (and there's no way to get the current value) and +        // 2) it would mean something very strange to set it to a value less than time script +        // has already been running, which would be the likely change. +          set_time_limit(0); -        ini_set('magic_quotes_gpc', 'off'); -        ini_set('short_open_tag', 'off'); -        ini_set('default_charset', 'iso-8859-1'); -        ini_set('register_globals', 'off'); -        ini_set('allow_call_time_pass_reference', 'on'); -         -        // should return memory limit in MB   -        $mem_limit = (int) ini_get('memory_limit'); -        if ($mem_limit < 32) { + +        self::$origIniSettings['magic_quotes_gpc'] = ini_set('magic_quotes_gpc', 'off'); +        self::$origIniSettings['short_open_tag'] = ini_set('short_open_tag', 'off'); +        self::$origIniSettings['default_charset'] = ini_set('default_charset', 'iso-8859-1'); +        self::$origIniSettings['register_globals'] = ini_set('register_globals', 'off'); +        self::$origIniSettings['allow_call_time_pass_reference'] = ini_set('allow_call_time_pass_reference', 'on'); +        self::$origIniSettings['track_errors'] = ini_set('track_errors', 1); + +        $mem_limit = (int) self::convertShorthand(ini_get('memory_limit')); +        if ($mem_limit < (32 * 1024 * 1024) && $mem_limit > -1) { +            // We do *not* need to save the original value here, since we don't plan to restore +            // this after shutdown (we don't trust the effectiveness of PHP's garbage collection).              ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects -        }         +        } +    } + +    /** +     * Restores [most] PHP INI values to their pre-Phing state. +     * +     * Currently the following settings are not restored: +     *  - max_execution_time (because getting current time limit is not possible) +     *  - memory_limit (which may have been increased by Phing) +     * +     * @return void +     */ +    private static function restoreIni() +    { +        foreach(self::$origIniSettings as $settingName => $settingValue) { +            switch($settingName) { +                case 'error_reporting': +                    error_reporting($settingValue); +                    break; +                default: +                    ini_set($settingName, $settingValue); +            } +        }      }      /** @@ -1122,15 +1372,17 @@ class Phing {          }          return self::$timer;      } -         -     /** + +    /**       * Start up Phing. -     * Sets up the Phing environment -- does NOT initiate the build process. +     * Sets up the Phing environment but does not initiate the build process.       * @return void +     * @throws Exception - If the Phing environment cannot be initialized.       */      public static function startup() { -        -        register_shutdown_function(array('Phing', 'shutdown')); + +        // setup STDOUT and STDERR defaults +        self::initializeOutputStreams();          // some init stuff          self::getTimer()->start(); @@ -1139,23 +1391,24 @@ class Phing {          self::setIncludePaths();          self::setIni();      } -     +      /**       * Halts the system. +     * @deprecated This method is deprecated and is no longer called by Phing internally.  Any +     *              normal shutdown routines are handled by the shutdown() method.       * @see shutdown()       */ -    public static function halt($code=0) {         -        self::shutdown($code);         +    public static function halt() { +        self::shutdown();      }      /** -     * Stops timers & exits. +     * Performs any shutdown routines, such as stopping timers.       * @return void       */ -    public static function shutdown($exitcode = 0) { -        //print("[AUTOMATIC SYSTEM SHUTDOWN]\n"); +    public static function shutdown() { +        self::restoreIni();          self::getTimer()->stop(); -        exit($exitcode); // final point where everything stops      } -     +  } diff --git a/buildscripts/phing/classes/phing/Project.php b/buildscripts/phing/classes/phing/Project.php index 8123d91e..8e662543 100644..100755 --- a/buildscripts/phing/classes/phing/Project.php +++ b/buildscripts/phing/classes/phing/Project.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Project.php,v 1.29 2006/02/02 20:27:10 hlellelid Exp $ + *  $Id: 7e67218e8e616860f9c746f9ab600f523089ea2e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,12 +19,6 @@   * <http://phing.info>.   */ -define('PROJECT_MSG_DEBUG', 4); -define('PROJECT_MSG_VERBOSE', 3); -define('PROJECT_MSG_INFO', 2); -define('PROJECT_MSG_WARN', 1); -define('PROJECT_MSG_ERR', 0); -  include_once 'phing/system/io/PhingFile.php';  include_once 'phing/util/FileUtils.php';  include_once 'phing/TaskAdapter.php'; @@ -40,11 +34,18 @@ include_once 'phing/input/DefaultInputHandler.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.29 $ + * @version   $Id: 7e67218e8e616860f9c746f9ab600f523089ea2e $   * @package   phing   */  class Project { +    // Logging level constants. +    const MSG_DEBUG = 4; +    const MSG_VERBOSE = 3; +    const MSG_INFO = 2; +    const MSG_WARN = 1; +    const MSG_ERR = 0; +          /** contains the targets */      private $targets         = array();      /** global filterset (future use) */ @@ -97,6 +98,9 @@ class Project {      /** project description */      private $description; +    /** require phing version */ +    private $phingVersion; +      /** a FileUtils object */      private $fileUtils; @@ -106,13 +110,14 @@ class Project {      /**       *  Constructor, sets any default vars.       */ -    function __construct() { +    public function __construct() {          $this->fileUtils = new FileUtils();          $this->inputHandler = new DefaultInputHandler();      }      /**       * Sets the input handler +     * @param InputHandler $handler       */      public function setInputHandler(InputHandler $handler) {          $this->inputHandler = $handler; @@ -120,13 +125,14 @@ class Project {      /**       * Retrieves the current input handler. +     * @return InputHandler       */      public function getInputHandler() {          return $this->inputHandler;      }      /** inits the project, called from main app */ -    function init() { +    public function init() {          // set builtin properties          $this->setSystemProperties(); @@ -173,7 +179,7 @@ class Project {      }      /** returns the global filterset (future use) */ -    function getGlobalFilterSet() { +    public function getGlobalFilterSet() {          return $this->globalFilterSet;      } @@ -191,18 +197,18 @@ class Project {       * @return void       */      public function setProperty($name, $value) { -	 +              // command line properties take precedence          if (isset($this->userProperties[$name])) { -            $this->log("Override ignored for user property " . $name, PROJECT_MSG_VERBOSE); +            $this->log("Override ignored for user property " . $name, Project::MSG_VERBOSE);              return;          }          if (isset($this->properties[$name])) { -            $this->log("Overriding previous definition of property " . $name, PROJECT_MSG_VERBOSE); +            $this->log("Overriding previous definition of property " . $name, Project::MSG_VERBOSE);          } -        $this->log("Setting project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG); +        $this->log("Setting project property: " . $name . " -> " . $value, Project::MSG_DEBUG);          $this->properties[$name] = $value;      } @@ -219,10 +225,10 @@ class Project {       */      public function setNewProperty($name, $value) {          if (isset($this->properties[$name])) { -            $this->log("Override ignored for property " . $name, PROJECT_MSG_DEBUG); +            $this->log("Override ignored for property " . $name, Project::MSG_DEBUG);              return;          } -        $this->log("Setting project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG); +        $this->log("Setting project property: " . $name . " -> " . $value, Project::MSG_DEBUG);          $this->properties[$name] = $value;      } @@ -236,7 +242,7 @@ class Project {       * @see #setProperty()       */      public function setUserProperty($name, $value) { -        $this->log("Setting ro project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG); +        $this->log("Setting ro project property: " . $name . " -> " . $value, Project::MSG_DEBUG);          $this->userProperties[$name] = $value;          $this->properties[$name] = $value;      } @@ -268,7 +274,7 @@ class Project {       */      private function setPropertyInternal($name, $value) {          if (isset($this->userProperties[$name])) { -			$this->log("Override ignored for user property " . $name, PROJECT_MSG_VERBOSE); +            $this->log("Override ignored for user property " . $name, Project::MSG_VERBOSE);              return;          }          $this->properties[$name] = $value; @@ -287,7 +293,15 @@ class Project {          if (!isset($this->properties[$name])) {              return null;          } -        return $this->properties[$name]; +        $found = $this->properties[$name]; +        // check to see if there are unresolved property references +        if (false !== strpos($found, '${')) { +          // attempt to resolve properties +          $found = $this->replaceProperties($found); +          // save resolved value +          $this->properties[$name] = $found; +        } +        return $found;      }      /** @@ -370,7 +384,7 @@ class Project {       * <p>To copy all "user" properties, you will also have to call       * {@link #copyUserProperties copyUserProperties}.</p>       * -     * @param other the project to copy the properties to.  Must not be null. +     * @param Project $other the project to copy the properties to.  Must not be null.       *       * @since phing 2.0       */ @@ -388,24 +402,31 @@ class Project {      // --------------------------------------------------------- -    function setDefaultTarget($targetName) { +    /** +     * Sets default target +     * @param string $targetName +     */ +    public function setDefaultTarget($targetName) {          $this->defaultTarget = (string) trim($targetName);      } -    function getDefaultTarget() { +    /** +     * Returns default target +     * @return string +     */ +    public function getDefaultTarget() {          return (string) $this->defaultTarget;      }      /**       * Sets the name of the current project       * -     * @param    string   name of project +     * @param    string $name   name of project       * @return   void       * @access   public       * @author   Andreas Aderhold, andi@binarycloud.com       */ - -    function setName($name) { +    public function setName($name) {          $this->name = (string) trim($name);          $this->setProperty("phing.project.name", $this->name);      } @@ -413,26 +434,55 @@ class Project {      /**       * Returns the name of this project       * -     * @returns  string  projectname -     * @access   public -     * @author   Andreas Aderhold, andi@binarycloud.com +     * @return  string  projectname +     * @access  public +     * @author  Andreas Aderhold, andi@binarycloud.com       */ -    function getName() { +    public function getName() {          return (string) $this->name;      } -    /** Set the projects description */ -    function setDescription($description) { +    /** +     * Set the projects description +     * @param string $description +     */ +    public function setDescription($description) {          $this->description = (string) trim($description);      } -    /** return the description, null otherwise */ -    function getDescription() { +    /** +     * return the description, null otherwise +     * @return string|null +     */ +    public function getDescription() {          return $this->description;      } -    /** Set basedir object from xml*/ -    function setBasedir($dir) { +    /** +     * Set the minimum required phing version +     * @param string $version +     */ +    public function setPhingVersion($version) { +        $version = str_replace('phing', '', strtolower($version)); +        $this->phingVersion = (string)trim($version); +    } + +    /** +     * Get the minimum required phing version +     * @return string +     */ +    public function getPhingVersion() { +        if($this->phingVersion === null) { +            $this->setPhingVersion(Phing::getPhingVersion()); +        } +        return $this->phingVersion; +    } + +    /** +     * Set basedir object from xm +     * @param PhingFile|string $dir +     */ +    public function setBasedir($dir) {          if ($dir instanceof PhingFile) {              $dir = $dir->getAbsolutePath();          } @@ -448,7 +498,7 @@ class Project {          }          $this->basedir = $dir;          $this->setPropertyInternal("project.basedir", $this->basedir->getAbsolutePath()); -        $this->log("Project base dir set to: " . $this->basedir->getPath(), PROJECT_MSG_VERBOSE); +        $this->log("Project base dir set to: " . $this->basedir->getPath(), Project::MSG_VERBOSE);          // [HL] added this so that ./ files resolve correctly.  This may be a mistake ... or may be in wrong place.                          chdir($dir->getAbsolutePath()); @@ -457,12 +507,12 @@ class Project {      /**       * Returns the basedir of this project       * -     * @returns  PhingFile  Basedir PhingFile object -     * @access   public -     * @throws   BuildException -     * @author   Andreas Aderhold, andi@binarycloud.com +     * @return  PhingFile  Basedir PhingFile object +     * @access  public +     * @throws  BuildException +     * @author  Andreas Aderhold, andi@binarycloud.com       */ -    function getBasedir() { +    public function getBasedir() {          if ($this->basedir === null) {                          try { // try to set it                  $this->setBasedir("."); @@ -478,7 +528,7 @@ class Project {       *        * @return void       */ -    function setSystemProperties() { +    public function setSystemProperties() {          // first get system properties          $systemP = array_merge( self::getProperties(), Phing::getProperties() ); @@ -504,59 +554,84 @@ class Project {       * @param string $class The class path to use.       * @param string $classpath The classpat to use.       */ -    function addTaskDefinition($name, $class, $classpath = null) { +    public function addTaskDefinition($name, $class, $classpath = null) {          $name  = $name;          $class = $class;          if ($class === "") { -            $this->log("Task $name has no class defined.", PROJECT_MSG_ERR); +            $this->log("Task $name has no class defined.", Project::MSG_ERR);          }  elseif (!isset($this->taskdefs[$name])) {              Phing::import($class, $classpath);              $this->taskdefs[$name] = $class; -            $this->log("  +Task definiton: $name ($class)", PROJECT_MSG_DEBUG); +            $this->log("  +Task definiton: $name ($class)", Project::MSG_DEBUG);          } else { -            $this->log("Task $name ($class) already registerd, skipping", PROJECT_MSG_VERBOSE); +            $this->log("Task $name ($class) already registerd, skipping", Project::MSG_VERBOSE);          }      } -    function &getTaskDefinitions() { +    /** +     * Returns the task definitions +     * @return array +     */ +    public function getTaskDefinitions() {          return $this->taskdefs;      }      /**       * Adds a data type definition. -     * @param string $name Name of tag. -     * @param string $class The class path to use. -     * @param string $classpath The classpat to use. +     * @param string $typeName Name of the type. +     * @param string $typeClass The class to use. +     * @param string $classpath The classpath to use.       */ -    function addDataTypeDefinition($typeName, $typeClass, $classpath = null) {     +    public function addDataTypeDefinition($typeName, $typeClass, $classpath = null) {              if (!isset($this->typedefs[$typeName])) {                      Phing::import($typeClass, $classpath);              $this->typedefs[$typeName] = $typeClass; -            $this->log("  +User datatype: $typeName ($typeClass)", PROJECT_MSG_DEBUG); +            $this->log("  +User datatype: $typeName ($typeClass)", Project::MSG_DEBUG);          } else { -            $this->log("Type $name ($class) already registerd, skipping", PROJECT_MSG_VERBOSE); +            $this->log("Type $typeName ($typeClass) already registerd, skipping", Project::MSG_VERBOSE);          }      } -    function getDataTypeDefinitions() { +    /** +     * Returns the data type definitions +     * @return array +     */ +    public function getDataTypeDefinitions() {          return $this->typedefs;      } -    /** add a new target to the project */ -    function addTarget($targetName, &$target) { +    /** +     * Add a new target to the project +     * @param string $targetName +     * @param Target $target +     */ +    public function addTarget($targetName, &$target) {          if (isset($this->targets[$targetName])) {              throw new BuildException("Duplicate target: $targetName");          }          $this->addOrReplaceTarget($targetName, $target);      } -    function addOrReplaceTarget($targetName, &$target) { -        $this->log("  +Target: $targetName", PROJECT_MSG_DEBUG); +    /** +     * Adds or replaces a target in the project +     * @param string $targetName +     * @param Target $target +     */ +    public function addOrReplaceTarget($targetName, &$target) { +        $this->log("  +Target: $targetName", Project::MSG_DEBUG);          $target->setProject($this);          $this->targets[$targetName] = $target; + +        $ctx = $this->getReference("phing.parsing.context"); +        $current = $ctx->getConfigurator()->getCurrentTargets(); +        $current[$targetName] = $target;      } -    function getTargets() { +    /** +     * Returns the available targets +     * @return array +     */ +    public function getTargets() {          return $this->targets;      } @@ -573,35 +648,37 @@ class Project {       * unless there's any good reason not to.       *       * @param    string    $taskType    Task name -     * @returns  Task                A task object +     * @return   Task                A task object       * @throws   BuildException       *           Exception       */ -    function createTask($taskType) { +    public function createTask($taskType) {          try { -            $cls = ""; +            $classname = "";              $tasklwr = strtolower($taskType);              foreach ($this->taskdefs as $name => $class) {                  if (strtolower($name) === $tasklwr) { -                    $cls = StringHelper::unqualify($class);                                     +                    $classname = $class;                      break;                  }              } -            if ($cls === "") { +            if ($classname === "") {                  return null;              } +            $cls = Phing::import($classname); +                          if (!class_exists($cls)) {                  throw new BuildException("Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)");              } -            $o = new $cls();         +            $o = new $cls();              if ($o instanceof Task) {                  $task = $o;              } else { -                $this->log ("  (Using TaskAdapter for: $taskType)", PROJECT_MSG_DEBUG); +                $this->log ("  (Using TaskAdapter for: $taskType)", Project::MSG_DEBUG);                  // not a real task, try adapter                  $taskA = new TaskAdapter();                  $taskA->setProxy($o); @@ -611,7 +688,7 @@ class Project {              $task->setTaskType($taskType);              // set default value, can be changed by the user              $task->setTaskName($taskType); -            $this->log ("  +Task: " . $taskType, PROJECT_MSG_DEBUG); +            $this->log ("  +Task: " . $taskType, Project::MSG_DEBUG);          } catch (Exception $t) {              throw new BuildException("Could not create task of type: " . $taskType, $t);          } @@ -620,15 +697,15 @@ class Project {      }      /** -     * Create a task instance and return reference to it +     * Create a datatype instance and return reference to it       * See createTask() for explanation how this works       * -     * @param    string   Type name -     * @returns  object   A datatype object -     * @throws   BuildException -     *           Exception +     * @param   string $typeName Type name +     * @return  object   A datatype object +     * @throws  BuildException +     *          Exception       */ -    function createDataType($typeName) {         +    public function createDataType($typeName) {                  try {              $cls = "";              $typelwr = strtolower($typeName); @@ -648,7 +725,7 @@ class Project {              }              $type = new $cls(); -            $this->log("  +Type: $typeName", PROJECT_MSG_DEBUG); +            $this->log("  +Type: $typeName", Project::MSG_DEBUG);              if (!($type instanceof DataType)) {                  throw new Exception("$class is not an instance of phing.types.DataType");              } @@ -665,11 +742,11 @@ class Project {      /**       * Executes a list of targets       * -     * @param    array  List of target names to execute -     * @returns  void -     * @throws   BuildException +     * @param   array $targetNames List of target names to execute +     * @return  void +     * @throws  BuildException       */ -    function executeTargets($targetNames) { +    public function executeTargets($targetNames) {          foreach($targetNames as $tname) {              $this->executeTarget($tname);          } @@ -678,11 +755,11 @@ class Project {      /**       * Executes a target       * -     * @param    string  Name of Target to execute -     * @returns  void -     * @throws   BuildException +     * @param   string $targetName Name of Target to execute +     * @return  void +     * @throws  BuildException       */ -    function executeTarget($targetName) { +    public function executeTarget($targetName) {          // complain about executing void          if ($targetName === null) { @@ -700,14 +777,16 @@ class Project {                  $curTarget = $sortedTargets[$curIndex++];                  $curTarget->performTasks();              } catch (BuildException $exc) { -                $this->log("Execution of target \"".$curTarget->getName()."\" failed for the following reason: ".$exc->getMessage(), PROJECT_MSG_ERR); +                $this->log("Execution of target \"".$curTarget->getName()."\" failed for the following reason: ".$exc->getMessage(), Project::MSG_ERR);                  throw $exc;              }          } while ($curTarget->getName() !== $targetName);      } - -    function resolveFile($fileName, $rootDir = null) { +    /** +     * Helper function +     */ +    public function resolveFile($fileName, $rootDir = null) {          if ($rootDir === null) {              return $this->fileUtils->resolveFile($this->basedir, $fileName);          } else { @@ -717,14 +796,14 @@ class Project {      /**       * Topologically sort a set of Targets. -     * @param  $root is the (String) name of the root Target. The sort is +     * @param  string $root is the (String) name of the root Target. The sort is       *         created in such a way that the sequence of Targets until the root       *         target is the minimum possible such sequence. -     * @param  $targets is a array representing a "name to Target" mapping +     * @param  array $targets is a array representing a "name to Target" mapping       * @return An array of Strings with the names of the targets in       *         sorted order.       */ -    function _topoSort($root, &$targets) { +    public function _topoSort($root, &$targets) {          $root     = (string) $root;          $ret      = array(); @@ -745,7 +824,7 @@ class Project {          for ($i=0, $_i=count($ret); $i < $_i; $i++) {              $retHuman .= $ret[$i]->toString()." ";          } -        $this->log("Build sequence for target '$root' is: $retHuman", PROJECT_MSG_VERBOSE); +        $this->log("Build sequence for target '$root' is: $retHuman", Project::MSG_VERBOSE);          $keys = array_keys($targets);          while($keys) { @@ -767,7 +846,7 @@ class Project {          for ($i=0,$_i=count($ret); $i < $_i; $i++) {              $retHuman .= $ret[$i]->toString()." ";          } -        $this->log("Complete build sequence is: $retHuman", PROJECT_MSG_VERBOSE); +        $this->log("Complete build sequence is: $retHuman", Project::MSG_VERBOSE);          return $ret;      } @@ -789,7 +868,7 @@ class Project {      //    "ret" now contains the sorted sequence of Targets upto the current      //    Target. -    function _tsort($root, &$targets, &$state, &$visiting, &$ret) { +    public function _tsort($root, &$targets, &$state, &$visiting, &$ret) {          $state[$root] = "VISITING";          $visiting[]  = $root; @@ -805,7 +884,7 @@ class Project {              array_pop($visiting);              if (!empty($visiting)) {                  $parent = (string) $visiting[count($visiting)-1]; -                $sb .= "It is used from target '$parent'."; +                $sb .= " It is a dependency of target '$parent'.";              }              throw new BuildException($sb);          } @@ -837,10 +916,11 @@ class Project {          $ret[] = $target;      } -    function _makeCircularException($end, $stk) { +    public function _makeCircularException($end, $stk) {          $sb = "Circular dependency: $end";          do { -            $sb .= " <- ".(string) array_pop($stk); +            $c = (string) array_pop($stk); +            $sb .= " <- ".$c;          } while($c != $end);          return new BuildException($sb);      } @@ -849,12 +929,14 @@ class Project {       * Adds a reference to an object. This method is called when the parser       * detects a id="foo" attribute. It passes the id as $name and a reference       * to the object assigned to this id as $value +     * @param string $name +     * @param object $object       */ -    function addReference($name, $object) { +    public function addReference($name, $object) {          if (isset($this->references[$name])) { -            $this->log("Overriding previous definition of reference to $name", PROJECT_MSG_WARN); +            $this->log("Overriding previous definition of reference to $name", Project::MSG_WARN);          } -        $this->log("Adding reference: $name -> ".get_class($object), PROJECT_MSG_DEBUG); +        $this->log("Adding reference: $name -> ".get_class($object), Project::MSG_DEBUG);          $this->references[$name] = $object;      } @@ -862,27 +944,29 @@ class Project {       * Returns the references array.       * @return array       */ -    function getReferences() { +    public function getReferences() {          return $this->references;      } -	 -	/** -	 * Returns a specific reference. -	 * @param string $key The reference id/key. -	 * @return object or null if not defined -	 */ -	function getReference($key) -	{ -		if (isset($this->references[$key])) { -		    return $this->references[$key]; -		} -		return null; // just to be explicit -	} +     +    /** +     * Returns a specific reference. +     * @param string $key The reference id/key. +     * @return object Reference or null if not defined +     */ +    public function getReference($key) +    { +        if (isset($this->references[$key])) { +            return $this->references[$key]; +        } +        return null; // just to be explicit +    }      /**       * Abstracting and simplifyling Logger calls for project messages +     * @param string $msg +     * @param int $level       */ -    function log($msg, $level = PROJECT_MSG_INFO) { +    public function log($msg, $level = Project::MSG_INFO) {          $this->logObject($this, $msg, $level);      } diff --git a/buildscripts/phing/classes/phing/ProjectComponent.php b/buildscripts/phing/classes/phing/ProjectComponent.php index 97ef329f..343e3a6c 100644..100755 --- a/buildscripts/phing/classes/phing/ProjectComponent.php +++ b/buildscripts/phing/classes/phing/ProjectComponent.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ProjectComponent.php,v 1.5 2003/12/24 13:02:08 hlellelid Exp $ + *  $Id: 9b2bbe8e58b0a7de3d426b1dcc88b8cac4bc69e2 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,46 +25,44 @@   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org>  - * @version   $Revision: 1.5 $ + * @version   $Id$   * @package   phing   */  abstract class ProjectComponent {      /** -     *  Holds a reference to the project that a project component -     *  (a task, a target, etc.) belongs to +     * Holds a reference to the project that a project component +     * (a task, a target, etc.) belongs to       * -     *  @var    object  A reference to the current project instance +     * @var Project A reference to the current project instance       */      protected $project = null;      /** -     *  References the project to the current component. +     * References the project to the current component.       * -     *  @param    object    The reference to the current project -     *  @access   public +     * @param Project $project The reference to the current project       */ -    function setProject($project) { +    public function setProject($project) {          $this->project = $project;      }      /** -     *  Returns a reference to current project +     * Returns a reference to current project       * -     *  @return   object   Reference to current porject object -     *  @access   public +     * @return Project Reference to current porject object       */ -    function getProject() { +    public function getProject() {          return $this->project;      }      /** -     *  Logs a message with the given priority. +     * Logs a message with the given priority.       * -     *  @param  string   The message to be logged. -     *  @param  integer  The message's priority at this message should have +     * @param string $msg The message to be logged. +     * @param integer $level The message's priority at this message should have       */ -    public function log($msg, $level = PROJECT_MSG_INFO) { +    public function log($msg, $level = Project::MSG_INFO) {          if ($this->project !== null) {              $this->project->log($msg, $level);          } diff --git a/buildscripts/phing/classes/phing/RuntimeConfigurable.php b/buildscripts/phing/classes/phing/RuntimeConfigurable.php index a23437fa..305a35f3 100644..100755 --- a/buildscripts/phing/classes/phing/RuntimeConfigurable.php +++ b/buildscripts/phing/classes/phing/RuntimeConfigurable.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: RuntimeConfigurable.php,v 1.6 2003/12/24 12:38:39 hlellelid Exp $ + *  $Id: 5dd4f1cae5f6da32a48370cf9cfaa39e1124c91c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.6 $ + * @version   $Id$   * @package   phing   */  class RuntimeConfigurable { @@ -95,8 +95,6 @@ class RuntimeConfigurable {                  $id = $this->attributes["id"];              } -            $this->attributes = null; -              if ($this->characters) {                  ProjectConfigurator::addText($project, $this->wrappedObject, (string) $this->characters);                  $this->characters=""; diff --git a/buildscripts/phing/classes/phing/Target.php b/buildscripts/phing/classes/phing/Target.php index 9aeb9440..342d11cb 100644..100755 --- a/buildscripts/phing/classes/phing/Target.php +++ b/buildscripts/phing/classes/phing/Target.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: Target.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $ + * $Id: b6779ff7860ec7a7a84d74a40ffcc9efa75255f7 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,8 +26,8 @@ include_once 'phing/TaskContainer.php';   *  abstract class {@link TaskContainer}   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.10 $ $Date: 2005/10/04 19:13:44 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id: b6779ff7860ec7a7a84d74a40ffcc9efa75255f7 $   *  @access    public   *  @see       TaskContainer   *  @package   phing @@ -35,51 +35,78 @@ include_once 'phing/TaskContainer.php';  class Target implements TaskContainer { -    /** name of target */ +    /** +     * Name of target +     * @var string +     */      private $name; -    /** dependencies */ +    /** +     * Dependencies +     * @var array +     */      private $dependencies = array(); -    /** holds objects of children of this target */ +    /** +     * Holds objects of children of this target +     * @var array +     */      private $children = array(); -    /** the if cond. from xml */ +    /** +     * The if condition from xml +     * @var string +     */      private $ifCondition = ""; -    /** the unless cond. from xml */ +    /** +     * The unless condition from xml +     * @var string +     */      private $unlessCondition = ""; -    /** description of this target */ +    /** +     * Description of this target +     * @var string +     */      private $description; + +    /** +     * Whether to hide target in targets list (-list -p switches) +     * @var boolean +     */ +    private $hidden = false; -    /** reference to project */ +    /** +     * Rreference to project  +     * @var Project +     */      private $project;      /** -     *  References the project to the current component. +     * References the project to the current component.       * -     *  @param Project The reference to the current project +     * @param Project $project The reference to the current project       */      public function setProject(Project $project) {          $this->project = $project;      }      /** -     *  Returns reference to current project +     * Returns reference to current project       * -     *  @return Project Reference to current porject object +     * @return Project Reference to current porject object       */      public function getProject() {          return $this->project;      }      /** -     *  Sets the target dependencies from xml +     * Sets the target dependencies from xml       * -     *  @param string $depends Comma separated list of targetnames that depend on +     * @param string $depends Comma separated list of targetnames that depend on       *                  this target -     *  @throws BuildException +     * @throws BuildException       */      public function setDepends($depends) {          // explode should be faster than strtok @@ -94,71 +121,103 @@ class Target implements TaskContainer {      }      /** -     *  Adds a singular dependent target name to the list +     * Adds a singular dependent target name to the list       * -     *  @param   string   The dependency target to add -     *  @access  public +     * @param   string  $dependency  The dependency target to add +     * @access  public       */      public function addDependency($dependency) {          $this->dependencies[] = (string) $dependency;      }      /** -     *  Returns reference to indexed array of the dependencies this target has. +     * Returns reference to indexed array of the dependencies this target has.       * -     *  @return  array  Referece to target dependencoes +     * @return  array  Referece to target dependencoes       */      public function getDependencies() {          return $this->dependencies;      }      /** -     *  Sets the name of the target +     * Sets the name of the target       * -     *  @param  string   Name of this target +     * @param  string  $name  Name of this target       */      public function setName($name) {          $this->name = (string) $name;      }      /** -     *  Returns name of this target. +     * Returns name of this target.       * -     *  @return  string     The name of the target -     *  @access   public +     * @return  string     The name of the target +     * @access   public       */ -    function getName() { +    public function getName() {          return (string) $this->name;      }      /** -     *  Adds a task element to the list of this targets child elements +     * Set target status. If true, target does not come in phing -list       * -     *  @param   object  The task object to add -     *  @access  public +     * @param  boolean $flag +     * @return Target       */ -    function addTask(Task $task) { +    public function setHidden($flag) +    { +        $this->hidden = (boolean) $flag; +        return $this; +    } + +    /** +     * Get target status. If true, target does not come in phing -list +     * +     * @return boolean +     */ +    public function getHidden() +    { +        return $this->hidden; +    } + +    /** +     * Alias for getHidden() +     * +     * @return boolean +     */ +    public function isHidden() +    { +        return $this->getHidden(); +    } + +    /** +     * Adds a task element to the list of this targets child elements +     * +     * @param   Task  $task  The task object to add +     * @access  public +     */ +    public function addTask(Task $task) {          $this->children[] = $task;      }      /** -     *  Adds a runtime configurable element to the list of this targets child -     *  elements. +     * Adds a runtime configurable element to the list of this targets child +     * elements.       * -     *  @param   object  The RuntimeConfigurabel object -     *  @access  public +     * @param   RuntimeConfigurable  $rtc  The RuntimeConfigurable object +     * @access  public       */ -    function addDataType($rtc) { +    public function addDataType($rtc) {          $this->children[] = $rtc;      }      /** -     *  Returns an array of all tasks this target has as childrens. +     * Returns an array of all tasks this target has as childrens.       * -     *  The task objects are copied here. Don't use this method to modify -     *  task objects. +     * The task objects are copied here. Don't use this method to modify +     * task objects.       * -     *  @return  array  Task[] +     * @return  array  Task[]       */      public function getTasks() {          $tasks = array(); @@ -173,32 +232,32 @@ class Target implements TaskContainer {      }      /** -     *  Set the if-condition from the XML tag, if any. The property name given -     *  as parameter must be present so the if condition evaluates to true +     * Set the if-condition from the XML tag, if any. The property name given +     * as parameter must be present so the if condition evaluates to true       * -     *  @param   string  The property name that has to be present -     *  @access  public +     * @param   string  $property  The property name that has to be present +     * @access  public       */      public function setIf($property) {          $this->ifCondition = ($property === null) ? "" : $property;      }      /** -     *  Set the unless-condition from the XML tag, if any. The property name -     *  given as parameter must be present so the unless condition evaluates -     *  to true +     * Set the unless-condition from the XML tag, if any. The property name +     * given as parameter must be present so the unless condition evaluates +     * to true       * -     *  @param   string  The property name that has to be present -     *  @access  public +     * @param   string  $property  The property name that has to be present +     * @access  public       */      public function setUnless($property) {          $this->unlessCondition = ($property === null) ? "" : $property;      }      /** -     *  Sets a textual description of this target. +     * Sets a textual description of this target.       * -     *  @param string The description text +     * @param string $description  The description text       */      public function setDescription($description) {          if ($description !== null && strcmp($description, "") !== 0) { @@ -209,28 +268,27 @@ class Target implements TaskContainer {      }      /** -     *  Returns the description of this target. +     * Returns the description of this target.       * -     *  @return string The description text of this target +     * @return string The description text of this target       */      public function getDescription() {          return $this->description;      }      /** -     *  Returns a string representation of this target. In our case it -     *  simply returns the target name field +     * Returns a string representation of this target. In our case it +     * simply returns the target name field       * -     *  @return string The string representation of this target +     * @return string The string representation of this target       */ -    function toString() { +    public function toString() {          return (string) $this->name;      }      /** -     *  The entry point for this class. Does some checking, then processes and -     *  performs the tasks for this target. -     * +     * The entry point for this class. Does some checking, then processes and +     * performs the tasks for this target.       */      public function main() {          if ($this->testIfCondition() && $this->testUnlessCondition()) { @@ -244,25 +302,25 @@ class Target implements TaskContainer {                  }              }          } elseif (!$this->testIfCondition()) { -            $this->project->log("Skipped target '".$this->name."' because property '".$this->ifCondition."' not set.", PROJECT_MSG_VERBOSE); +            $this->project->log("Skipped target '".$this->name."' because property '".$this->ifCondition."' not set.", Project::MSG_VERBOSE);          } else { -            $this->project->log("Skipped target '".$this->name."' because property '".$this->unlessCondition."' set.", PROJECT_MSG_VERBOSE); +            $this->project->log("Skipped target '".$this->name."' because property '".$this->unlessCondition."' set.", Project::MSG_VERBOSE);          }      }      /** -     *  Performs the tasks by calling the main method of this target that -     *  actually executes the tasks. +     * Performs the tasks by calling the main method of this target that +     * actually executes the tasks.       * -     *  This method is for ZE2 and used for proper exception handling of -     *  task exceptions. +     * This method is for ZE2 and used for proper exception handling of +     * task exceptions.       */      public function performTasks() {          try {// try to execute this target              $this->project->fireTargetStarted($this);              $this->main();              $this->project->fireTargetFinished($this, $null=null); -        } catch (Exception $exc) { +        } catch (BuildException $exc) {              // log here and rethrow              $this->project->fireTargetFinished($this, $exc);              throw $exc; @@ -270,11 +328,11 @@ class Target implements TaskContainer {      }          /** -     *  Tests if the property set in ifConfiditon exists. +     * Tests if the property set in ifConfiditon exists.       * -     *  @return  boolean  <code>true</code> if the property specified -     *                    in <code>$this->ifCondition</code> exists; -     *                    <code>false</code> otherwise +     * @return  boolean  <code>true</code> if the property specified +     *                   in <code>$this->ifCondition</code> exists; +     *                   <code>false</code> otherwise       */      private function testIfCondition() {          if ($this->ifCondition === "") { @@ -293,10 +351,10 @@ class Target implements TaskContainer {      }      /** -     *  Tests if the property set in unlessCondition exists. +     * Tests if the property set in unlessCondition exists.       * -     *  @return  boolean  <code>true</code> if the property specified -     *                    in <code>$this->unlessCondition</code> exists; +     * @return  boolean  <code>true</code> if the property specified +     *                   in <code>$this->unlessCondition</code> exists;       *                    <code>false</code> otherwise       */      private function testUnlessCondition() { diff --git a/buildscripts/phing/classes/phing/Task.php b/buildscripts/phing/classes/phing/Task.php index 893a82e9..d2490a90 100644..100755 --- a/buildscripts/phing/classes/phing/Task.php +++ b/buildscripts/phing/classes/phing/Task.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Task.php,v 1.11 2005/10/05 20:23:22 hlellelid Exp $ + *  $Id: 65e76e7a86e08ce1f1d4ef0f7cda011bc9efee5e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,58 +28,73 @@ include_once 'phing/RuntimeConfigurable.php';   * Use {@link Project#createTask} to register a new Task.   *   * @author    Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.11 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @see       Project#createTask()   * @package   phing   */  abstract class Task extends ProjectComponent { -    /** owning Target object */ +    /** +     * Owning Target object +     * @var Target +     */      protected $target; -    /** description of the task */ +    /** +     * Description of the task +     * @var string +     */      protected $description; -    /** internal taskname (req) */ +    /** +     * Internal taskname (req) +     * @var string +     */      protected $taskType; -    /** taskname for logger */ +    /** +     * Taskname for logger +     * @var string +     */      protected $taskName; -    /** stored buildfile location */ +    /** +     * Stored buildfile location +     * @var Location +     */      protected $location; -    /** wrapper of the task */ +    /** +     * Wrapper of the task +     * @var RuntimeConfigurable +     */      protected $wrapper;      /**       * Sets the owning target this task belongs to.       * -     * @param   object  Reference to owning target -     * @access  public +     * @param Target Reference to owning target       */ -    function setOwningTarget(Target $target) { +    public function setOwningTarget(Target $target) {          $this->target = $target;      }      /** -     *  Returns the owning target of this task. +     * Returns the owning target of this task.       * -     *  @return  object    The target object that owns this task -     *  @access  public +     * @return Target The target object that owns this task       */ -    function getOwningTarget() { +    public function getOwningTarget() {          return $this->target;      }      /** -     *  Returns the name of task, used only for log messages +     * Returns the name of task, used only for log messages       * -     *  @return  string  Name of this task -     *  @access  public +     * @return string Name of this task       */ -    function getTaskName() { +    public function getTaskName() {          if ($this->taskName === null) {              // if no task name is set, then it's possible              // this task was created from within another task.  We don't @@ -92,77 +107,77 @@ abstract class Task extends ProjectComponent {      }      /** -     *  Sets the name of this task for log messages +     * Sets the name of this task for log messages       * -     *  @return  string  A string representing the name of this task for log -     *  @access  public +     * @param  string $name +     * @return string A string representing the name of this task for log       */ -    function setTaskName($name) { +    public function setTaskName($name) {          $this->taskName = (string) $name;      }      /** -     *  Returns the name of the task under which it was invoked, -     *  usually the XML tagname +     * Returns the name of the task under which it was invoked, +     * usually the XML tagname       * -     *  @return string The type of this task (XML Tag) +     * @return string The type of this task (XML Tag)       */ -    function getTaskType() { +    public function getTaskType() {          return $this->taskType;      }      /** -     *  Sets the type of the task. Usually this is the name of the XML tag +     * Sets the type of the task. Usually this is the name of the XML tag       * -     *  @param string The type of this task (XML Tag) +     * @param string The type of this task (XML Tag)       */ -    function setTaskType($name) { +    public function setTaskType($name) {          $this->taskType = (string) $name;      } -	 -	/** -	 * Returns a name  -	 *  -	 */ -	protected function getRegisterSlot($slotName) { -		return Register::getSlot('task.' . $this->getTaskName() . '.' . $slotName); -	} -	 +     +    /** +     * Returns a name  +     * @param string $slotName +     */ +    protected function getRegisterSlot($slotName) { +        return Register::getSlot('task.' . $this->getTaskName() . '.' . $slotName); +    } +          /** -     *  Provides a project level log event to the task. +     * Provides a project level log event to the task.       * -     *  @param string  The message to log -     *  @param integer The priority of the message -     *  @see BuildEvent -     *  @see BuildListener +     * @param string  The message to log +     * @param integer The priority of the message +     * @see BuildEvent +     * @see BuildListener       */ -    function log($msg, $level = PROJECT_MSG_INFO) { +    function log($msg, $level = Project::MSG_INFO) {          $this->project->logObject($this, $msg, $level);      }      /** -     *  Sets a textual description of the task +     * Sets a textual description of the task       * -     *  @param    string    The text describing the task +     * @param string $desc The text describing the task       */      public function setDescription($desc) {          $this->description = $desc;      }      /** -     *  Returns the textual description of the task +     * Returns the textual description of the task       * -     *  @return  string  The text description of the task +     * @return string The text description of the task       */      public function getDescription() {          return $this->description;      }      /** -     *  Called by the parser to let the task initialize properly. -     *  Should throw a BuildException if something goes wrong with the build +     * Called by the parser to let the task initialize properly. +     * Should throw a BuildException if something goes wrong with the build       * -     *  This is abstract here, but may not be overloaded by subclasses. +     * This is abstract here, but may not be overloaded by subclasses.       *       * @throws BuildException       */ @@ -178,39 +193,35 @@ abstract class Task extends ProjectComponent {       *  Should throw a BuildException if someting goes wrong with the build       *       *  This is abstract here. Must be overloaded by real tasks. -     * -     *  @access  public       */ -    abstract function main(); +    abstract public function main();      /** -     *  Returns the location within the buildfile this task occurs. Used -     *  by {@link BuildException} to give detailed error messages. +     * Returns the location within the buildfile this task occurs. Used +     * by {@link BuildException} to give detailed error messages.       * -     *  @return Location The location object describing the position of this -     *                   task within the buildfile. +     * @return Location The location object describing the position of this +     *                  task within the buildfile.       */      function getLocation() {          return $this->location;      }      /** -     *  Sets the location within the buildfile this task occurs. Called by -     *  the parser to set location information. +     * Sets the location within the buildfile this task occurs. Called by +     * the parser to set location information.       * -     *  @return  object  The location object describing the position of this -     *                   task within the buildfile. -     *  @access  public +     * @param Location $location The location object describing the position of this +     *                           task within the buildfile.       */      function setLocation(Location $location) {          $this->location = $location;      }      /** -     *  Returns the wrapper object for runtime configuration +     * Returns the wrapper object for runtime configuration       * -     *  @return  object  The wrapper object used by this task -     *  @access  public +     * @return RuntimeConfigurable The wrapper object used by this task       */      function getRuntimeConfigurableWrapper() {          if ($this->wrapper === null) { @@ -223,8 +234,7 @@ abstract class Task extends ProjectComponent {       *  Sets the wrapper object this task should use for runtime       *  configurable elements.       * -     *  @param   object  The wrapper object this task should use -     *  @access  public +     * @param RuntimeConfigurable $wrapper The wrapper object this task should use       */      function setRuntimeConfigurableWrapper(RuntimeConfigurable $wrapper) {          $this->wrapper = $wrapper; @@ -232,21 +242,17 @@ abstract class Task extends ProjectComponent {      /**       *  Configure this task if it hasn't been done already. -     * -     *  @access  public       */ -    function maybeConfigure() { +    public function maybeConfigure() {          if ($this->wrapper !== null) {              $this->wrapper->maybeConfigure($this->project);          }      }      /** -     *  Perfrom this task -     * -     *  @access  public +     * Perfrom this task       */ -    function perform() { +    public function perform() {          try { // try executing task              $this->project->fireTaskStarted($this); diff --git a/buildscripts/phing/classes/phing/TaskAdapter.php b/buildscripts/phing/classes/phing/TaskAdapter.php index 8b84b768..ba323c56 100644..100755 --- a/buildscripts/phing/classes/phing/TaskAdapter.php +++ b/buildscripts/phing/classes/phing/TaskAdapter.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TaskAdapter.php,v 1.7 2005/10/04 13:52:53 hlellelid Exp $ + *  $Id: 8cd2a3322c659a5de7fcb47e21192730e5cc863d $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,8 +26,8 @@ require_once 'phing/Task.php';   *  similar patterns).   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.7 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @package   phing   */  class TaskAdapter extends Task { @@ -45,7 +45,7 @@ class TaskAdapter extends Task {              try {  // try to set project                  $this->proxy->setProject($this->project);              } catch (Exception $ex) { -                $this->log("Error setting project in " . get_class($this->proxy) . PROJECT_MSG_ERR); +                $this->log("Error setting project in " . get_class($this->proxy) . Project::MSG_ERR);                  throw new BuildException($ex);              }          } else { @@ -56,7 +56,8 @@ class TaskAdapter extends Task {              try { //try to call main                  $this->proxy->main($this->project);              } catch (Exception $ex) { -                $this->log("Error in " . get_class($this->proxy), PROJECT_MSG_ERR); +                $this->log("Error in " . get_class($this->proxy), Project::MSG_ERR); +                $this->log($ex->getTraceAsString(), Project::MSG_DEBUG);                  throw new BuildException($ex->getMessage());              }          } else { diff --git a/buildscripts/phing/classes/phing/TaskContainer.php b/buildscripts/phing/classes/phing/TaskContainer.php index 2e9eb67a..4be2ef41 100644..100755 --- a/buildscripts/phing/classes/phing/TaskContainer.php +++ b/buildscripts/phing/classes/phing/TaskContainer.php @@ -1,6 +1,6 @@  <?php -/* - *  $Id: TaskContainer.php,v 1.5 2005/10/04 19:13:44 hlellelid Exp $ +/** + *  $Id: c31c503eb573b2f454071e9a97fa6a2323c128eb $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -17,6 +17,8 @@   * This software consists of voluntary contributions made by many individuals   * and is licensed under the LGPL. For more information please see   * <http://phing.info>. + * + * @package phing   */  /** @@ -24,8 +26,8 @@   *  Used to check if a class can contain tasks (via instanceof)   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.5 $ $Date: 2005/10/04 19:13:44 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @access    public   *  @package   phing   */ diff --git a/buildscripts/phing/classes/phing/UnknownElement.php b/buildscripts/phing/classes/phing/UnknownElement.php index 745130dc..b04365e7 100644..100755 --- a/buildscripts/phing/classes/phing/UnknownElement.php +++ b/buildscripts/phing/classes/phing/UnknownElement.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: UnknownElement.php,v 1.9 2005/11/08 20:45:59 hlellelid Exp $ + *  $Id: a4e6c2e3f776c5a353e52fb8518b3533f14a97c4 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ require_once 'phing/Task.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.9 $ + * @version   $Id$   * @package   phing   */  class UnknownElement extends Task { @@ -130,15 +130,19 @@ class UnknownElement extends Task {                  $realChild = $this->makeTask($child, $childWrapper, false);                  $parent->addTask($realChild);              } else { -                $realChild = $ih->createElement($this->project, $parent, $child->getTag()); +                $project = $this->project === null ? $parent->project : $this->project; +                $realChild = $ih->createElement($project, $parent, $child->getTag());              }              $childWrapper->setProxy($realChild);              if ($realChild instanceof Task) {                  $realChild->setRuntimeConfigurableWrapper($childWrapper);              } - -            $child->handleChildren($realChild, $childWrapper); +             +            if ($realChild instanceof ProjectComponent) { +                $child->handleChildren($realChild, $childWrapper); +            } +                          if ($realChild instanceof Task) {                  $realChild->maybeConfigure();              } diff --git a/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/Manager.php b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/Manager.php new file mode 100644 index 00000000..6fe71107 --- /dev/null +++ b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/Manager.php @@ -0,0 +1,304 @@ +<?php +/** + * DocBlox + * + * PHP Version 5 + * + * @category  DocBlox + * @package   Parallel + * @author    Mike van Riel <mike.vanriel@naenius.com> + * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) + * @license   http://www.opensource.org/licenses/mit-license.php MIT + * @link      http://docblox-project.org + */ + +/** + * Manager class for Parallel processes. + * + * This class will manage the workers and make sure all processes are executed + * in parallel and not too many at the same time. + * + * @category DocBlox + * @package  Parallel + * @author   Mike van Riel <mike.vanriel@naenius.com> + * @license  http://www.opensource.org/licenses/mit-license.php MIT + * @link     http://docblox-project.org + */ +class DocBlox_Parallel_Manager extends ArrayObject +{ +    /** @var int The maximum number of processes to run simultaneously */ +    protected $process_limit = 2; + +    /** @var boolean Tracks whether this manager is currently executing */ +    protected $is_running = false; + +    /** +     * Tries to autodetect the optimal number of process by counting the number +     * of processors. +     * +     * @param array  $input          Input for the array object. +     * @param int    $flags          flags for the array object. +     * @param string $iterator_class Iterator class for this array object. +     */ +    public function __construct( +        $input = array(), $flags = 0, $iterator_class = "ArrayIterator" +    ) { +        parent::__construct($input, $flags, $iterator_class); + +        if (is_readable('/proc/cpuinfo')) { +            $processors = 0; +            exec("cat /proc/cpuinfo | grep processor | wc -l", $processors); +            $this->setProcessLimit(reset($processors)); +        } +    } + +    /** +     * Adds a worker to to the queue. +     * +     * This method will prepare a worker to be executed in parallel once the +     * execute method is invoked. +     * A fluent interface is provided so that you can chain multiple workers +     * in one call. +     * +     * Example: +     * +     *    $cb1 = function() { var_dump('a'); sleep(1); }; +     *    $cb2 = function() { var_dump('b'); sleep(1); }; +     * +     *    $mgr = new DocBlox_Parallel_Manager(); +     *    $mgr->setProcessLimit(2) +     *        ->addWorker(new DocBlox_Parallel_Worker($cb1)) +     *        ->addWorker(new DocBlox_Parallel_Worker($cb2)) +     *        ->execute(); +     * +     * @param int                     $index  The key for this worker. +     * @param DocBlox_Parallel_Worker $newval The worker to add onto the queue. +     * +     * @see DocBlox_Parallel_Manager::execute() +     * +     * @throws RuntimeException         if this method is invoked while the +     *     manager is busy executing tasks. +     * @throws InvalidArgumentException if the provided element is not of type +     *     DocBlox_Parallel_Worker. +     * +     * @return void +     */ +    public function offsetSet($index, $newval) +    { +        if (!$newval instanceof DocBlox_Parallel_Worker) { +            throw new InvalidArgumentException( +                'Provided element must be of type DocBlox_Parallel_Worker' +            ); +        } +        if ($this->isRunning()) { +            throw new RuntimeException( +                'Workers may not be added during execution of the manager' +            ); +        } + +        parent::offsetSet($index, $newval); +    } + +    /** +     * Convenience method to make the addition of workers explicit and allow a +     * fluent interface. +     * +     * @param DocBlox_Parallel_Worker $worker The worker to add onto the queue. +     * +     * @return self +     */ +    public function addWorker(DocBlox_Parallel_Worker $worker) +    { +        $this[] = $worker; + +        return $this; +    } + +    /** +     * Sets how many processes at most to execute at the same time. +     * +     * A fluent interface is provided so that you can chain multiple workers +     * in one call. +     * +     * @param int $process_limit The limit, minimum of 1 +     * +     * @see DocBlox_Parallel_Manager::addWorker() for an example +     * +     * @return self +     */ +    public function setProcessLimit($process_limit) +    { +        if ($process_limit < 1) { +            throw new InvalidArgumentException( +                'Number of simultaneous processes may not be less than 1' +            ); +        } + +        $this->process_limit = $process_limit; + +        return $this; +    } + +    /** +     * Returns the current limit on the amount of processes that can be +     * executed at the same time. +     * +     * @return int +     */ +    public function getProcessLimit() +    { +        return $this->process_limit; +    } + +    /** +     * Returns whether the manager is executing the workers. +     * +     * @return boolean +     */ +    public function isRunning() +    { +        return $this->is_running; +    } + +    /** +     * Executes each worker. +     * +     * This method loops through the list of workers and tries to fork as +     * many times as the ProcessLimit dictates at the same time. +     * +     * @return void +     */ +    public function execute() +    { +        /** @var int[] $processes */ +        $processes = $this->startExecution(); + +        /** @var DocBlox_Parallel_Worker $worker */ +        foreach ($this as $worker) { + +            // if requirements are not met, execute workers in series. +            if (!$this->checkRequirements()) { +                $worker->execute(); +                continue; +            } + +            $this->forkAndRun($worker, $processes); +        } + +        $this->stopExecution($processes); +    } + +    /** +     * Notifies manager that execution has started, checks requirements and +     * returns array for child processes. +     * +     * If forking is not available because library requirements are not met +     * than the list of workers is processed in series and a E_USER_NOTICE is +     * triggered. +     * +     * @return int[] +     */ +    protected function startExecution() +    { +        $this->is_running = true; + +        // throw a E_USER_NOTICE if the requirements are not met. +        if (!$this->checkRequirements()) { +            trigger_error( +                'The PCNTL extension is not available, running workers in series ' +                . 'instead of parallel', +                E_USER_NOTICE +            ); +        } + +        return array(); +    } + +    /** +     * Waits for all processes to have finished and notifies the manager that +     * execution has stopped. +     * +     * @param int[] &$processes List of running processes. +     * +     * @return void +     */ +    protected function stopExecution(array &$processes) +    { +        // starting of processes has ended but some processes might still be +        // running wait for them to finish +        while (!empty($processes)) { +            pcntl_waitpid(array_shift($processes), $status); +        } + +        /** @var DocBlox_Parallel_Worker $worker */ +        foreach ($this as $worker) { +            $worker->pipe->push(); +        } + +        $this->is_running = false; +    } + +    /** +     * Forks the current process and calls the Worker's execute method OR +     * handles the parent process' execution. +     * +     * This is the really tricky part of the forking mechanism. Here we invoke +     * {@link http://www.php.net/manual/en/function.pcntl-fork.php pcntl_fork} +     * and either execute the forked process or deal with the parent's process +     * based on in which process we are. +     * +     * To fully understand what is going on here it is recommended to read the +     * PHP manual page on +     * {@link http://www.php.net/manual/en/function.pcntl-fork.php pcntl_fork} +     * and associated articles. +     * +     * If there are more workers than may be ran simultaneously then this method +     * will wait until a slot becomes available and then starts the next worker. +     * +     * @param DocBlox_Parallel_Worker $worker     The worker to process. +     * @param int[]                   &$processes The list of running processes. +     * +     * @throws RuntimeException if we are unable to fork. +     * +     * @return void +     */ +    protected function forkAndRun( +        DocBlox_Parallel_Worker $worker, array &$processes +    ) { +        $worker->pipe = new DocBlox_Parallel_WorkerPipe($worker); + +        // fork the process and register the PID +        $pid = pcntl_fork(); + +        switch ($pid) { +        case -1: +            throw new RuntimeException('Unable to establish a fork'); +        case 0: // Child process +            $worker->execute(); + +            $worker->pipe->pull(); + +            // Kill -9 this process to prevent closing of shared file handlers. +            // Not doing this causes, for example, MySQL connections to be cleaned. +            posix_kill(getmypid(), SIGKILL); +        default: // Parent process +            // Keep track if the worker children +            $processes[] = $pid; + +            if (count($processes) >= $this->getProcessLimit()) { +                pcntl_waitpid(array_shift($processes), $status); +            } +            break; +        } +    } + +    /** +     * Returns true when all requirements are met. +     * +     * @return bool +     */ +    protected function checkRequirements() +    { +        return (bool)(extension_loaded('pcntl')); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/README.md b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/README.md new file mode 100644 index 00000000..272d7191 --- /dev/null +++ b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/README.md @@ -0,0 +1,106 @@ +Parallel +======== + +This is a library for introducing Parallelization into your project. +See the `example.php` file for an example how to use this library. + +Theory of Operation +------------------- + +This library will enable the developer to execute a given amount of tasks +(workers) in parallel. This is achieved by adding workers onto a manager, +optionally defining how many processes to run simultaneously and then execute +the manager. + +Under Linux this library will try to detect the number of processors and allow +a maximum number of processes to run equal to the number of processors. If this +cannot be determined or the user is running Windows then a default of 2 is used. + +Requirements and graceful degradation +------------------------------------- + +Parallelization has several requirements. But to allow distribution, without +adding several requirements to your application, will this library execute the +given tasks in serie if the requirements are not met. And throw a E_USER_NOTICE +php error that explains to the user that dependencies are missing. + +The requirements for this library are: + +* A *NIX compatible operating system +* Scripts must not run from an apache module +* the PCNTL PHP extension (http://php.net/manual/en/book.pcntl.php) + +Workers +------- + +Workers are basically wrappers around callback functions or methods. As such you +can use anything in your existing project and parallelize it. + +Do note that each parallel process is a duplicate of the original. This means +that, for example, if you pass an object (or other reference) and change that, +that the changes that you have made do not carry over to the caller. + +The return value of the given callback is stored as result on the worker and +can be read using the `getResult()` method. + +Any exception that is thrown will result in an error, where the `getReturnCode()` +method will return the exception code (be warned: this may be 0!) and the +`getError()` method will return the exception message. + +Errors and exceptions +--------------------- + +if a task throws an exception it is caught and registered as an error. The +exception's code is used as error number, where the message is used as error +message. + +By using this, instead of dying, you can continue execution of the other parallel +processes and handle errors yourself after all processes have been executed. + +Examples +-------- + +### Fluent interface + +    $mgr = new DocBlox_Parallel_Manager(); +    $mgr +      ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'a'; })) +      ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'b'; })) +      ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'c'; })) +      ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'd'; })) +      ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'e'; })) +      ->execute(); + +    /** @var DocBlox_Parallel_Worker $worker */ +    foreach ($mgr as $worker) { +        var_dump($worker->getResult()); +    } + +### Array interface + +    $mgr = new DocBlox_Parallel_Manager(); +    $mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'f'; }); +    $mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'g'; }); +    $mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'h'; }); +    $mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'i'; }); +    $mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'j'; }); +    $mgr->execute(); + +    /** @var DocBlox_Parallel_Worker $worker */ +    foreach ($mgr as $worker) { +        var_dump($worker->getResult()); +    } + +TODO +---- + +* Improve docs +* More intelligent process slots; currently only the oldest in a 'set' of slots +  is waited on but if this runs for a longer time then the other slots than +  those will not be filled as long as the first slot is occupied. +* Last parts of IPC (Inter-Process Communication), to be able to return +  information from Workers to the Manager. + +  * STDOUT +  * STDERR + diff --git a/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/Worker.php b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/Worker.php new file mode 100644 index 00000000..338f4b25 --- /dev/null +++ b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/Worker.php @@ -0,0 +1,203 @@ +<?php +/** + * DocBlox + * + * PHP Version 5 + * + * @category  DocBlox + * @package   Parallel + * @author    Mike van Riel <mike.vanriel@naenius.com> + * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) + * @license   http://www.opensource.org/licenses/mit-license.php MIT + * @link      http://docblox-project.org + */ + +/** + * Class that represents the execution of a single task within a parallelized + * frame. + * + * @category DocBlox + * @package  Parallel + * @author   Mike van Riel <mike.vanriel@naenius.com> + * @license  http://www.opensource.org/licenses/mit-license.php MIT + * @link     http://docblox-project.org + */ +class DocBlox_Parallel_Worker +{ +    /** @var callback the task to execute for this worker */ +    protected $task = null; + +    /** @var mixed[] A list of argument to pass to the task */ +    protected $arguments = array(); + +    /** @var int The return code to tell the parent process how it went */ +    protected $return_code = -1; + +    /** @var mixed The result of the given task */ +    protected $result = ''; + +    /** @var string The error message, if an error occurred */ +    protected $error = ''; + +    /** +     * Creates the worker and sets the task to execute optionally including +     * the arguments that need to be passed to the task. +     * +     * @param callback $task      The task to invoke upon execution. +     * @param mixed[]  $arguments The arguments to provide to the task. +     */ +    function __construct($task, array $arguments = array()) +    { +        $this->setTask($task); +        $this->arguments = $arguments; +    } + +    /** +     * Returns the list of arguments as provided int he constructor. +     * +     * @see DocBlox_Parallel_Worker::__construct() +     * +     * @return mixed[] +     */ +    public function getArguments() +    { +        return $this->arguments; +    } + +    /** +     * Returns the task as provided in the constructor. +     * +     * @see DocBlox_Parallel_Worker::__construct() +     * +     * @return callback +     */ +    public function getTask() +    { +        return $this->task; +    } + +    /** +     * Returns the available return code. +     * +     * This method may return -1 if no return code is available yet. +     * +     * @return int +     */ +    public function getReturnCode() +    { +        return $this->return_code; +    } + +    /** +     * Sets the return code for this worker. +     * +     * Recommended is to use the same codes as are used with +     * {@link http://www.gnu.org/software/bash/manual/html_node/Exit-Status.html +     * exit codes}. +     * +     * In short: 0 means that the task succeeded and a any other positive value +     * indicates an error condition. +     * +     * @param int $return_code Recommended to be a positive number +     * +     * @throw InvalidArgumentException if the code is not a number or negative +     * +     * @return void +     */ +    public function setReturnCode($return_code) +    { +        if (!is_numeric($return_code) || ($return_code  < 0)) { +            throw new InvalidArgumentException( +                'Expected the return code to be a positive number' +            ); +        } + +        $this->return_code = $return_code; +    } + +    /** +     * Returns the error message associated with the return code. +     * +     * @return string +     */ +    public function getError() +    { +        return $this->error; +    } + +    /** +     * Sets the error message. +     * +     * @param string $error The error message. +     * +     * @return void +     */ +    public function setError($error) +    { +        $this->error = $error; +    } + +    /** +     * Returns the result for this task run. +     * +     * @return null|mixed +     */ +    public function getResult() +    { +        return $this->result; +    } + +    /** +     * Sets the result for this task run. +     * +     * @param mixed $result The value that is returned by the task; can be anything. +     * +     * @return void +     */ +    public function setResult($result) +    { +        $this->result = $result; +    } + +    /** +     * Invokes the task with the given arguments and processes the output. +     * +     * @return void. +     */ +    public function execute() +    { +        $this->setReturnCode(0); +        try { +            $this->setResult( +                call_user_func_array($this->getTask(), $this->getArguments()) +            ); +        } catch (Exception $e) { +            $this->setError($e->getMessage()); +            $this->setReturnCode($e->getCode()); +        } +    } + +    /** +     * Sets the task for this worker and validates whether it is callable. +     * +     * @param callback $task The task to execute when the execute method +     *     is invoked. +     * +     * @throws InvalidArgumentException if the given argument is not a callback. +     * +     * @see DocBlox_Parallel_Worker::__construct() +     * @see DocBlox_Parallel_Worker::execute() +     * +     * @return void +     */ +    protected function setTask($task) +    { +        if (!is_callable($task)) { +            throw new InvalidArgumentException( +                'Worker task is not a callable object' +            ); +        } + +        $this->task = $task; +    } +} diff --git a/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/WorkerPipe.php b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/WorkerPipe.php new file mode 100644 index 00000000..3b7eb7fe --- /dev/null +++ b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/WorkerPipe.php @@ -0,0 +1,127 @@ +<?php +/** + * DocBlox + * + * PHP Version 5 + * + * @category  DocBlox + * @package   Parallel + * @author    Mike van Riel <mike.vanriel@naenius.com> + * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) + * @license   http://www.opensource.org/licenses/mit-license.php MIT + * @link      http://docblox-project.org + */ + +/** + * Class that represents a named pipe for a Worker. + * + * This class manages the named pipe for a worker and is able to push and pull + * specific data to facilitate IPC (interprocess communication). + * + * @category DocBlox + * @package  Parallel + * @author   Mike van Riel <mike.vanriel@naenius.com> + * @license  http://www.opensource.org/licenses/mit-license.php MIT + * @link     http://docblox-project.org + */ +class DocBlox_Parallel_WorkerPipe +{ +    /** @var DocBlox_Parallel_Worker worker class that is associated */ +    protected $worker; + +    /** @var string Path to the pipe */ +    protected $path; + +    /** +     * Initializes the named pipe. +     * +     * @param DocBlox_Parallel_Worker $worker Associated worker. +     */ +    public function __construct(DocBlox_Parallel_Worker $worker) +    { +        $this->worker = $worker; + +        $this->path = tempnam(sys_get_temp_dir(), 'dpm_'); +        posix_mkfifo($this->path, 0750); +    } + +    /** +     * If the named pipe was not cleaned up, do so now. +     */ +    public function __destruct() +    { +        if (file_exists($this->path)) { +            $this->release(); +        } +    } + +    /** +     * Pull the worker data into the named pipe. +     * +     * @return void +     */ +    public function pull() +    { +        $this->writePipeContents(); +    } + +    /** +     * Push the worker data back onto the worker and release the pipe. +     * +     * @return void +     */ +    public function push() +    { +        list($result, $error, $return_code) = $this->readPipeContents(); +        $this->release(); + +        $this->worker->setResult($result); +        $this->worker->setError($error); +        $this->worker->setReturnCode($return_code); +    } + +    /** +     * Convenience method to show relation to readPipeContents. +     * +     * @return void +     */ +    protected function writePipeContents() +    { +        // push the gathered data onto a name pipe +        $pipe = fopen($this->path, 'w'); +        fwrite( +            $pipe, serialize( +                array( +                    $this->worker->getResult(), +                    $this->worker->getError(), +                    $this->worker->getReturnCode() +                ) +            ) +        ); +        fclose($pipe); +    } + +    /** +     * Returns the unserialized contents of the pipe. +     * +     * @return array +     */ +    protected function readPipeContents() +    { +        $pipe = fopen($this->path, 'r+'); +        $result = unserialize(fread($pipe, filesize($this->path))); +        fclose($pipe); + +        return $result; +    } + +    /** +     * Releases the pipe. +     * +     * @return void +     */ +    protected function release() +    { +        unlink($this->path); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/example.php b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/example.php new file mode 100644 index 00000000..3bdcd408 --- /dev/null +++ b/buildscripts/phing/classes/phing/contrib/DocBlox/Parallel/example.php @@ -0,0 +1,57 @@ +<?php +/** + * DocBlox + * + * PHP Version 5 + * + * @category  DocBlox + * @package   Parallel + * @author    Mike van Riel <mike.vanriel@naenius.com> + * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) + * @license   http://www.opensource.org/licenses/mit-license.php MIT + * @link      http://docblox-project.org + */ + +/** Include the manager as we do not autoload */ +require_once 'Manager.php'; + +/** Include the worker as we do not autoload */ +require_once 'Worker.php'; + +/** Include the worker's pipe as we do not autoload */ +require_once 'WorkerPipe.php'; + +// ----------------------------------------------------------------------------- +// method 1: using a fluent interface and the addWorker helper. +// ----------------------------------------------------------------------------- + +$mgr = new DocBlox_Parallel_Manager(); +$mgr +  ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'a'; })) +  ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'b'; })) +  ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'c'; })) +  ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'd'; })) +  ->addWorker(new DocBlox_Parallel_Worker(function() { sleep(1); return 'e'; })) +  ->execute(); + +/** @var DocBlox_Parallel_Worker $worker */ +foreach ($mgr as $worker) { +    var_dump($worker->getResult()); +} + +// ----------------------------------------------------------------------------- +// method 2: using the manager as worker array +// ----------------------------------------------------------------------------- + +$mgr = new DocBlox_Parallel_Manager(); +$mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'f'; }); +$mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'g'; }); +$mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'h'; }); +$mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'i'; }); +$mgr[] = new DocBlox_Parallel_Worker(function() { sleep(1); return 'j'; }); +$mgr->execute(); + +/** @var DocBlox_Parallel_Worker $worker */ +foreach ($mgr as $worker) { +    var_dump($worker->getResult()); +} diff --git a/buildscripts/phing/classes/phing/filters/BaseFilterReader.php b/buildscripts/phing/classes/phing/filters/BaseFilterReader.php index c9f8c619..4489b16e 100644..100755 --- a/buildscripts/phing/classes/phing/filters/BaseFilterReader.php +++ b/buildscripts/phing/classes/phing/filters/BaseFilterReader.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: BaseFilterReader.php,v 1.8 2004/05/20 02:24:10 hlellelid Exp $ + *  $Id: a1da135c09abf5cf07a53b3a327baf3497cfb697 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@ include_once 'phing/system/io/StringReader.php';   * Base class for core filter readers.   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> - * @version   $Revision: 1.8 $ $Date: 2004/05/20 02:24:10 $ + * @version   $Id$   * @access    public   * @see       FilterReader   * @package   phing.filters @@ -147,11 +147,11 @@ class BaseFilterReader extends FilterReader {       * @param string $msg Message to log.       * @param int $level Priority level.       */ -    function log($msg, $level = PROJECT_MSG_INFO) { +    function log($msg, $level = Project::MSG_INFO) {          if ($this->project !== null) {              $this->project->log("[filter:".get_class($this)."] ".$msg, $level);              }      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php b/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php index 3d767b40..8d3b0810 100644..100755 --- a/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php +++ b/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: BaseParamFilterReader.php,v 1.5 2005/02/27 20:52:08 mrook Exp $ + *  $Id: 412cc012db35b1dcf3545b93d5053e727d66b61f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,8 +28,8 @@ include_once 'phing/types/Parameter.php';   * Base class for core filter readers.   *   * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> - * @copyright © 2003 seasonfive. All rights reserved - * @version   $Revision: 1.5 $ $Date: 2005/02/27 20:52:08 $ + * @copyright � 2003 seasonfive. All rights reserved + * @version   $Id$   * @access    public   * @see       FilterReader   * @package   phing.filters @@ -66,4 +66,4 @@ class BaseParamFilterReader extends BaseFilterReader implements Parameterizable      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/ChainableReader.php b/buildscripts/phing/classes/phing/filters/ChainableReader.php index c7de07c4..2b773dbe 100644 --- a/buildscripts/phing/classes/phing/filters/ChainableReader.php +++ b/buildscripts/phing/classes/phing/filters/ChainableReader.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: ChainableReader.php,v 1.2 2003/11/19 05:48:27 hlellelid Exp $ + *  $Id: fb9ebbb44f13ecc3693265e1b793ab17cea543a1 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,6 +24,7 @@   * Interface indicating that a reader may be chained to another one.   *   * @author Magesh Umasankar + * @package phing.filters   */  interface ChainableReader { @@ -39,4 +40,4 @@ interface ChainableReader {      public function chain(Reader $rdr);  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/ExpandProperties.php b/buildscripts/phing/classes/phing/filters/ExpandProperties.php index dfd98cc8..2517783f 100644..100755 --- a/buildscripts/phing/classes/phing/filters/ExpandProperties.php +++ b/buildscripts/phing/classes/phing/filters/ExpandProperties.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: ExpandProperties.php,v 1.6 2004/07/14 17:14:15 hlellelid Exp $ + *  $Id: d6bb7717db7cf2b122cbdcb93e5bb0f45d97ec52 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -33,13 +33,30 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    Yannick Lecaillez <yl@seasonfive.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.6 $ + * @version   $Id: d6bb7717db7cf2b122cbdcb93e5bb0f45d97ec52 $   * @see       BaseFilterReader   * @package   phing.filters   */  class ExpandProperties extends BaseFilterReader implements ChainableReader { +    protected $logLevel = Project::MSG_VERBOSE;      /** +     * Set level of log messages generated (default = info) +     * @param string $level +     */ +    public function setLevel($level) +    { +        switch ($level) +        { +            case "error": $this->logLevel = Project::MSG_ERR; break; +            case "warning": $this->logLevel = Project::MSG_WARN; break; +            case "info": $this->logLevel = Project::MSG_INFO; break; +            case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; +            case "debug": $this->logLevel = Project::MSG_DEBUG; break; +        } +    } +     +    /**       * Returns the filtered stream.        * The original stream is first read in fully, and the Phing properties are expanded.       *  @@ -57,7 +74,7 @@ class ExpandProperties extends BaseFilterReader implements ChainableReader {          }          $project = $this->getProject(); -        $buffer = ProjectConfigurator::replaceProperties($project, $buffer, $project->getProperties()); +        $buffer = ProjectConfigurator::replaceProperties($project, $buffer, $project->getProperties(), $this->logLevel);          return $buffer;      } @@ -79,4 +96,4 @@ class ExpandProperties extends BaseFilterReader implements ChainableReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/HeadFilter.php b/buildscripts/phing/classes/phing/filters/HeadFilter.php index 84673b4a..3cbcb51b 100644..100755 --- a/buildscripts/phing/classes/phing/filters/HeadFilter.php +++ b/buildscripts/phing/classes/phing/filters/HeadFilter.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: HeadFilter.php,v 1.6 2004/03/15 14:45:06 hlellelid Exp $   + *  $Id: e3e9c0a171b4416545e57fe42b45b4eec14914ce $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -36,7 +36,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @version   $Revision: 1.6 $ $Date: 2004/03/15 14:45:06 $ + * @version   $Id$   * @access    public   * @see       FilterReader   * @package   phing.filters @@ -158,4 +158,4 @@ class HeadFilter extends BaseParamFilterReader implements ChainableReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/IconvFilter.php b/buildscripts/phing/classes/phing/filters/IconvFilter.php new file mode 100755 index 00000000..c9883b17 --- /dev/null +++ b/buildscripts/phing/classes/phing/filters/IconvFilter.php @@ -0,0 +1,155 @@ +<?php + +/* + *  $Id: 9c0d703f08f0160b6a699d328a6025587877e104 $ + * + * 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>. +*/ + +include_once 'phing/filters/BaseParamFilterReader.php'; +include_once 'phing/filters/ChainableReader.php'; + +/** + * Encode data from <code>in</code> encoding to <code>out</code> encoding. + * + * Example: + * <pre> + * <iconvfilter inputencoding="UTF-8" outputencoding="CP1251" /> + * </pre> + * Or: + * <pre> + * <filterreader classname="phing.filters.IconvFilter"> + *    <param name="inputencoding" value="UTF-8" /> + *    <param name="outputencoding" value="CP1251" /> + * </filterreader> + * </pre> + * + * @author    Alexey Shockov, <alexey@shockov.com> + * @version   $Id$ + * @package   phing.filters + */ +class IconvFilter +    extends BaseParamFilterReader +    implements ChainableReader { + +    private $_inputEncoding; + +    private $_outputEncoding; + +    /** +     * Returns first n lines of stream. +     * @return the resulting stream, or -1 +     * if the end of the resulting stream has been reached +     * +     * @exception IOException if the underlying stream throws an IOException +     * during reading +     */ +    function read($len = null) { +        $this->_initialize(); + +        // Process whole text at once. +        $text = null; +        while (($data = $this->in->read($len)) !== -1) { +            $text .= $data; +        } + +        // At the end. +        if (null === $text) { +            return -1; +        } + +        $this->log( +            "Encoding " . $this->in->getResource() . " from " . $this->getInputEncoding() . " to " . $this->getOutputEncoding(), +            Project::MSG_VERBOSE +        ); + +        return iconv($this->_inputEncoding, $this->_outputEncoding, $text); +    } + +    /** +     * +     * @param string $encoding Input encoding. +     */ +    public function setInputEncoding($encoding) { +        $this->_inputEncoding = $encoding; +    } + +    /** +     * +     * @return string +     */ +    public function getInputEncoding() { +        return $this->_inputEncoding; +    } + +    /** +     * +     * @param string $encoding Output encoding. +     */ +    public function setOutputEncoding($encoding) { +        $this->_outputEncoding = $encoding; +    } + +    /** +     * +     * @return string +     */ +    public function getOutputEncoding() { +        return $this->_outputEncoding; +    } + +    /** +     * Creates a new IconvFilter using the passed in Reader for instantiation. +     * +     * @param object A Reader object providing the underlying stream. Must not be <code>null</code>. +     * +     * @return object A new filter based on this configuration, but filtering the specified reader. +     */ +    function chain(Reader $reader) { +        $filter = new self($reader); + +        $filter->setInputEncoding($this->getInputEncoding()); +        $filter->setOutputEncoding($this->getOutputEncoding()); + +        $filter->setInitialized(true); +        $filter->setProject($this->getProject()); + +        return $filter; +    } + +    /** +     * Configuring object from the parameters list. +     */ +    private function _initialize() { +        if ($this->getInitialized()) { +            return; +        } + +        $params = $this->getParameters(); +        if ($params !== null) { +            foreach ($params as $param) { +                if ('in' == $param->getName()) { +                    $this->setInputEncoding($param->getValue()); +                } else if ('out' == $param->getName()) { +                    $this->setOutputEncoding($param->getValue()); +                } +            } +        } + +        $this->setInitialized(true); +    } +} diff --git a/buildscripts/phing/classes/phing/filters/LineContains.php b/buildscripts/phing/classes/phing/filters/LineContains.php index 8f3136b7..b84b62c1 100644..100755 --- a/buildscripts/phing/classes/phing/filters/LineContains.php +++ b/buildscripts/phing/classes/phing/filters/LineContains.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: LineContains.php,v 1.11 2005/02/27 20:52:08 mrook Exp $ + *  $Id: 2e783b14ff093df7de21477479a123403d630984 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -47,7 +47,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    Yannick Lecaillez <yl@seasonfive.com>   * @author    Hans Lellelid <hans@velum.net> - * @version   $Revision: 1.11 $ + * @version   $Id$   * @see       PhingFilterReader   * @package   phing.filters  */ @@ -153,7 +153,7 @@ class LineContains extends BaseParamFilterReader implements ChainableReader {      }      /** -     * Adds a <code><contains></code> nested element. +     * Adds a <code>contains</code> nested element.       *       * @return Contains The <code>contains</code> element added.       *                  Must not be <code>null</code>. @@ -169,7 +169,7 @@ class LineContains extends BaseParamFilterReader implements ChainableReader {       *       * @param array $contains An array of words which must be contained       *                 within a line in order for it to match in this filter. -     *                 Must not be <code>null<code>. +     *                 Must not be <code>null</code>.       */      function setContains($contains) {          // type check, error must never occur, bad code of it does @@ -231,6 +231,8 @@ class LineContains extends BaseParamFilterReader implements ChainableReader {  /**   * Holds a contains element. + * + * @package phing.filters   */  class Contains { @@ -255,4 +257,4 @@ class Contains {          return $this->_value;      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php b/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php index dcbb532c..c603978f 100644..100755 --- a/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php +++ b/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: LineContainsRegexp.php,v 1.8 2005/02/27 20:52:08 mrook Exp $ + *  $Id: 0a881c0b67c96c20345980fd033f006379949dda $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -42,7 +42,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    Yannick Lecaillez <yl@seasonfive.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.8 $ + * @version   $Id$   * @see       FilterReader   * @package   phing.filters   */ @@ -176,4 +176,4 @@ class LineContainsRegexp extends BaseParamFilterReader implements ChainableReade      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/PrefixLines.php b/buildscripts/phing/classes/phing/filters/PrefixLines.php index a5580f87..9edcc02a 100644..100755 --- a/buildscripts/phing/classes/phing/filters/PrefixLines.php +++ b/buildscripts/phing/classes/phing/filters/PrefixLines.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: PrefixLines.php,v 1.6 2004/03/15 14:45:06 hlellelid Exp $ + *  $Id: 744d8766d5aba397c0a8efd61afb8e60bd77b0c3 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -37,7 +37,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @version   $Revision: 1.6 $ $Date: 2004/03/15 14:45:06 $ + * @version   $Id$   * @access    public   * @see       FilterReader   * @package   phing.filters @@ -139,4 +139,4 @@ class PrefixLines extends BaseParamFilterReader implements ChainableReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php b/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php index 3c5592e8..70e8940f 100644..100755 --- a/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php +++ b/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: ReplaceRegexp.php,v 1.5 2003/12/24 12:38:39 hlellelid Exp $ + *  $Id: 3ea7f569d0f0b1c4d0f057c9f7f8969cb829f2cb $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -36,7 +36,7 @@ include_once 'phing/types/RegularExpression.php';   * </pre>   *   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.5 $ + * @version   $Id$   * @package   phing.filters   */  class ReplaceRegexp extends BaseFilterReader implements ChainableReader { @@ -97,10 +97,10 @@ class ReplaceRegexp extends BaseFilterReader implements ChainableReader {              $regexp = $exptype->getRegexp($this->project);              try {                  $buffer = $regexp->replace($buffer); -                $this->log("Performing regexp replace: /".$regexp->getPattern()."/".$regexp->getReplace()."/g".($regexp->getIgnoreCase() ? 'i' : ''), PROJECT_MSG_VERBOSE); +                $this->log("Performing regexp replace: /".$regexp->getPattern()."/".$regexp->getReplace()."/g".$regexp->getModifiers(), Project::MSG_VERBOSE);              } catch (Exception $e) {                  // perhaps mismatch in params (e.g. no replace or pattern specified) -                $this->log("Error performing regexp replace: " . $e->getMessage(), PROJECT_MSG_WARN); +                $this->log("Error performing regexp replace: " . $e->getMessage(), Project::MSG_WARN);              }          } @@ -126,4 +126,4 @@ class ReplaceRegexp extends BaseFilterReader implements ChainableReader {  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/ReplaceTokens.php b/buildscripts/phing/classes/phing/filters/ReplaceTokens.php index 999f734f..a5cd7521 100644..100755 --- a/buildscripts/phing/classes/phing/filters/ReplaceTokens.php +++ b/buildscripts/phing/classes/phing/filters/ReplaceTokens.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: ReplaceTokens.php,v 1.14 2005/06/16 15:09:10 hlellelid Exp $   + *  $Id: 6c5d97f2254de3c08ac34baaabf6119c54a49a7d $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,7 +24,7 @@ include_once 'phing/filters/BaseParamFilterReader.php';  include_once 'phing/types/TokenSource.php';  include_once 'phing/filters/ChainableReader.php'; -/* +/**   * Replaces tokens in the original input with user-supplied values.   *   * Example: @@ -43,7 +43,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @version   $Revision: 1.14 $ $Date: 2005/06/16 15:09:10 $ + * @version   $Id: 6c5d97f2254de3c08ac34baaabf6119c54a49a7d $   * @access    public   * @see       BaseParamFilterReader   * @package   phing.filters @@ -142,7 +142,7 @@ class ReplaceTokens extends BaseParamFilterReader implements ChainableReader {              $replaceWith = $this->_beginToken . $key . $this->_endToken;                          $this->log("No token defined for key \"".$this->_beginToken  . $key . $this->_endToken."\"");          } else { -            $this->log("Replaced \"".$this->_beginToken  . $key . $this->_endToken ."\" with \"".$replaceWith."\""); +            $this->log("Replaced \"".$this->_beginToken  . $key . $this->_endToken ."\" with \"".$replaceWith."\"", Project::MSG_VERBOSE);          }          return $replaceWith; @@ -169,7 +169,7 @@ class ReplaceTokens extends BaseParamFilterReader implements ChainableReader {          // filter buffer          $buffer = preg_replace_callback( -            "/".preg_quote($this->_beginToken)."([\w\.\-:]+?)".preg_quote($this->_endToken)."/", +            "/".preg_quote($this->_beginToken, '/')."([\w\.\-:]+?)".preg_quote($this->_endToken, '/')."/",              array($this, 'replaceTokenCallback'), $buffer);          return $buffer; @@ -360,6 +360,8 @@ class ReplaceTokens extends BaseParamFilterReader implements ChainableReader {  /**   * Holds a token. + * + * @package   phing.filters   */  class Token { @@ -390,7 +392,16 @@ class Token {       * @param string $value The value for this token. Must not be <code>null</code>.       */      function setValue($value) { -        $this->_value = (string) $value; +        // special case for boolean values +        if (is_bool($value)) { +            if ($value) { +                $this->_value = "true"; +            } else { +                $this->_value = "false"; +            } +        } else {         +            $this->_value = (string) $value; +        }      }      /** @@ -410,6 +421,15 @@ class Token {      function getValue() {          return $this->_value;      } + +    /** +     * Sets the token value from text. +     * +     * @param string $value The value for this token. Must not be <code>null</code>. +     */ +    function addText($value) { +        $this->setValue($value); +    }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/ReplaceTokensWithFile.php b/buildscripts/phing/classes/phing/filters/ReplaceTokensWithFile.php new file mode 100644 index 00000000..580b8d84 --- /dev/null +++ b/buildscripts/phing/classes/phing/filters/ReplaceTokensWithFile.php @@ -0,0 +1,361 @@ +<?php + +/* + *  $Id: 164a2d9eeba3673653086b32e9fa2045168c992c $ + * + * 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>. +*/ + +include_once 'phing/filters/BaseParamFilterReader.php'; +include_once 'phing/filters/ChainableReader.php'; + +/** + * Replaces tokens in the original input with the contents of a file. + * The file to be used is controlled by the name of the token which + * corresponds to the basename of the file to be used together with + * the optional pre and postfix strings that is possible to set. + * + * By default all HTML entities in the file is replaced by the + * corresponding HTML entities. This behaviour can be controlled by + * the "translatehtml" parameter. + * + * Supported parameters are: + *  <pre> + *  prefix         string Text to be prefixed to token before using as filename + *  postfix        string Text to be prefixed to token before using as filename + *  dir            string The directory where the files should be read from + *  translatehtml  bool   If we should translate all HTML entities in the file. + * </pre> + * Example: + * + * <pre><filterreader classname="phing.filters.ReplaceTokensWithFile"> + *   <param name="dir" value="examples/" /> + *   <param name="postfix" value=".php" /> + * </filterreader></pre> + * + * @author    johan persson, johanp@aditus.nu + * @version   $Id: 164a2d9eeba3673653086b32e9fa2045168c992c $ + * @access    public + * @see       ReplaceTokensWithFile + * @package   phing.filters + */ +class ReplaceTokensWithFile extends BaseParamFilterReader implements ChainableReader { + +    /** +     * Default "begin token" character. +     * @var string +     */ +    const DEFAULT_BEGIN_TOKEN = "#@#"; + +    /** +     * Default "end token" character. +     * @var string +     */ +    const DEFAULT_END_TOKEN = "#@#"; + +    /** +     * Array to hold the token sources that make tokens from +     * different sources available +     * @var array +     */ +    private $_tokensources = array(); + +    /** +     * Character marking the beginning of a token. +     * @var string +     */ +    private    $_beginToken =  ReplaceTokensWithFile::DEFAULT_BEGIN_TOKEN; + +    /** +     * Character marking the end of a token. +     * @var string +     */ +    private    $_endToken = ReplaceTokensWithFile::DEFAULT_END_TOKEN; + +    /** +     * File prefix to be inserted in front of the token to create the +     * file name to be used. +     * @var string +     */ +    private    $_prefix = ''; + +    /** +     * File postfix to be inserted in front of the token to create the +     * file name to be used. +     * @var string +     */ +    private    $_postfix = ''; + +    /** +     * Directory where to look for the files. The default is to look in the +     * current file. +     * +     * @var string +     */ +    private    $_dir = './'; + +    /** +     * Translate all HTML entities in the file to the corresponding HTML +     * entities before it is used as replacements. For example all '<' +     * will be translated to < before the content is inserted. +     * +     * @var boolean +     */ +    private    $_translatehtml = true; + + +    /** +     * Sets the drectory where to look for the files to use for token replacement +     * +     * @param string $dir +     */ +    function setTranslateHTML($translate) { +        $this->_translatehtml = (bool) $translate; +    } + +    /** +     * Returns the drectory where to look for the files to use for token replacement +     */ +    function getTranslateHTML() { +        return $this->_translatehtml; +    } +     +    /** +     * Sets the drectory where to look for the files to use for token replacement +     * +     * @param string $dir +     */ +    function setDir($dir) { +        $this->_dir = (string) $dir; +    } + +    /** +     * Returns the drectory where to look for the files to use for token replacement +     */ +    function getDir() { +        return $this->_dir; +    } +         +    /** +     * Sets the prefix that is prepended to the token in order to create the file +     * name. For example if the token is 01 and the prefix is "example" then +     * the filename to look for will be "example01" +     * +     * @param string $prefix +     */ +    function setPrefix($prefix) { +        $this->_prefix = (string) $prefix; +    } + +    /* +     * Returns the prefix that is prepended to the token in order to create the file +     * name. For example if the token is 01 and the prefix is "example" then +     * the filename to look for will be "example01" +     */ +    function getPrefix() { +        return $this->_prefix; +    } +     +    /** +     * Sets the postfix that is added to the token in order to create the file +     * name. For example if the token is 01 and the postfix is ".php" then +     * the filename to look for will be "01.php" +     * +     * @param string $postfix +     */ +    function setPostfix($postfix) { +        $this->_postfix = (string) $postfix; +    } + +    /** +     * Returns the postfix that is added to the token in order to create the file +     * name. For example if the token is 01 and the postfix is ".php" then +     * the filename to look for will be "01.php" +     */ +    function getPostfix() { +        return $this->_postfix; +    } +     +    /** +     * Sets the "begin token" character. +     * +     * @param string $beginToken the character used to denote the beginning of a token. +     */ +    function setBeginToken($beginToken) { +        $this->_beginToken = (string) $beginToken; +    } + +    /** +     * Returns the "begin token" character. +     * +     * @return string The character used to denote the beginning of a token. +     */ +    function getBeginToken() { +        return $this->_beginToken; +    } + +    /** +     * Sets the "end token" character. +     * +     * @param string $endToken the character used to denote the end of a token +     */ +    function setEndToken($endToken) { +        $this->_endToken = (string) $endToken; +    } + +    /** +     * Returns the "end token" character. +     * +     * @return the character used to denote the beginning of a token +     */ +    function getEndToken() { +        return $this->_endToken; +    } + +    /** +     * Replace the token found with the appropriate file contents +     * @param array $matches Array of 1 el containing key to search for. +     * @return string     Text with which to replace key or value of key if none is found. +     * @access private +     */ +    private function replaceTokenCallback($matches) { + +        $filetoken = $matches[1]; + +        // We look in all specified directories for the named file and use +        // the first directory which has the file. +        $dirs = explode(';',$this->_dir); + +        $ndirs = count($dirs); +        $n = 0; +        $file = $dirs[$n] . $this->_prefix . $filetoken . $this->_postfix; + +        while ( $n < $ndirs && ! is_readable($file) ) { +            ++$n; +        } + +        if( ! is_readable($file) || $n >= $ndirs ) { +            $this->log("Can not read or find file \"$file\". Searched in directories: {$this->_dir}", Project::MSG_WARN); +            //return $this->_beginToken  . $filetoken . $this->_endToken; +            return "[Phing::Filters::ReplaceTokensWithFile: Can not find file "  . '"' . $filetoken . $this->_postfix . '"' . "]"; +        } + +        $buffer = file_get_contents($file); +        if( $this->_translatehtml ) { +            $buffer = htmlentities($buffer); +        } + +        if ($buffer === null) { +            $buffer = $this->_beginToken . $filetoken . $this->_endToken; +            $this->log("No corresponding file found for key \"$buffer\"", Project::MSG_WARN); +        } else { +            $this->log("Replaced \"".$this->_beginToken . $filetoken . $this->_endToken."\" with content from file \"$file\""); +        } + +        return $buffer; +    } + +    /** +     * Returns stream with tokens having been replaced with appropriate values. +     * If a replacement value is not found for a token, the token is left in the stream. +     * +     * @return mixed filtered stream, -1 on EOF. +     */ +    function read($len = null) { +        if ( !$this->getInitialized() ) { +            $this->_initialize(); +            $this->setInitialized(true); +        } + +        // read from next filter up the chain +        $buffer = $this->in->read($len); + +        if($buffer === -1) { +            return -1; +        } + +        // filter buffer +        $buffer = preg_replace_callback( +            "/".preg_quote($this->_beginToken)."([\w\.\-:\/]+?)".preg_quote($this->_endToken)."/", +            array($this, 'replaceTokenCallback'), $buffer); + +        return $buffer; +    } + +    /** +     * Creates a new ReplaceTokensWithFile using the passed in +     * Reader for instantiation. +     * +     * @param object A Reader object providing the underlying stream. +     *               Must not be <code>null</code>. +     * +     * @return object A new filter based on this configuration, but filtering +     *         the specified reader +     */ +    function chain(Reader $reader) { +        $newFilter = new ReplaceTokensWithFile($reader); +        $newFilter->setProject($this->getProject()); +        $newFilter->setTranslateHTML($this->getTranslateHTML()); +        $newFilter->setDir($this->getDir()); +        $newFilter->setPrefix($this->getPrefix()); +        $newFilter->setPostfix($this->getPostfix()); +        $newFilter->setBeginToken($this->getBeginToken()); +        $newFilter->setEndToken($this->getEndToken()); +        $newFilter->setInitialized(true); +        return $newFilter; +    } + +    /** +     * Initializes parameters +     * This method is only called when this filter is used through +     * a <filterreader> tag in build file. +     */ +    private function _initialize() { +        $params = $this->getParameters(); +        $n = count($params); + +        if ( $params !== null ) { +            for($i = 0 ; $i < $n ; $i++) { +                if ( $params[$i] !== null ) { +                    $name = $params[$i]->getName(); +                    switch( $name ) { +                    case 'begintoken' : +                        $this->_beginToken = $params[$i]->getValue(); +                        break; +                    case 'endtoken' : +                        $this->_endToken = $params[$i]->getValue(); +                        break; +                    case 'dir': +                        $this->_dir = $params[$i]->getValue(); +                        break; +                    case 'prefix': +                        $this->_prefix = $params[$i]->getValue(); +                        break; +                    case 'postfix': +                        $this->_postfix = $params[$i]->getValue(); +                        break; +                    case 'translatehtml': +                        $this->_translatehtml = $params[$i]->getValue(); +                        break; +                    } +                } +            } +        } +    } +} + + diff --git a/buildscripts/phing/classes/phing/filters/StripLineBreaks.php b/buildscripts/phing/classes/phing/filters/StripLineBreaks.php index c5a06129..08d1aa6b 100644..100755 --- a/buildscripts/phing/classes/phing/filters/StripLineBreaks.php +++ b/buildscripts/phing/classes/phing/filters/StripLineBreaks.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: StripLineBreaks.php,v 1.8 2004/03/15 14:45:06 hlellelid Exp $   + *  $Id: 84767114c6fcf8abe5fcc0dce48513faf18d6306 $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -36,7 +36,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @version   $Revision: 1.8 $ $Date: 2004/03/15 14:45:06 $ + * @version   $Id$   * @access    public   * @see       BaseParamFilterReader   * @package   phing.filters @@ -145,4 +145,4 @@ class StripLineBreaks extends BaseParamFilterReader implements ChainableReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/StripLineComments.php b/buildscripts/phing/classes/phing/filters/StripLineComments.php index 5d97979a..2a19ca25 100644..100755 --- a/buildscripts/phing/classes/phing/filters/StripLineComments.php +++ b/buildscripts/phing/classes/phing/filters/StripLineComments.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: StripLineComments.php,v 1.8 2005/02/27 20:52:08 mrook Exp $   + *  $Id: b0b2b1dc67fff8bd5285e43e9d11b15f4ef44ae7 $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,7 +23,7 @@  include_once 'phing/filters/BaseParamFilterReader.php';  include_once 'phing/filters/ChainableReader.php'; -/* +/**   * This filter strips line comments.   *   * Example: @@ -48,7 +48,7 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @version   $Revision: 1.8 $ $Date: 2005/02/27 20:52:08 $ + * @version   $Id$   * @access    public   * @see       BaseParamFilterReader   * @package   phing.filters @@ -175,9 +175,11 @@ class StripLineComments extends BaseParamFilterReader implements ChainableReader      }  } -/* +/**   * The class that holds a comment representation. -*/ + * + * @package phing.filters + */  class Comment {      /** The prefix for a line comment. */ @@ -202,4 +204,4 @@ class Comment {          return $this->_value;      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/StripPhpComments.php b/buildscripts/phing/classes/phing/filters/StripPhpComments.php index 9e21eed3..0abb8a67 100644..100755 --- a/buildscripts/phing/classes/phing/filters/StripPhpComments.php +++ b/buildscripts/phing/classes/phing/filters/StripPhpComments.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: StripPhpComments.php,v 1.6 2004/07/16 01:36:35 hlellelid Exp $ + *  $Id: 6c68ae0ad1aa7f2f7825087c1c54233bd2462124 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -32,11 +32,10 @@ include_once 'phing/filters/ChainableReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @version   $Revision: 1.6 $ $Date: 2004/07/16 01:36:35 $ + * @version   $Id$   * @access    public   * @see       FilterReader   * @package   phing.filters - * @todo -c use new PHP functions to perform this instead of regex.   */  class StripPhpComments extends BaseFilterReader implements ChainableReader {      /** @@ -171,7 +170,7 @@ class StripPhpComments extends BaseFilterReader implements ChainableReader {      }      /** -     * Creates a new StripJavaComments using the passed in +     * Creates a new StripPhpComments using the passed in       * Reader for instantiation.       *        * @param reader A Reader object providing the underlying stream. @@ -187,4 +186,3 @@ class StripPhpComments extends BaseFilterReader implements ChainableReader {      }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/filters/StripWhitespace.php b/buildscripts/phing/classes/phing/filters/StripWhitespace.php new file mode 100755 index 00000000..d7b6113f --- /dev/null +++ b/buildscripts/phing/classes/phing/filters/StripWhitespace.php @@ -0,0 +1,95 @@ +<?php + +/* + *  $Id $ + * + * 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>. +*/ + +include_once 'phing/filters/BaseFilterReader.php'; +include_once 'phing/filters/ChainableReader.php'; + +/** + * Strips whitespace from [php] files using PHP stripwhitespace() method. + *  + * @author    Hans Lellelid, hans@velum.net + * @version   $Id$ + * @see       FilterReader + * @package   phing.filters + * @todo -c use new PHP functions to perform this instead of regex. + */ +class StripWhitespace extends BaseFilterReader implements ChainableReader { +     +    private $processed = false; +     +    /** +     * Returns the  stream without Php comments and whitespace. +     *  +     * @return the resulting stream, or -1 +     *         if the end of the resulting stream has been reached +     *  +     * @throws IOException if the underlying stream throws an IOException +     *                        during reading      +     */ +    function read($len = null) { +     +        if ($this->processed === true) { +            return -1; // EOF +        } +         +        // Read XML +        $php = null; +        while ( ($buffer = $this->in->read($len)) !== -1 ) { +            $php .= $buffer; +        } +         +        if ($php === null ) { // EOF? +            return -1; +        } +         +        if(empty($php)) { +            $this->log("PHP file is empty!", Project::MSG_WARN); +            return ''; // return empty string, don't attempt to strip whitespace +        } +                 +        // write buffer to a temporary file, since php_strip_whitespace() needs a filename +        $file = new PhingFile(tempnam(PhingFile::getTempDir(), 'stripwhitespace')); +        file_put_contents($file->getAbsolutePath(), $php); +        $output = php_strip_whitespace($file->getAbsolutePath()); +        unlink($file->getAbsolutePath()); +         +        $this->processed = true; +         +        return $output; +    } + +    /** +     * Creates a new StripWhitespace using the passed in +     * Reader for instantiation. +     *  +     * @param reader A Reader object providing the underlying stream. +     *               Must not be <code>null</code>. +     *  +     * @return a new filter based on this configuration, but filtering +     *         the specified reader +     */ +    public function chain(Reader $reader) { +        $newFilter = new StripWhitespace($reader); +        $newFilter->setProject($this->getProject());         +        return $newFilter; +    } +} diff --git a/buildscripts/phing/classes/phing/filters/TabToSpaces.php b/buildscripts/phing/classes/phing/filters/TabToSpaces.php index 7293d3b5..80d3c215 100644..100755 --- a/buildscripts/phing/classes/phing/filters/TabToSpaces.php +++ b/buildscripts/phing/classes/phing/filters/TabToSpaces.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: TabToSpaces.php,v 1.9 2004/03/15 14:45:06 hlellelid Exp $   + *  $Id: 71dc074faa0ed97b47c49fec5449233ea485120c $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -38,7 +38,7 @@ require_once 'phing/filters/ChainableReader.php';   *   * @author    Yannick Lecaillez <yl@seasonfive.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.9 $ + * @version   $Id$   * @see       BaseParamFilterReader   * @package   phing.filters   */ @@ -141,4 +141,4 @@ class TabToSpaces extends BaseParamFilterReader implements ChainableReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/TailFilter.php b/buildscripts/phing/classes/phing/filters/TailFilter.php index a6af6e4b..95a9c6f5 100644..100755 --- a/buildscripts/phing/classes/phing/filters/TailFilter.php +++ b/buildscripts/phing/classes/phing/filters/TailFilter.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: TailFilter.php,v 1.7 2004/03/15 14:45:06 hlellelid Exp $   + *  $Id: 3c108d45a4b3be6f6b9a395477e7641d8e17c44b $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -37,8 +37,8 @@ require_once 'phing/filters/BaseParamFilterReader.php';   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @author    hans lellelid, hans@velum.net - * @copyright © 2003 seasonfive. All rights reserved - * @version   $Revision: 1.7 $ + * @copyright � 2003 seasonfive. All rights reserved + * @version   $Id$   * @see       BaseParamFilterReader   * @package   phing.filters   */ @@ -154,4 +154,4 @@ class TailFilter extends BaseParamFilterReader implements ChainableReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/TidyFilter.php b/buildscripts/phing/classes/phing/filters/TidyFilter.php index 10d75fc4..22abcee5 100644..100755 --- a/buildscripts/phing/classes/phing/filters/TidyFilter.php +++ b/buildscripts/phing/classes/phing/filters/TidyFilter.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TidyFilter.php,v 1.2 2005/12/08 19:15:20 hlellelid Exp $   + *  $Id: a612fea7722441639c6dfdc69b43ad65ec02652f $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,56 +35,56 @@ include_once 'phing/filters/ChainableReader.php';   * </pre>   *    * @author Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.2 $ $Date: 2005/12/08 19:15:20 $ + * @version   $Id$   * @package   phing.filters   */  class TidyFilter extends BaseParamFilterReader implements ChainableReader { -   	 -	/** @var string Encoding of resulting document. */ -	private $encoding = 'utf8'; +     +    /** @var string Encoding of resulting document. */ +    private $encoding = 'utf8';      /** @var array Parameter[] */ -	private $configParameters = array(); +    private $configParameters = array(); -	/** -	 * Set the encoding for resulting (X)HTML document. -	 * @param string $v -	 */ -	public function setEncoding($v) { -		$this->encoding = $v; -	} -	 -	/** -	 * Sets the config params. -	 * @param array Parameter[] -	 * @see chain() -	 */ -	public function setConfigParameters($params) -	{ -		$this->configParameters = $params; -	} -	 -	/** -	 * Adds a <config> element (which is a Parameter). -	 * @return Parameter -	 */ -	public function createConfig() { -		$num = array_push($this->configParameters, new Parameter()); +    /** +     * Set the encoding for resulting (X)HTML document. +     * @param string $v +     */ +    public function setEncoding($v) { +        $this->encoding = $v; +    } +     +    /** +     * Sets the config params. +     * @param array Parameter[] +     * @see chain() +     */ +    public function setConfigParameters($params) +    { +        $this->configParameters = $params; +    } +     +    /** +     * Adds a <config> element (which is a Parameter). +     * @return Parameter +     */ +    public function createConfig() { +        $num = array_push($this->configParameters, new Parameter());          return $this->configParameters[$num-1]; -	} -	 -	/** -	 * Converts the Parameter objects being used to store configuration into a simle assoc array. -	 * @return array -	 */ -	private function getDistilledConfig() { -		$config = array(); -		foreach($this->configParameters as $p) { -			$config[$p->getName()] = $p->getValue(); -		} -		return $config; -	} -	 +    } +     +    /** +     * Converts the Parameter objects being used to store configuration into a simle assoc array. +     * @return array +     */ +    private function getDistilledConfig() { +        $config = array(); +        foreach($this->configParameters as $p) { +            $config[$p->getName()] = $p->getValue(); +        } +        return $config; +    } +          /**       * Reads input and returns Tidy-filtered output.       *  @@ -94,29 +94,29 @@ class TidyFilter extends BaseParamFilterReader implements ChainableReader {       *                        during reading            */      function read($len = null) { -    	 -		if (!class_exists('Tidy')) { -			throw new BuildException("You must enable the 'tidy' extension in your PHP configuration in order to use the Tidy filter."); -		} -		 -		if ( !$this->getInitialized() ) { +         +        if (!class_exists('Tidy')) { +            throw new BuildException("You must enable the 'tidy' extension in your PHP configuration in order to use the Tidy filter."); +        } +         +        if ( !$this->getInitialized() ) {              $this->_initialize();              $this->setInitialized(true);          } -		 +                  $buffer = $this->in->read($len);          if($buffer === -1) {              return -1;          } -		 -		$config = $this->getDistilledConfig(); -		 -		$tidy = new Tidy(); -		$tidy->parseString($buffer, $config, $this->encoding); -		$tidy->cleanRepair(); +         +        $config = $this->getDistilledConfig(); +         +        $tidy = new Tidy(); +        $tidy->parseString($buffer, $config, $this->encoding); +        $tidy->cleanRepair(); -		return tidy_get_output($tidy); -		 +        return tidy_get_output($tidy); +              } @@ -131,32 +131,32 @@ class TidyFilter extends BaseParamFilterReader implements ChainableReader {       */      public function chain(Reader $reader) {          $newFilter = new TidyFilter($reader); -		$newFilter->setConfigParameters($this->configParameters); -		$newFilter->setEncoding($this->encoding); +        $newFilter->setConfigParameters($this->configParameters); +        $newFilter->setEncoding($this->encoding);          $newFilter->setProject($this->getProject());          return $newFilter;      } -	 -	/** +     +    /**       * Initializes any parameters (e.g. config options).       * This method is only called when this filter is used through a <filterreader> tag in build file.       */      private function _initialize() {          $params = $this->getParameters(); -		if ($params) { -			foreach($params as $param) { -				if ($param->getType() == "config") { -					$this->configParameters[] = $param; -				} else { -					 -					if ($param->getName() == "encoding") { -					    $this->setEncoding($param->getValue()); -					} -					 -				} -				 -			} -		} +        if ($params) { +            foreach($params as $param) { +                if ($param->getType() == "config") { +                    $this->configParameters[] = $param; +                } else { +                     +                    if ($param->getName() == "encoding") { +                        $this->setEncoding($param->getValue()); +                    } +                     +                } +                 +            } +        }      }  } diff --git a/buildscripts/phing/classes/phing/filters/TranslateGettext.php b/buildscripts/phing/classes/phing/filters/TranslateGettext.php index f71823e3..b2a4264c 100644..100755 --- a/buildscripts/phing/classes/phing/filters/TranslateGettext.php +++ b/buildscripts/phing/classes/phing/filters/TranslateGettext.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: TranslateGettext.php,v 1.11 2005/12/08 15:59:56 hlellelid Exp $ + *  $Id: 7dc28b63ed7f57bcf86d92f2b669bd386c2076a6 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -39,7 +39,7 @@ include_once 'phing/filters/ChainableReader.php';   * </pre>   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.11 $ $Date: 2005/12/08 15:59:56 $ + * @version   $Id$   * @access    public   * @see       BaseFilterReader   * @package   phing.filters @@ -140,7 +140,7 @@ class TranslateGettext extends BaseParamFilterReader implements ChainableReader      protected function initEnvironment() {          $this->storedLocale = getenv("LANG"); -        $this->log("Setting locale to " . $this->locale, PROJECT_MSG_DEBUG); +        $this->log("Setting locale to " . $this->locale, Project::MSG_DEBUG);          putenv("LANG=".$this->locale);          $ret = setlocale(LC_ALL, $this->locale);          if ($ret === false) { @@ -150,7 +150,7 @@ class TranslateGettext extends BaseParamFilterReader implements ChainableReader              throw new BuildException($msg);          }         -        $this->log("Binding domain '".$this->domain."' to "  . $this->dir, PROJECT_MSG_DEBUG); +        $this->log("Binding domain '".$this->domain."' to "  . $this->dir, Project::MSG_DEBUG);          bindtextdomain($this->domain, $this->dir->getAbsolutePath());          textdomain($this->domain);              } @@ -181,7 +181,7 @@ class TranslateGettext extends BaseParamFilterReader implements ChainableReader          $charbefore = $matches[1];          $msgid = $matches[2];          $translated = gettext($msgid); -        $this->log("Translating \"$msgid\" => \"$translated\"", PROJECT_MSG_DEBUG); +        $this->log("Translating \"$msgid\" => \"$translated\"", Project::MSG_DEBUG);          return $charbefore . '"' . $translated . '"';      } @@ -231,7 +231,7 @@ class TranslateGettext extends BaseParamFilterReader implements ChainableReader          $matches = array();          if (preg_match('/([^\w]|^)(gettext\([^\)]+\))/', $buffer, $matches)) { -            $this->log("Unable to perform translation on: " . $matches[2], PROJECT_MSG_WARN); +            $this->log("Unable to perform translation on: " . $matches[2], Project::MSG_WARN);          }          $this->restoreEnvironment(); @@ -282,4 +282,4 @@ class TranslateGettext extends BaseParamFilterReader implements ChainableReader      }  } -?> + diff --git a/buildscripts/phing/classes/phing/filters/XincludeFilter.php b/buildscripts/phing/classes/phing/filters/XincludeFilter.php new file mode 100644 index 00000000..e2b3cd00 --- /dev/null +++ b/buildscripts/phing/classes/phing/filters/XincludeFilter.php @@ -0,0 +1,176 @@ +<?php + +/* + *  $Id: 6c47e03d52cf26c183b05e347dac83735dd8c8dd $ + * + * 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>. + */ + +include_once 'phing/filters/BaseParamFilterReader.php'; +include_once 'phing/filters/ChainableReader.php'; + +/** + * Applies Xinclude parsing to incoming text. + *  + * Uses PHP DOM XML support + *  + * @author    Bill Karwin <bill@karwin.com> + * @version   $Id: 6c47e03d52cf26c183b05e347dac83735dd8c8dd $ + * @see       FilterReader + * @package   phing.filters + */ +class XincludeFilter extends BaseParamFilterReader implements ChainableReader { + +    private $basedir = null; + +    /** +     * @var bool +     */ +    private $processed = false; +     +    /** +     * Whether to resolve entities. +     *  +     * @var bool +     *  +     * @since 2.4 +     */ +    private $resolveExternals = false; +     +    /** +     * Whether to resolve entities. +     *  +     * @param $resolveExternals +     *  +     * @since 2.4 +     */ +    public function setResolveExternals($resolveExternals) +    { +        $this->resolveExternals = (bool)$resolveExternals; +    } +     +    /** +     * @return bool +     *  +     * @since 2.4 +     */ +    public function getResolveExternals() +    { +        return $this->resolveExternals; +    } + +    public function setBasedir(PhingFile $dir) +    { +        $this->basedir = $dir; +    } + +    public function getBasedir() +    { +        return $this->basedir; +    } + +    /** +     * Reads stream, applies XSLT and returns resulting stream. +     * @return string transformed buffer. +     * @throws BuildException - if XSLT support missing, if error in xslt processing +     */ +    function read($len = null) { +         +        if (!class_exists('DomDocument')) { +            throw new BuildException("Could not find the DomDocument class. Make sure PHP has been compiled/configured to support DOM XML."); +        } +         +        if ($this->processed === true) { +            return -1; // EOF +        } +         +        // Read XML +        $_xml = null; +        while ( ($data = $this->in->read($len)) !== -1 ) +            $_xml .= $data; + +        if ($_xml === null ) { // EOF? +            return -1; +        } + +        if (empty($_xml)) { +            $this->log("XML file is empty!", Project::MSG_WARN); +            return '';  +        } +        +        $this->log("Transforming XML " . $this->in->getResource() . " using Xinclude ", Project::MSG_VERBOSE); +         +        $out = ''; +        try { +            $out = $this->process($_xml); +            $this->processed = true; +        } catch (IOException $e) {             +            throw new BuildException($e); +        } + +        return $out; +    } + +    /** +     * Try to process the Xinclude transformation +     * +     * @param   string  XML to process. +     * +     * @throws BuildException   On errors +     */ +    protected function process($xml) {     +                 +        if ($this->basedir) { +            $cwd = getcwd(); +            chdir($this->basedir); +        } + +        // Create and setup document. +        $xmlDom                   = new DomDocument(); +        $xmlDom->resolveExternals = $this->resolveExternals; +         +        $xmlDom->loadXML($xml); +         +        $xmlDom->xinclude(); + +        if ($this->basedir) { +            chdir($cwd); +        } + +        return $xmlDom->saveXML(); +    }     + +    /** +     * Creates a new XincludeFilter using the passed in +     * Reader for instantiation. +     * +     * @param Reader A Reader object providing the underlying stream. +     *               Must not be <code>null</code>. +     * +     * @return Reader A new filter based on this configuration, but filtering +     *         the specified reader +     */ +    function chain(Reader $reader) { +        $newFilter = new XincludeFilter($reader); +        $newFilter->setProject($this->getProject()); +        $newFilter->setBasedir($this->getBasedir()); +        return $newFilter; +    } + +} + + diff --git a/buildscripts/phing/classes/phing/filters/XsltFilter.php b/buildscripts/phing/classes/phing/filters/XsltFilter.php index 0b8c4e6f..8866bff7 100644 --- a/buildscripts/phing/classes/phing/filters/XsltFilter.php +++ b/buildscripts/phing/classes/phing/filters/XsltFilter.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: XsltFilter.php,v 1.16 2005/12/07 20:05:01 hlellelid Exp $ + *  $Id: 057af49d450e4c137127acc0f5331368e7a76183 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/filters/ChainableReader.php';   * @author    Hans Lellelid <hans@velum.net>   * @author    Yannick Lecaillez <yl@seasonfive.com>   * @author    Andreas Aderhold <andi@binarycloud.com> - * @version   $Revision: 1.16 $ + * @version   $Id: 057af49d450e4c137127acc0f5331368e7a76183 $   * @see       FilterReader   * @package   phing.filters   */ @@ -61,6 +61,26 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {      private $html = false;      /** +     * Whether to resolve entities in the XML document (see  +     * {@link http://www.php.net/manual/en/class.domdocument.php#domdocument.props.resolveexternals}  +     * for more details). +     *  +     * @var bool +     *  +     * @since 2.4 +     */ +    private $resolveDocumentExternals = false; +     +    /** +     * Whether to resolve entities in the stylesheet. +     *  +     * @var bool +     *  +     * @since 2.4 +     */ +    private $resolveStylesheetExternals = false; +     +    /**       * Create new XSLT Param object, to handle the <param/> nested element.       * @return XSLTParam       */ @@ -121,6 +141,46 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {      }      /** +     * Whether to resolve entities in document. +     *  +     * @param bool $resolveExternals +     *  +     * @since 2.4 +     */ +    function setResolveDocumentExternals($resolveExternals) { +        $this->resolveDocumentExternals = (bool)$resolveExternals; +    } +     +    /** +     * @return bool +     *  +     * @since 2.4 +     */ +    function getResolveDocumentExternals() { +        return $this->resolveDocumentExternals; +    } +     +    /** +     * Whether to resolve entities in stylesheet. +     *  +     * @param bool $resolveExternals +     *  +     * @since 2.4 +     */ +    function setResolveStylesheetExternals($resolveExternals) { +        $this->resolveStylesheetExternals = (bool)$resolveExternals; +    } +     +    /** +     * @return bool +     *  +     * @since 2.4 +     */ +    function getResolveStylesheetExternals() { +        return $this->resolveStylesheetExternals; +    } +     +    /**       * Reads stream, applies XSLT and returns resulting stream.       * @return string transformed buffer.       * @throws BuildException - if XSLT support missing, if error in xslt processing @@ -150,7 +210,7 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {          }          if(empty($_xml)) { -            $this->log("XML file is empty!", PROJECT_MSG_WARN); +            $this->log("XML file is empty!", Project::MSG_WARN);              return ''; // return empty string, don't attempt to apply XSLT          } @@ -159,7 +219,7 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {          $xslFr = new FileReader($this->xslFile);          $xslFr->readInto($_xsl); -        $this->log("Tranforming XML " . $this->in->getResource() . " using style " . $this->xslFile->getPath(), PROJECT_MSG_VERBOSE); +        $this->log("Tranforming XML " . $this->in->getResource() . " using style " . $this->xslFile->getPath(), Project::MSG_VERBOSE);          $out = '';          try { @@ -185,8 +245,13 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {          $processor = new XSLTProcessor(); -        $xmlDom = new DOMDocument(); -        $xslDom = new DOMDocument();         +        // Create and setup document. +        $xmlDom                   = new DOMDocument(); +        $xmlDom->resolveExternals = $this->resolveDocumentExternals; +         +        // Create and setup stylesheet. +        $xslDom                   = new DOMDocument(); +        $xslDom->resolveExternals = $this->resolveStylesheetExternals;          if ($this->html) {                          $xmlDom->loadHTML($xml); @@ -201,13 +266,16 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {          // ignoring param "type" attrib, because          // we're only supporting direct XSL params right now          foreach($this->xsltParams as $param) { -            $this->log("Setting XSLT param: " . $param->getName() . "=>" . $param->getExpression(), PROJECT_MSG_DEBUG); +            $this->log("Setting XSLT param: " . $param->getName() . "=>" . $param->getExpression(), Project::MSG_DEBUG);              $processor->setParameter(null, $param->getName(), $param->getExpression());          } -        $result = $processor->transformToXML($xmlDom); +        $errorlevel = error_reporting(); +        error_reporting($errorlevel & ~E_WARNING); +        @$result = $processor->transformToXML($xmlDom); +        error_reporting($errorlevel); -        if ( !$result ) { +        if (false === $result) {              //$errno = xslt_errno($processor);              //$err   = xslt_error($processor);                  throw new BuildException("XSLT Error");             @@ -262,6 +330,8 @@ class XsltFilter extends BaseParamFilterReader implements ChainableReader {  /**   * Class that holds an XSLT parameter. + * + * @package   phing.filters   */  class XSLTParam { @@ -286,6 +356,28 @@ class XSLTParam {      }      /** +     * Sets expression value (alias to the setExpression()) method.  +     * +     * @param string $v +     * @see setExpression() +     */ +    public function setValue($v) +    { +        $this->setExpression($v); +    } +     +    /** +     * Gets expression value (alias to the getExpression()) method.  +     * +     * @param string $v +     * @see getExpression() +     */ +    public function getValue() +    { +        return $this->getExpression(); +    } +     +    /**       * Sets expression value.       * @param string $expr       */ @@ -314,4 +406,3 @@ class XSLTParam {      }          } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php b/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php index 80508a82..c465d0a1 100644..100755 --- a/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php +++ b/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ChainReaderHelper.php,v 1.8 2005/02/27 20:52:09 mrook Exp $ + *  $Id: c1709ddb9da44ce62fbe072c61d29dba4814e3f6 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -61,7 +61,7 @@ include_once 'phing/filters/ChainableReader.php';   * TODO: Implement the classPath feature.   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> - * @version   $Revision: 1.8 $ $Date: 2005/02/27 20:52:09 $ + * @version   $Id$   * @access    public   * @package   phing.filters.util  */ @@ -181,4 +181,3 @@ class ChainReaderHelper {  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php b/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php index 34bc5943..f47e155c 100644..100755 --- a/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php +++ b/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: IniFileTokenReader.php,v 1.7 2005/05/26 13:10:51 mrook Exp $ + *  $Id: e709765b4c0c1be330183f462ab527fa8354b555 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ include_once 'phing/filters/ReplaceTokens.php'; // For class Token   * Class that allows reading tokens from INI files.   *    * @author    Manuel Holtgewe - * @version   $Revision: 1.7 $ + * @version   $Id$   * @package   phing.filters.util   */  class IniFileTokenReader extends TokenReader { @@ -49,6 +49,7 @@ class IniFileTokenReader extends TokenReader {       * Reads the next token from the INI file       *       * @throws  IOException     On error +     * @return Token       */      function readToken() {          if ($this->file === null) { @@ -93,4 +94,4 @@ class IniFileTokenReader extends TokenReader {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/input/DefaultInputHandler.php b/buildscripts/phing/classes/phing/input/DefaultInputHandler.php index 8ce76cdd..5e53c878 100644..100755 --- a/buildscripts/phing/classes/phing/input/DefaultInputHandler.php +++ b/buildscripts/phing/classes/phing/input/DefaultInputHandler.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: DefaultInputHandler.php,v 1.6 2004/02/27 18:49:13 hlellelid Exp $ + *  $Id: 5d3d4fb125da3344b5aafec31ba330969bdbdb42 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@ include_once 'phing/system/io/ConsoleReader.php';   *   * @author Hans Lellelid <hans@xmpl.org> (Phing)   * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.6 $ + * @version $Id$   * @package phing.input   */  class DefaultInputHandler implements InputHandler { @@ -66,15 +66,18 @@ class DefaultInputHandler implements InputHandler {       */      protected function getPrompt(InputRequest $request) {          $prompt = $request->getPrompt(); +        $defaultValue = $request->getDefaultValue(); -        // use is_a() to avoid needing the class to be loaded -        if (is_a($request, 'YesNoInputRequest')) { // (yes/no) +        if ($request instanceof YesNoInputRequest) { +            $choices = $request->getChoices(); +            $defaultValue = $choices[(int) !$request->getDefaultValue()];              $prompt .= '(' . implode('/', $request->getChoices()) .')'; -        } elseif (is_a($request, 'MultipleChoiceInputRequest')) { // (a,b,c,d) +        } elseif ($request instanceof MultipleChoiceInputRequest) { // (a,b,c,d)              $prompt .= '(' . implode(',', $request->getChoices()) . ')';                      } +                  if ($request->getDefaultValue() !== null) { -            $prompt .= ' ['.$request->getDefaultValue().']'; +            $prompt .= ' ['.$defaultValue.']';          }          $pchar = $request->getPromptChar();                  return $prompt . ($pchar ? $pchar . ' ' : ' '); diff --git a/buildscripts/phing/classes/phing/input/InputHandler.php b/buildscripts/phing/classes/phing/input/InputHandler.php index 68fad7b5..9a414fd4 100644..100755 --- a/buildscripts/phing/classes/phing/input/InputHandler.php +++ b/buildscripts/phing/classes/phing/input/InputHandler.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: InputHandler.php,v 1.3 2003/12/24 12:38:39 hlellelid Exp $ + *  $Id: c7412bfab167852910c4dfe935769e4b0c7ec9fe $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,7 +24,7 @@   * Plugin to Phing to handle requests for user input.   *   * @author Stefan Bodewig <stefan.bodewig@epost.de> - * @version $Revision: 1.3 $ + * @version $Id$   * @package phing.input   */  interface InputHandler { diff --git a/buildscripts/phing/classes/phing/input/InputRequest.php b/buildscripts/phing/classes/phing/input/InputRequest.php index 7bfe8def..1d9e156d 100644..100755 --- a/buildscripts/phing/classes/phing/input/InputRequest.php +++ b/buildscripts/phing/classes/phing/input/InputRequest.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: InputRequest.php,v 1.4 2003/12/24 12:38:39 hlellelid Exp $ + *  $Id: f74cb3768bf512aeb0156b8de3e3b65c824cd0dc $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@   *   * @author Hans Lellelid <hans@xmpl.org> (Phing)   * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.4 $ + * @version $Id$   * @package phing.input   */  class InputRequest { diff --git a/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php b/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php index d4ea1212..24e93b58 100644..100755 --- a/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php +++ b/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: MultipleChoiceInputRequest.php,v 1.5 2004/03/15 17:11:15 hlellelid Exp $ + *  $Id: 12fcf735b10cae890d51bce8d3aebb637d9b6928 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ require_once 'phing/input/InputRequest.php';   * Encapsulates an input request.   *   * @author Stefan Bodewig <stefan.bodewig@epost.de> - * @version $Revision: 1.5 $ + * @version $Id$   * @package phing.input   */  class MultipleChoiceInputRequest extends InputRequest { diff --git a/buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php b/buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php deleted file mode 100644 index e588cead..00000000 --- a/buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php +++ /dev/null @@ -1,129 +0,0 @@ -/* - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2002 The Apache Software Foundation.  All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in - *    the documentation and/or other materials provided with the - *    distribution. - * - * 3. The end-user documentation included with the redistribution, if - *    any, must include the following acknowlegement: - *       "This product includes software developed by the - *        Apache Software Foundation (http://www.apache.org/)." - *    Alternately, this acknowlegement may appear in the software itself, - *    if and wherever such third-party acknowlegements normally appear. - * - * 4. The names "Ant" and "Apache Software - *    Foundation" must not be used to endorse or promote products derived - *    from this software without prior written permission. For written - *    permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache" - *    nor may "Apache" appear in their names without prior written - *    permission of the Apache Group. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR - * ITS 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 on behalf of the Apache Software Foundation.  For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ - -package org.apache.tools.ant.input; - -import org.apache.tools.ant.BuildException; - -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; - -/** - * Reads input from a property file, the file name is read from the - * system property ant.input.properties, the prompt is the key for input. - * - * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> - * @version $Revision: 1.1 $ - * @since Ant 1.5 - */ -public class PropertyFileInputHandler implements InputHandler { -    private Properties props = null; - -    /** -     * Name of the system property we expect to hold the file name. -     */ -    public static final String FILE_NAME_KEY = "ant.input.properties"; - -    /** -     * Empty no-arg constructor. -     */ -    public PropertyFileInputHandler() { -    } - -    /** -     * Picks up the input from a property, using the prompt as the -     * name of the property. -     * -     * @exception BuildException if no property of that name can be found. -     */ -    public void handleInput(InputRequest request) throws BuildException { -        readProps(); -         -        Object o = props.get(request.getPrompt()); -        if (o == null) { -            throw new BuildException("Unable to find input for \'" -                                     + request.getPrompt()+"\'"); -        } -        request.setInput(o.toString()); -        if (!request.isInputValid()) { -            throw new BuildException("Found invalid input " + o -                                     + " for \'" + request.getPrompt() + "\'"); -        } -    } - -    /** -     * Reads the properties file if it hasn't already been read. -     */ -    private synchronized void readProps() throws BuildException { -        if (props == null) { -            String propsFile = System.getProperty(FILE_NAME_KEY); -            if (propsFile == null) { -                throw new BuildException("System property " -                                         + FILE_NAME_KEY -                                         + " for PropertyFileInputHandler not" -                                         + " set"); -            } -             -            props = new Properties(); -             -            try { -                props.load(new FileInputStream(propsFile)); -            } catch (IOException e) { -                throw new BuildException("Couldn't load " + propsFile, e); -            } -        } -    } - -} diff --git a/buildscripts/phing/classes/phing/input/YesNoInputRequest.php b/buildscripts/phing/classes/phing/input/YesNoInputRequest.php index e34863d5..1a712327 100644..100755 --- a/buildscripts/phing/classes/phing/input/YesNoInputRequest.php +++ b/buildscripts/phing/classes/phing/input/YesNoInputRequest.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: YesNoInputRequest.php,v 1.4 2003/12/24 12:38:39 hlellelid Exp $ + *  $Id: 659526fec1ed2e66d5b9308fba48924ea3dda494 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ require_once 'phing/input/MultipleChoiceInputRequest.php';   * Encapsulates an input request that returns a boolean (yes/no).   *   * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.4 $ + * @version $Id: 659526fec1ed2e66d5b9308fba48924ea3dda494 $   * @package phing.input   */  class YesNoInputRequest extends MultipleChoiceInputRequest {      diff --git a/buildscripts/phing/classes/phing/lib/Capsule.php b/buildscripts/phing/classes/phing/lib/Capsule.php index bab05486..e6885a6a 100644..100755 --- a/buildscripts/phing/classes/phing/lib/Capsule.php +++ b/buildscripts/phing/classes/phing/lib/Capsule.php @@ -9,7 +9,8 @@   * the business logic from display / output logic.   *    * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.9 $ $Date: 2004/08/31 20:12:02 $ + * @version $Id$ + * @package phing.lib   */  class Capsule { diff --git a/buildscripts/phing/classes/phing/lib/Zip.php b/buildscripts/phing/classes/phing/lib/Zip.php deleted file mode 100644 index 70d31595..00000000 --- a/buildscripts/phing/classes/phing/lib/Zip.php +++ /dev/null @@ -1,3588 +0,0 @@ -<?php -/* vim: set ts=4 sw=4: */ -// +----------------------------------------------------------------------+ -// | PHP Version 4                                                        | -// +----------------------------------------------------------------------+ -// | Copyright (c) 1997-2003 The PHP Group                                | -// +----------------------------------------------------------------------+ -// | This source file is subject to version 3.0 of the PHP license,       | -// | that is bundled with this package in the file LICENSE, and is        | -// | available through the world-wide-web at the following url:           | -// | http://www.php.net/license/3_0.txt.                                  | -// | If you did not receive a copy of the PHP license and are unable to   | -// | obtain it through the world-wide-web, please send a note to          | -// | license@php.net so we can mail you a copy immediately.               | -// +----------------------------------------------------------------------+ -// | Author: Vincent Blavet <vincent@blavet.net>                          | -// +----------------------------------------------------------------------+ -// -// $Id: Zip.php,v 1.3 2005/12/27 16:05:57 hlellelid Exp $ - -  // ----- Constants -  define( 'ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048 ); - -  // ----- File list separator -  define( 'ARCHIVE_ZIP_SEPARATOR', ',' ); - -  // ----- Optional static temporary directory -  //       By default temporary files are generated in the script current -  //       path. -  //       If defined : -  //       - MUST BE terminated by a '/'. -  //       - MUST be a valid, already created directory -  //       Samples : -  // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '/temp/' ); -  // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', 'C:/Temp/' ); -  define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '' ); - -  // ----- Error codes -  define( 'ARCHIVE_ZIP_ERR_NO_ERROR', 0 ); -  define( 'ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1 ); -  define( 'ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2 ); -  define( 'ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3 ); -  define( 'ARCHIVE_ZIP_ERR_MISSING_FILE', -4 ); -  define( 'ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5 ); -  define( 'ARCHIVE_ZIP_ERR_INVALID_ZIP', -6 ); -  define( 'ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7 ); -  define( 'ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8 ); -  define( 'ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9 ); -  define( 'ARCHIVE_ZIP_ERR_BAD_FORMAT', -10 ); -  define( 'ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11 ); -  define( 'ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12 ); -  define( 'ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13 ); -  define( 'ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14 ); -  define( 'ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15 ); -  define( 'ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16 ); - -  // ----- Warning codes -  define( 'ARCHIVE_ZIP_WARN_NO_WARNING', 0 ); -  define( 'ARCHIVE_ZIP_WARN_FILE_EXIST', 1 ); - -  // ----- Methods parameters -  define( 'ARCHIVE_ZIP_PARAM_PATH', 'path' ); -  define( 'ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path' ); -  define( 'ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path' ); -  define( 'ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path' ); -  define( 'ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod' ); -  define( 'ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string' ); -  define( 'ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression' ); -  define( 'ARCHIVE_ZIP_PARAM_BY_NAME', 'by_name' ); -  define( 'ARCHIVE_ZIP_PARAM_BY_INDEX', 'by_index' ); -  define( 'ARCHIVE_ZIP_PARAM_BY_EREG', 'by_ereg' ); -  define( 'ARCHIVE_ZIP_PARAM_BY_PREG', 'by_preg' ); - -  define( 'ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract' ); -  define( 'ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract' ); -  define( 'ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add' ); -  define( 'ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add' ); - - - -/** -* Class for manipulating zip archive files -* -* A class which provided common methods to manipulate ZIP formatted -* archive files. -* It provides creation, extraction, deletion and add features. -* -* @author   Vincent Blavet <vincent@blavet.net> -* @version  $Revision: 1.3 $ -* @package  phing.lib -*/ -class Archive_Zip -{ -    /** -    * The filename of the zip archive. -    * -    * @var string Name of the Zip file -    */ -    var $_zipname=''; - -    /** -    * File descriptor of the opened Zip file. -    * -    * @var int Internal zip file descriptor -    */ -    var $_zip_fd=0; - -    /** -    * @var int last error code -    */ -    var $_error_code=1; - -    /** -    * @var string Last error description -    */ -    var $_error_string=''; - -    // {{{ constructor -    /** -    * Archive_Zip Class constructor. This flavour of the constructor only -    * declare a new Archive_Zip object, identifying it by the name of the -    * zip file. -    * -    * @param    string  $p_zipname  The name of the zip archive to create -    * @access public -    */ -    function __construct($p_zipname) -    { -      if (!extension_loaded('zlib')) { -          throw new Exception("The extension 'zlib' couldn't be found.\n". -              "Please make sure your version of PHP was built ". -              "with 'zlib' support."); -      } - -      // ----- Set the attributes -      $this->_zipname = $p_zipname; -      $this->_zip_fd = 0; -    } -    // }}} - -    // {{{ create() -    /** -    * This method creates a Zip Archive with the filename set with -	* the constructor. -	* The files and directories indicated in $p_filelist -    * are added in the archive. -	* When a directory is in the list, the directory and its content is added -    * in the archive. -    * The methods takes a variable list of parameters in $p_params. -    * The supported parameters for this method are : -    *   'add_path' : Add a path to the archived files. -    *   'remove_path' : Remove the specified 'root' path of the archived files. -    *   'remove_all_path' : Remove all the path of the archived files. -    *   'no_compression' : The archived files will not be compressed. -    * -    * @access public -    * @param  mixed  $p_filelist  The list of the files or folders to add. -    *                             It can be a string with filenames separated -    *                             by a comma, or an array of filenames. -    * @param  mixed  $p_params  An array of variable parameters and values. -    * @return mixed An array of file description on success, -	*               an error code on error -    */ -    function create($p_filelist, $p_params=0) -    { -        $this->_errorReset(); - -        // ----- Set default values -        if ($p_params === 0) { -    	    $p_params = array(); -        } -        if ($this->_check_parameters($p_params, -	                                 array('no_compression' => false, -	                                       'add_path' => "", -	                                       'remove_path' => "", -	                                       'remove_all_path' => false)) != 1) { -		    return 0; -	    } - -        // ----- Look if the $p_filelist is really an array -        $p_result_list = array(); -        if (is_array($p_filelist)) { -            $v_result = $this->_create($p_filelist, $p_result_list, $p_params); -        } - -        // ----- Look if the $p_filelist is a string -        else if (is_string($p_filelist)) { -            // ----- Create a list with the elements from the string -            $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist); - -            $v_result = $this->_create($v_list, $p_result_list, $p_params); -        } - -        // ----- Invalid variable -        else { -            $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -	                         'Invalid variable type p_filelist'); -            $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; -        } - -        if ($v_result != 1) { -            return 0; -        } - -        return $p_result_list; -    } -    // }}} - -    // {{{ add() -    /** -    * This method add files or directory in an existing Zip Archive. -    * If the Zip Archive does not exist it is created. -	* The files and directories to add are indicated in $p_filelist. -	* When a directory is in the list, the directory and its content is added -    * in the archive. -    * The methods takes a variable list of parameters in $p_params. -    * The supported parameters for this method are : -    *   'add_path' : Add a path to the archived files. -    *   'remove_path' : Remove the specified 'root' path of the archived files. -    *   'remove_all_path' : Remove all the path of the archived files. -    *   'no_compression' : The archived files will not be compressed. -    *   'callback_pre_add' : A callback function that will be called before -    *                        each entry archiving. -    *   'callback_post_add' : A callback function that will be called after -    *                         each entry archiving. -    * -    * @access public -    * @param    mixed  $p_filelist  The list of the files or folders to add. -    *                               It can be a string with filenames separated -    *                               by a comma, or an array of filenames. -    * @param    mixed  $p_params  An array of variable parameters and values. -    * @return mixed An array of file description on success, -	*               0 on an unrecoverable failure, an error code is logged. -    */ -    function add($p_filelist, $p_params=0) -    { -        $this->_errorReset(); - -        // ----- Set default values -        if ($p_params === 0) { -        	$p_params = array(); -        } -        if ($this->_check_parameters($p_params, -	                                 array ('no_compression' => false, -	                                        'add_path' => '', -	                                        'remove_path' => '', -	                                        'remove_all_path' => false, -						    	     		'callback_pre_add' => '', -							    		    'callback_post_add' => '')) != 1) { -		    return 0; -	    } - -        // ----- Look if the $p_filelist is really an array -        $p_result_list = array(); -        if (is_array($p_filelist)) { -            // ----- Call the create fct -            $v_result = $this->_add($p_filelist, $p_result_list, $p_params); -        } - -        // ----- Look if the $p_filelist is a string -        else if (is_string($p_filelist)) { -            // ----- Create a list with the elements from the string -            $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist); - -            // ----- Call the create fct -            $v_result = $this->_add($v_list, $p_result_list, $p_params); -        } - -        // ----- Invalid variable -        else { -            $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -	                         "add() : Invalid variable type p_filelist"); -            $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; -        } - -        if ($v_result != 1) { -            return 0; -        } - -        // ----- Return the result list -        return $p_result_list; -    } -    // }}} - -    // {{{ listContent() -    /** -    * This method gives the names and properties of the files and directories -	* which are present in the zip archive. -    * The properties of each entries in the list are : -    *   filename : Name of the file. -	*              For create() or add() it's the filename given by the user. -	*              For an extract() it's the filename of the extracted file. -    *   stored_filename : Name of the file / directory stored in the archive. -    *   size : Size of the stored file. -    *   compressed_size : Size of the file's data compressed in the archive -    *                     (without the zip headers overhead) -    *   mtime : Last known modification date of the file (UNIX timestamp) -    *   comment : Comment associated with the file -    *   folder : true | false (indicates if the entry is a folder) -    *   index : index of the file in the archive (-1 when not available) -    *   status : status of the action on the entry (depending of the action) : -    *            Values are : -    *              ok : OK ! -    *              filtered : the file/dir was not extracted (filtered by user) -    *              already_a_directory : the file can't be extracted because a -    *                                    directory with the same name already -	*                                    exists -    *              write_protected : the file can't be extracted because a file -    *                                with the same name already exists and is -    *                                write protected -    *              newer_exist : the file was not extracted because a newer -	*                            file already exists -    *              path_creation_fail : the file is not extracted because the -	*                                   folder does not exists and can't be -	*                                   created -    *              write_error : the file was not extracted because there was a -    *                            error while writing the file -    *              read_error : the file was not extracted because there was a -	*                           error while reading the file -    *              invalid_header : the file was not extracted because of an -	*                               archive format error (bad file header) -    * Note that each time a method can continue operating when there -    * is an error on a single file, the error is only logged in the file status. -    * -    * @access public -    * @return mixed An array of file description on success, -	*               0 on an unrecoverable failure, an error code is logged. -    */ -    function listContent() -    { -        $this->_errorReset(); - -        // ----- Check archive -        if (!$this->_checkFormat()) { -            return(0); -        } - -        $v_list = array(); -        if ($this->_list($v_list) != 1) { -            unset($v_list); -            return(0); -        } - -        return $v_list; -    } -    // }}} - -    // {{{ extract() -    /** -    * This method extract the files and folders which are in the zip archive. -    * It can extract all the archive or a part of the archive by using filter -    * feature (extract by name, by index, by ereg, by preg). The extraction -    * can occur in the current path or an other path. -    * All the advanced features are activated by the use of variable -	* parameters. -	* The return value is an array of entry descriptions which gives -	* information on extracted files (See listContent()). -	* The method may return a success value (an array) even if some files -	* are not correctly extracted (see the file status in listContent()). -    * The supported variable parameters for this method are : -    *   'add_path' : Path where the files and directories are to be extracted -    *   'remove_path' : First part ('root' part) of the memorized path -    *                   (if similar) to remove while extracting. -    *   'remove_all_path' : Remove all the memorized path while extracting. -    *   'extract_as_string' : -    *   'set_chmod' : After the extraction of the file the indicated mode -    *                 will be set. -    *   'by_name' : It can be a string with file/dir names separated by ',', -    *               or an array of file/dir names to extract from the archive. -    *   'by_index' : A string with range of indexes separated by ',', -    *                (sample "1,3-5,12"). -    *   'by_ereg' : A regular expression (ereg) that must match the extracted -    *               filename. -    *   'by_preg' : A regular expression (preg) that must match the extracted -    *               filename. -    *   'callback_pre_extract' : A callback function that will be called before -    *                            each entry extraction. -    *   'callback_post_extract' : A callback function that will be called after -    *                            each entry extraction. -    * -    * @access public -    * @param    mixed  $p_params  An array of variable parameters and values. -    * @return mixed An array of file description on success, -	*               0 on an unrecoverable failure, an error code is logged. -    */ -    function extract($p_params=0) -    { - -        $this->_errorReset(); - -        // ----- Check archive -        if (!$this->_checkFormat()) { -            return(0); -        } - -        // ----- Set default values -        if ($p_params === 0) { -        	$p_params = array(); -        } -        if ($this->_check_parameters($p_params, -	                                 array ('extract_as_string' => false, -	                                        'add_path' => '', -	                                        'remove_path' => '', -	                                        'remove_all_path' => false, -					    		     		'callback_pre_extract' => '', -						    			    'callback_post_extract' => '', -							    		    'set_chmod' => 0, -								    	    'by_name' => '', -									        'by_index' => '', -									        'by_ereg' => '', -									        'by_preg' => '') ) != 1) { -	    	return 0; -	    } - -        // ----- Call the extracting fct -        $v_list = array(); -        if ($this->_extractByRule($v_list, $p_params) != 1) { -            unset($v_list); -            return(0); -        } - -        return $v_list; -    } -    // }}} - - -    // {{{ delete() -    /** -    * This methods delete archive entries in the zip archive. -    * Notice that at least one filtering rule (set by the variable parameter -    * list) must be set. -    * Also notice that if you delete a folder entry, only the folder entry -    * is deleted, not all the files bellonging to this folder. -    * The supported variable parameters for this method are : -    *   'by_name' : It can be a string with file/dir names separated by ',', -    *               or an array of file/dir names to delete from the archive. -    *   'by_index' : A string with range of indexes separated by ',', -    *                (sample "1,3-5,12"). -    *   'by_ereg' : A regular expression (ereg) that must match the extracted -    *               filename. -    *   'by_preg' : A regular expression (preg) that must match the extracted -    *               filename. -    * -    * @access public -    * @param    mixed  $p_params  An array of variable parameters and values. -    * @return mixed An array of file description on success, -	*               0 on an unrecoverable failure, an error code is logged. -    */ -    function delete($p_params) -    { -        $this->_errorReset(); - -        // ----- Check archive -        if (!$this->_checkFormat()) { -            return(0); -        } - -        // ----- Set default values -        if ($this->_check_parameters($p_params, -	                                 array ('by_name' => '', -									        'by_index' => '', -									        'by_ereg' => '', -									        'by_preg' => '') ) != 1) { -	    	return 0; -    	} - -        // ----- Check that at least one rule is set -        if (   ($p_params['by_name'] == '') -            && ($p_params['by_index'] == '') -            && ($p_params['by_ereg'] == '') -            && ($p_params['by_preg'] == '')) { -            $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -			                 'At least one filtering rule must' -							 .' be set as parameter'); -            return 0; -        } - -        // ----- Call the delete fct -        $v_list = array(); -        if ($this->_deleteByRule($v_list, $p_params) != 1) { -            unset($v_list); -            return(0); -        } - -        return $v_list; -    } -    // }}} - -    // {{{ properties() -    /** -    * This method gives the global properties of the archive. -    *  The properties are : -    *    nb : Number of files in the archive -    *    comment : Comment associated with the archive file -    *    status : not_exist, ok -    * -    * @access public -    * @param    mixed  $p_params  {Description} -    * @return mixed An array with the global properties or 0 on error. -    */ -    function properties() -    { -        $this->_errorReset(); - -        // ----- Check archive -        if (!$this->_checkFormat()) { -            return(0); -        } - -        // ----- Default properties -        $v_prop = array(); -        $v_prop['comment'] = ''; -        $v_prop['nb'] = 0; -        $v_prop['status'] = 'not_exist'; - -        // ----- Look if file exists -        if (@is_file($this->_zipname)) { -            // ----- Open the zip file -            if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) { -                $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -				                 'Unable to open archive \''.$this->_zipname -								 .'\' in binary read mode'); -                return 0; -            } - -            // ----- Read the central directory informations -            $v_central_dir = array(); -            if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { -                return 0; -            } - -            $this->_closeFd(); - -            // ----- Set the user attributes -            $v_prop['comment'] = $v_central_dir['comment']; -            $v_prop['nb'] = $v_central_dir['entries']; -            $v_prop['status'] = 'ok'; -        } - -        return $v_prop; -    } -    // }}} - - -    // {{{ duplicate() -    /** -    * This method creates an archive by copying the content of an other one. -	* If the archive already exist, it is replaced by the new one without -	* any warning. -    * -    * @access public -    * @param  mixed  $p_archive  It can be a valid Archive_Zip object or -	*                            the filename of a valid zip archive. -    * @return integer 1 on success, 0 on failure. -    */ -    function duplicate($p_archive) -    { -        $this->_errorReset(); - -        // ----- Look if the $p_archive is a Archive_Zip object -        if (   (is_object($p_archive)) -		    && (strtolower(get_class($p_archive)) == 'archive_zip')) { -            $v_result = $this->_duplicate($p_archive->_zipname); -        } - -        // ----- Look if the $p_archive is a string (so a filename) -        else if (is_string($p_archive)) { -            // ----- Check that $p_archive is a valid zip file -            // TBC : Should also check the archive format -            if (!is_file($p_archive)) { -                $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, -				                 "No file with filename '".$p_archive."'"); -                $v_result = ARCHIVE_ZIP_ERR_MISSING_FILE; -            } -            else { -                $v_result = $this->_duplicate($p_archive); -            } -        } - -        // ----- Invalid variable -        else { -            $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -			                 "Invalid variable type p_archive_to_add"); -            $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; -        } - -        return $v_result; -    } -    // }}} - -    // {{{ merge() -    /** -    *  This method merge a valid zip archive at the end of the -	*  archive identified by the Archive_Zip object. -    *  If the archive ($this) does not exist, the merge becomes a duplicate. -    *  If the archive to add does not exist, the merge is a success. -    * -    * @access public -    * @param mixed $p_archive_to_add  It can be a valid Archive_Zip object or -	*                                 the filename of a valid zip archive. -    * @return integer 1 on success, 0 on failure. -    */ -    function merge($p_archive_to_add) -    { -        $v_result = 1; -        $this->_errorReset(); - -        // ----- Check archive -        if (!$this->_checkFormat()) { -            return(0); -        } - -        // ----- Look if the $p_archive_to_add is a Archive_Zip object -        if (   (is_object($p_archive_to_add)) -		    && (strtolower(get_class($p_archive_to_add)) == 'archive_zip')) { -            $v_result = $this->_merge($p_archive_to_add); -        } - -        // ----- Look if the $p_archive_to_add is a string (so a filename) -        else if (is_string($p_archive_to_add)) { -            // ----- Create a temporary archive -            $v_object_archive = new Archive_Zip($p_archive_to_add); - -            // ----- Merge the archive -            $v_result = $this->_merge($v_object_archive); -        } - -        // ----- Invalid variable -        else { -            $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -			                 "Invalid variable type p_archive_to_add"); -            $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; -        } - -        return $v_result; -    } -    // }}} - -    // {{{ errorCode() -    /** -    * Method that gives the lastest error code. -    * -    * @access public -    * @return integer The error code value. -    */ -    function errorCode() -    { -        return($this->_error_code); -    } -    // }}} - -    // {{{ errorName() -    /** -    * This method gives the latest error code name. -    * -    * @access public -    * @param  boolean $p_with_code  If true, gives the name and the int value. -    * @return string The error name. -    */ -    function errorName($p_with_code=false) -    { -        $v_const_list = get_defined_constants(); -  	 -      	// ----- Extract error constants from all const. -        for (reset($v_const_list); -		     list($v_key, $v_value) = each($v_const_list);) { -     	    if (substr($v_key, 0, strlen('ARCHIVE_ZIP_ERR_')) -			    =='ARCHIVE_ZIP_ERR_') { -    		    $v_error_list[$v_key] = $v_value; -    	    } -        } -     -        // ----- Search the name form the code value -        $v_key=array_search($this->_error_code, $v_error_list, true); -  	    if ($v_key!=false) { -            $v_value = $v_key; -  	    } -  	    else { -            $v_value = 'NoName'; -  	    } -  	 -        if ($p_with_code) { -            return($v_value.' ('.$this->_error_code.')'); -        } -        else { -          return($v_value); -        } -    } -    // }}} - -    // {{{ errorInfo() -    /** -    * This method returns the description associated with the latest error. -    * -    * @access public -    * @param  boolean $p_full If set to true gives the description with the -    *                         error code, the name and the description. -    *                         If set to false gives only the description -    *                         and the error code. -    * @return string The error description. -    */ -    function errorInfo($p_full=false) -    { -        if ($p_full) { -            return($this->errorName(true)." : ".$this->_error_string); -        } -        else { -            return($this->_error_string." [code ".$this->_error_code."]"); -        } -    } -    // }}} - - -// ----------------------------------------------------------------------------- -// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** -// *****                                                        ***** -// *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       ***** -// ----------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _checkFormat() -  // Description : -  //   This method check that the archive exists and is a valid zip archive. -  //   Several level of check exists. (futur) -  // Parameters : -  //   $p_level : Level of check. Default 0. -  //              0 : Check the first bytes (magic codes) (default value)) -  //              1 : 0 + Check the central directory (futur) -  //              2 : 1 + Check each file header (futur) -  // Return Values : -  //   true on success, -  //   false on error, the error code is set. -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_checkFormat() -  * -  * { Description } -  * -  * @param integer $p_level -  */ -  function _checkFormat($p_level=0) -  { -    $v_result = true; - -    // ----- Reset the error handler -    $this->_errorReset(); - -    // ----- Look if the file exits -    if (!is_file($this->_zipname)) { -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, -	                   "Missing archive file '".$this->_zipname."'"); -      return(false); -    } - -    // ----- Check that the file is readeable -    if (!is_readable($this->_zipname)) { -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -	                   "Unable to read archive '".$this->_zipname."'"); -      return(false); -    } - -    // ----- Check the magic code -    // TBC - -    // ----- Check the central header -    // TBC - -    // ----- Check each file header -    // TBC - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _create() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_create() -  * -  * { Description } -  * -  */ -  function _create($p_list, &$p_result_list, &$p_params) -  { -    $v_result=1; -    $v_list_detail = array(); - -	$p_add_dir = $p_params['add_path']; -	$p_remove_dir = $p_params['remove_path']; -	$p_remove_all_dir = $p_params['remove_all_path']; - -    // ----- Open the file in write mode -    if (($v_result = $this->_openFd('wb')) != 1) -    { -      // ----- Return -      return $v_result; -    } - -    // ----- Add the list of files -    $v_result = $this->_addList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params); - -    // ----- Close -    $this->_closeFd(); - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _add() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_add() -  * -  * { Description } -  * -  */ -  function _add($p_list, &$p_result_list, &$p_params) -  { -    $v_result=1; -    $v_list_detail = array(); - -	$p_add_dir = $p_params['add_path']; -	$p_remove_dir = $p_params['remove_path']; -	$p_remove_all_dir = $p_params['remove_all_path']; - -    // ----- Look if the archive exists or is empty and need to be created -    if ((!is_file($this->_zipname)) || (filesize($this->_zipname) == 0)) { -      $v_result = $this->_create($p_list, $p_result_list, $p_params); -      return $v_result; -    } - -    // ----- Open the zip file -    if (($v_result=$this->_openFd('rb')) != 1) { -      return $v_result; -    } - -    // ----- Read the central directory informations -    $v_central_dir = array(); -    if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) -    { -      $this->_closeFd(); -      return $v_result; -    } - -    // ----- Go to beginning of File -    @rewind($this->_zip_fd); - -    // ----- Creates a temporay file -    $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp'; - -    // ----- Open the temporary file in write mode -    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) -    { -      $this->_closeFd(); - -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -	                   'Unable to open temporary file \'' -					   .$v_zip_temp_name.'\' in binary write mode'); -      return Archive_Zip::errorCode(); -    } - -    // ----- Copy the files from the archive to the temporary file -    // TBC : Here I should better append the file and go back to erase the -	// central dir -    $v_size = $v_central_dir['offset']; -    while ($v_size != 0) -    { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = fread($this->_zip_fd, $v_read_size); -      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Swap the file descriptor -    // Here is a trick : I swap the temporary fd with the zip fd, in order to  -    // use the following methods on the temporary fil and not the real archive -    $v_swap = $this->_zip_fd; -    $this->_zip_fd = $v_zip_temp_fd; -    $v_zip_temp_fd = $v_swap; - -    // ----- Add the files -    $v_header_list = array(); -    if (($v_result = $this->_addFileList($p_list, $v_header_list, -	                                     $p_add_dir, $p_remove_dir, -										 $p_remove_all_dir, $p_params)) != 1) -    { -      fclose($v_zip_temp_fd); -      $this->_closeFd(); -      @unlink($v_zip_temp_name); - -      // ----- Return -      return $v_result; -    } - -    // ----- Store the offset of the central dir -    $v_offset = @ftell($this->_zip_fd); - -    // ----- Copy the block of file headers from the old archive -    $v_size = $v_central_dir['size']; -    while ($v_size != 0) -    { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = @fread($v_zip_temp_fd, $v_read_size); -      @fwrite($this->_zip_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Create the Central Dir files header -    for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) -    { -      // ----- Create the file header -      if ($v_header_list[$i]['status'] == 'ok') { -        if (($v_result=$this->_writeCentralFileHeader($v_header_list[$i]))!=1) { -          fclose($v_zip_temp_fd); -          $this->_closeFd(); -          @unlink($v_zip_temp_name); - -          // ----- Return -          return $v_result; -        } -        $v_count++; -      } - -      // ----- Transform the header to a 'usable' info -      $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); -    } - -    // ----- Zip file comment -    $v_comment = ''; - -    // ----- Calculate the size of the central header -    $v_size = @ftell($this->_zip_fd)-$v_offset; - -    // ----- Create the central dir footer -    if (($v_result = $this->_writeCentralHeader($v_count -	                                              +$v_central_dir['entries'], -	                                            $v_size, $v_offset, -												$v_comment)) != 1) { -      // ----- Reset the file list -      unset($v_header_list); - -      // ----- Return -      return $v_result; -    } - -    // ----- Swap back the file descriptor -    $v_swap = $this->_zip_fd; -    $this->_zip_fd = $v_zip_temp_fd; -    $v_zip_temp_fd = $v_swap; - -    // ----- Close -    $this->_closeFd(); - -    // ----- Close the temporary file -    @fclose($v_zip_temp_fd); - -    // ----- Delete the zip file -    // TBC : I should test the result ... -    @unlink($this->_zipname); - -    // ----- Rename the temporary file -    // TBC : I should test the result ... -    //@rename($v_zip_temp_name, $this->_zipname); -    $this->_tool_Rename($v_zip_temp_name, $this->_zipname); - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _openFd() -  // Description : -  // Parameters : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_openFd() -  * -  * { Description } -  * -  */ -  function _openFd($p_mode) -  { -    $v_result=1; - -    // ----- Look if already open -    if ($this->_zip_fd != 0) -    { -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -	                   'Zip file \''.$this->_zipname.'\' already open'); -      return Archive_Zip::errorCode(); -    } - -    // ----- Open the zip file -    if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0) -    { -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -	                   'Unable to open archive \''.$this->_zipname -					   .'\' in '.$p_mode.' mode'); -      return Archive_Zip::errorCode(); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _closeFd() -  // Description : -  // Parameters : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_closeFd() -  * -  * { Description } -  * -  */ -  function _closeFd() -  { -    $v_result=1; - -    if ($this->_zip_fd != 0) -      @fclose($this->_zip_fd); -    $this->_zip_fd = 0; - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _addList() -  // Description : -  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is -  //   different from the real path of the file. This is usefull if you want to have PclTar -  //   running in any directory, and memorize relative path from an other directory. -  // Parameters : -  //   $p_list : An array containing the file or directory names to add in the tar -  //   $p_result_list : list of added files with their properties (specially the status field) -  //   $p_add_dir : Path to add in the filename path archived -  //   $p_remove_dir : Path to remove in the filename path archived -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_addList() -  * -  * { Description } -  * -  */ -  function _addList($p_list, &$p_result_list, -                    $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) -  { -    $v_result=1; - -    // ----- Add the files -    $v_header_list = array(); -    if (($v_result = $this->_addFileList($p_list, $v_header_list, -	                                     $p_add_dir, $p_remove_dir, -										 $p_remove_all_dir, $p_params)) != 1) { -      return $v_result; -    } - -    // ----- Store the offset of the central dir -    $v_offset = @ftell($this->_zip_fd); - -    // ----- Create the Central Dir files header -    for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++) -    { -      // ----- Create the file header -      if ($v_header_list[$i]['status'] == 'ok') { -        if (($v_result = $this->_writeCentralFileHeader($v_header_list[$i])) != 1) { -          return $v_result; -        } -        $v_count++; -      } - -      // ----- Transform the header to a 'usable' info -      $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); -    } - -    // ----- Zip file comment -    $v_comment = ''; - -    // ----- Calculate the size of the central header -    $v_size = @ftell($this->_zip_fd)-$v_offset; - -    // ----- Create the central dir footer -    if (($v_result = $this->_writeCentralHeader($v_count, $v_size, $v_offset, -	                                            $v_comment)) != 1) -    { -      // ----- Reset the file list -      unset($v_header_list); - -      // ----- Return -      return $v_result; -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _addFileList() -  // Description : -  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is -  //   different from the real path of the file. This is usefull if you want to -  //   run the lib in any directory, and memorize relative path from an other directory. -  // Parameters : -  //   $p_list : An array containing the file or directory names to add in the tar -  //   $p_result_list : list of added files with their properties (specially the status field) -  //   $p_add_dir : Path to add in the filename path archived -  //   $p_remove_dir : Path to remove in the filename path archived -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_addFileList() -  * -  * { Description } -  * -  */ -  function _addFileList($p_list, &$p_result_list, -                        $p_add_dir, $p_remove_dir, $p_remove_all_dir, -						&$p_params) -  { -    $v_result=1; -    $v_header = array(); - -    // ----- Recuperate the current number of elt in list -    $v_nb = sizeof($p_result_list); - -    // ----- Loop on the files -    for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++) -    { -      // ----- Recuperate the filename -      $p_filename = $this->_tool_TranslateWinPath($p_list[$j], false); - -      // ----- Skip empty file names -      if ($p_filename == "") -      { -        continue; -      } - -      // ----- Check the filename -      if (!file_exists($p_filename)) -      { -        $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, -		                 "File '$p_filename' does not exists"); -        return Archive_Zip::errorCode(); -      } - -      // ----- Look if it is a file or a dir with no all pathnre move -      if ((is_file($p_filename)) || ((is_dir($p_filename)) && !$p_remove_all_dir)) { -        // ----- Add the file -        if (($v_result = $this->_addFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) -        { -          // ----- Return status -          return $v_result; -        } - -        // ----- Store the file infos -        $p_result_list[$v_nb++] = $v_header; -      } - -      // ----- Look for directory -      if (is_dir($p_filename)) -      { - -        // ----- Look for path -        if ($p_filename != ".") -          $v_path = $p_filename."/"; -        else -          $v_path = ""; - -        // ----- Read the directory for files and sub-directories -        $p_hdir = opendir($p_filename); -        $p_hitem = readdir($p_hdir); // '.' directory -        $p_hitem = readdir($p_hdir); // '..' directory -        while ($p_hitem = readdir($p_hdir)) -        { - -          // ----- Look for a file -          if (is_file($v_path.$p_hitem)) -          { - -            // ----- Add the file -            if (($v_result = $this->_addFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) -            { -              // ----- Return status -              return $v_result; -            } - -            // ----- Store the file infos -            $p_result_list[$v_nb++] = $v_header; -          } - -          // ----- Recursive call to _addFileList() -          else -          { - -            // ----- Need an array as parameter -            $p_temp_list[0] = $v_path.$p_hitem; -            $v_result = $this->_addFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params); - -            // ----- Update the number of elements of the list -            $v_nb = sizeof($p_result_list); -          } -        } - -        // ----- Free memory for the recursive loop -        unset($p_temp_list); -        unset($p_hdir); -        unset($p_hitem); -      } -    } - -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _addFile() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_addFile() -  * -  * { Description } -  * -  */ -  function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) -  { -    $v_result=1; - -    if ($p_filename == "") -    { -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Calculate the stored filename -    $v_stored_filename = $p_filename; - -    // ----- Look for all path to remove -    if ($p_remove_all_dir) { -      $v_stored_filename = basename($p_filename); -    } -    // ----- Look for partial path remove -    else if ($p_remove_dir != "") -    { -      if (substr($p_remove_dir, -1) != '/') -        $p_remove_dir .= "/"; - -      if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./")) -      { -        if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./")) -          $p_remove_dir = "./".$p_remove_dir; -        if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./")) -          $p_remove_dir = substr($p_remove_dir, 2); -      } - -      $v_compare = $this->_tool_PathInclusion($p_remove_dir, $p_filename); -      if ($v_compare > 0) -//      if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) -      { - -        if ($v_compare == 2) { -          $v_stored_filename = ""; -        } -        else { -          $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); -        } -      } -    } -    // ----- Look for path to add -    if ($p_add_dir != "") -    { -      if (substr($p_add_dir, -1) == "/") -        $v_stored_filename = $p_add_dir.$v_stored_filename; -      else -        $v_stored_filename = $p_add_dir."/".$v_stored_filename; -    } - -    // ----- Filename (reduce the path of stored name) -    $v_stored_filename = $this->_tool_PathReduction($v_stored_filename); - - -    /* filename length moved after call-back in release 1.3 -    // ----- Check the path length -    if (strlen($v_stored_filename) > 0xFF) -    { -      // ----- Error log -      $this->_errorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'"); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } -    */ - -    // ----- Set the file properties -    clearstatcache(); -    $p_header['version'] = 20; -    $p_header['version_extracted'] = 10; -    $p_header['flag'] = 0; -    $p_header['compression'] = 0; -    $p_header['mtime'] = filemtime($p_filename); -    $p_header['crc'] = 0; -    $p_header['compressed_size'] = 0; -    $p_header['size'] = filesize($p_filename); -    $p_header['filename_len'] = strlen($p_filename); -    $p_header['extra_len'] = 0; -    $p_header['comment_len'] = 0; -    $p_header['disk'] = 0; -    $p_header['internal'] = 0; -    $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010); -    $p_header['offset'] = 0; -    $p_header['filename'] = $p_filename; -    $p_header['stored_filename'] = $v_stored_filename; -    $p_header['extra'] = ''; -    $p_header['comment'] = ''; -    $p_header['status'] = 'ok'; -    $p_header['index'] = -1; - -    // ----- Look for pre-add callback -    if (   (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD])) -	    && ($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD] != '')) { - -      // ----- Generate a local information -      $v_local_header = array(); -      $this->_convertHeader2FileInfo($p_header, $v_local_header); - -      // ----- Call the callback -      // Here I do not use call_user_func() because I need to send a reference to the -      // header. -      eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_ADD].'(ARCHIVE_ZIP_PARAM_PRE_ADD, $v_local_header);'); -      if ($v_result == 0) { -        // ----- Change the file status -        $p_header['status'] = "skipped"; -        $v_result = 1; -      } - -      // ----- Update the informations -      // Only some fields can be modified -      if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { -        $p_header['stored_filename'] = $this->_tool_PathReduction($v_local_header['stored_filename']); -      } -    } - -    // ----- Look for empty stored filename -    if ($p_header['stored_filename'] == "") { -      $p_header['status'] = "filtered"; -    } - -    // ----- Check the path length -    if (strlen($p_header['stored_filename']) > 0xFF) { -      $p_header['status'] = 'filename_too_long'; -    } - -    // ----- Look if no error, or file not skipped -    if ($p_header['status'] == 'ok') { - -      // ----- Look for a file -      if (is_file($p_filename)) -      { -        // ----- Open the source file -        if (($v_file = @fopen($p_filename, "rb")) == 0) { -          $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); -          return Archive_Zip::errorCode(); -        } -         -        if ($p_params['no_compression']) { -          // ----- Read the file content -          $v_content_compressed = @fread($v_file, $p_header['size']); - -          // ----- Calculate the CRC -          $p_header['crc'] = crc32($v_content_compressed); -        } -        else { -          // ----- Read the file content -          $v_content = @fread($v_file, $p_header['size']); - -          // ----- Calculate the CRC -          $p_header['crc'] = crc32($v_content); - -          // ----- Compress the file -          $v_content_compressed = gzdeflate($v_content); -        } - -        // ----- Set header parameters -        $p_header['compressed_size'] = strlen($v_content_compressed); -        $p_header['compression'] = 8; - -        // ----- Call the header generation -        if (($v_result = $this->_writeFileHeader($p_header)) != 1) { -          @fclose($v_file); -          return $v_result; -        } - -        // ----- Write the compressed content -        $v_binary_data = pack('a'.$p_header['compressed_size'], $v_content_compressed); -        @fwrite($this->_zip_fd, $v_binary_data, $p_header['compressed_size']); - -        // ----- Close the file -        @fclose($v_file); -      } - -      // ----- Look for a directory -      else -      { -        // ----- Set the file properties -        $p_header['filename'] .= '/'; -        $p_header['filename_len']++; -        $p_header['size'] = 0; -        $p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked - -        // ----- Call the header generation -        if (($v_result = $this->_writeFileHeader($p_header)) != 1) -        { -          return $v_result; -        } -      } -    } - -    // ----- Look for pre-add callback -    if (   (isset($p_params[ARCHIVE_ZIP_PARAM_POST_ADD])) -	    && ($p_params[ARCHIVE_ZIP_PARAM_POST_ADD] != '')) { - -      // ----- Generate a local information -      $v_local_header = array(); -      $this->_convertHeader2FileInfo($p_header, $v_local_header); - -      // ----- Call the callback -      // Here I do not use call_user_func() because I need to send a reference to the -      // header. -      eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_ADD].'(ARCHIVE_ZIP_PARAM_POST_ADD, $v_local_header);'); -      if ($v_result == 0) { -        // ----- Ignored -        $v_result = 1; -      } - -      // ----- Update the informations -      // Nothing can be modified -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _writeFileHeader() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_writeFileHeader() -  * -  * { Description } -  * -  */ -  function _writeFileHeader(&$p_header) -  { -    $v_result=1; - -    // TBC -    //for(reset($p_header); $key = key($p_header); next($p_header)) { -    //} - -    // ----- Store the offset position of the file -    $p_header['offset'] = ftell($this->_zip_fd); - -    // ----- Transform UNIX mtime to DOS format mdate/mtime -    $v_date = getdate($p_header['mtime']); -    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; -    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; - -    // ----- Packed data -    $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version'], $p_header['flag'], -                          $p_header['compression'], $v_mtime, $v_mdate, -                          $p_header['crc'], $p_header['compressed_size'], $p_header['size'], -                          strlen($p_header['stored_filename']), $p_header['extra_len']); - -    // ----- Write the first 148 bytes of the header in the archive -    fputs($this->_zip_fd, $v_binary_data, 30); - -    // ----- Write the variable fields -    if (strlen($p_header['stored_filename']) != 0) -    { -      fputs($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); -    } -    if ($p_header['extra_len'] != 0) -    { -      fputs($this->_zip_fd, $p_header['extra'], $p_header['extra_len']); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _writeCentralFileHeader() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_writeCentralFileHeader() -  * -  * { Description } -  * -  */ -  function _writeCentralFileHeader(&$p_header) -  { -    $v_result=1; - -    // TBC -    //for(reset($p_header); $key = key($p_header); next($p_header)) { -    //} - -    // ----- Transform UNIX mtime to DOS format mdate/mtime -    $v_date = getdate($p_header['mtime']); -    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; -    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; - -    // ----- Packed data -    $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'], -                          $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], -                          $p_header['compressed_size'], $p_header['size'], -                          strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'], -                          $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']); - -    // ----- Write the 42 bytes of the header in the zip file -    fputs($this->_zip_fd, $v_binary_data, 46); - -    // ----- Write the variable fields -    if (strlen($p_header['stored_filename']) != 0) -    { -      fputs($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); -    } -    if ($p_header['extra_len'] != 0) -    { -      fputs($this->_zip_fd, $p_header['extra'], $p_header['extra_len']); -    } -    if ($p_header['comment_len'] != 0) -    { -      fputs($this->_zip_fd, $p_header['comment'], $p_header['comment_len']); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _writeCentralHeader() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_writeCentralHeader() -  * -  * { Description } -  * -  */ -  function _writeCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) -  { -    $v_result=1; - -    // ----- Packed data -    $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment)); - -    // ----- Write the 22 bytes of the header in the zip file -    fputs($this->_zip_fd, $v_binary_data, 22); - -    // ----- Write the variable fields -    if (strlen($p_comment) != 0) -    { -      fputs($this->_zip_fd, $p_comment, strlen($p_comment)); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _list() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_list() -  * -  * { Description } -  * -  */ -  function _list(&$p_list) -  { -    $v_result=1; - -    // ----- Open the zip file -    if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) -    { -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->_zipname.'\' in binary read mode'); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Read the central directory informations -    $v_central_dir = array(); -    if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) -    { -      return $v_result; -    } - -    // ----- Go to beginning of Central Dir -    @rewind($this->_zip_fd); -    if (@fseek($this->_zip_fd, $v_central_dir['offset'])) -    { -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Read each entry -    for ($i=0; $i<$v_central_dir['entries']; $i++) -    { -      // ----- Read the file header -      if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) -      { -        return $v_result; -      } -      $v_header['index'] = $i; - -      // ----- Get the only interesting attributes -      $this->_convertHeader2FileInfo($v_header, $p_list[$i]); -      unset($v_header); -    } - -    // ----- Close the zip file -    $this->_closeFd(); - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _convertHeader2FileInfo() -  // Description : -  //   This function takes the file informations from the central directory -  //   entries and extract the interesting parameters that will be given back. -  //   The resulting file infos are set in the array $p_info -  //     $p_info['filename'] : Filename with full path. Given by user (add), -  //                           extracted in the filesystem (extract). -  //     $p_info['stored_filename'] : Stored filename in the archive. -  //     $p_info['size'] = Size of the file. -  //     $p_info['compressed_size'] = Compressed size of the file. -  //     $p_info['mtime'] = Last modification date of the file. -  //     $p_info['comment'] = Comment associated with the file. -  //     $p_info['folder'] = true/false : indicates if the entry is a folder or not. -  //     $p_info['status'] = status of the action on the file. -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_convertHeader2FileInfo() -  * -  * { Description } -  * -  */ -  function _convertHeader2FileInfo($p_header, &$p_info) -  { -    $v_result=1; - -    // ----- Get the interesting attributes -    $p_info['filename'] = $p_header['filename']; -    $p_info['stored_filename'] = $p_header['stored_filename']; -    $p_info['size'] = $p_header['size']; -    $p_info['compressed_size'] = $p_header['compressed_size']; -    $p_info['mtime'] = $p_header['mtime']; -    $p_info['comment'] = $p_header['comment']; -    $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); -    $p_info['index'] = $p_header['index']; -    $p_info['status'] = $p_header['status']; - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _extractByRule() -  // Description : -  //   Extract a file or directory depending of rules (by index, by name, ...) -  // Parameters : -  //   $p_file_list : An array where will be placed the properties of each -  //                  extracted file -  //   $p_path : Path to add while writing the extracted files -  //   $p_remove_path : Path to remove (from the file memorized path) while writing the -  //                    extracted files. If the path does not match the file path, -  //                    the file is extracted with its memorized path. -  //                    $p_remove_path does not apply to 'list' mode. -  //                    $p_path and $p_remove_path are commulative. -  // Return Values : -  //   1 on success,0 or less on error (see error code list) -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_extractByRule() -  * -  * { Description } -  * -  */ -  function _extractByRule(&$p_file_list, &$p_params) -  { -    $v_result=1; - -	$p_path = $p_params['add_path']; -	$p_remove_path = $p_params['remove_path']; -	$p_remove_all_path = $p_params['remove_all_path']; - -    // ----- Check the path -    if (($p_path == "") -	    || ((substr($p_path, 0, 1) != "/") -	    && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/"))) -      $p_path = "./".$p_path; - -    // ----- Reduce the path last (and duplicated) '/' -    if (($p_path != "./") && ($p_path != "/")) { -      // ----- Look for the path end '/' -      while (substr($p_path, -1) == "/") { -        $p_path = substr($p_path, 0, strlen($p_path)-1); -      } -    } - -    // ----- Look for path to remove format (should end by /) -    if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) { -      $p_remove_path .= '/'; -    } -    $p_remove_path_size = strlen($p_remove_path); - -    // ----- Open the zip file -    if (($v_result = $this->_openFd('rb')) != 1) -    { -      return $v_result; -    } - -    // ----- Read the central directory informations -    $v_central_dir = array(); -    if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) -    { -      // ----- Close the zip file -      $this->_closeFd(); - -      return $v_result; -    } - -    // ----- Start at beginning of Central Dir -    $v_pos_entry = $v_central_dir['offset']; - -    // ----- Read each entry -    $j_start = 0; -    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) { -      // ----- Read next Central dir entry -      @rewind($this->_zip_fd); -      if (@fseek($this->_zip_fd, $v_pos_entry)) { -        $this->_closeFd(); - -        $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, -		                 'Invalid archive size'); - -        return Archive_Zip::errorCode(); -      } - -      // ----- Read the file header -      $v_header = array(); -      if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) { -        $this->_closeFd(); - -        return $v_result; -      } - -      // ----- Store the index -      $v_header['index'] = $i; - -      // ----- Store the file position -      $v_pos_entry = ftell($this->_zip_fd); - -      // ----- Look for the specific extract rules -      $v_extract = false; - -      // ----- Look for extract by name rule -      if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) -          && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) { - -          // ----- Look if the filename is in the list -          for ($j=0; -		          ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) -			   && (!$v_extract); -			   $j++) { - -              // ----- Look for a directory -              if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == "/") { - -                  // ----- Look if the directory is in the filename path -                  if (   (strlen($v_header['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) -                      && (substr($v_header['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) { -                      $v_extract = true; -                  } -              } -              // ----- Look for a filename -              elseif ($v_header['stored_filename'] == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) { -                  $v_extract = true; -              } -          } -      } - -      // ----- Look for extract by ereg rule -      else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG])) -               && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != "")) { - -          if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG], $v_header['stored_filename'])) { -              $v_extract = true; -          } -      } - -      // ----- Look for extract by preg rule -      else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG])) -               && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != "")) { - -          if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], $v_header['stored_filename'])) { -              $v_extract = true; -          } -      } - -      // ----- Look for extract by index rule -      else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) -               && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) { - -          // ----- Look if the index is in the list -          for ($j=$j_start; ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) && (!$v_extract); $j++) { - -              if (($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) { -                  $v_extract = true; -              } -              if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) { -                  $j_start = $j+1; -              } - -              if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) { -                  break; -              } -          } -      } - -      // ----- Look for no rule, which means extract all the archive -      else { -          $v_extract = true; -      } - - -      // ----- Look for real extraction -      if ($v_extract) -      { - -        // ----- Go to the file position -        @rewind($this->_zip_fd); -        if (@fseek($this->_zip_fd, $v_header['offset'])) -        { -          // ----- Close the zip file -          $this->_closeFd(); - -          // ----- Error log -          $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); - -          // ----- Return -          return Archive_Zip::errorCode(); -        } - -        // ----- Look for extraction as string -        if ($p_params[ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING]) { - -          // ----- Extracting the file -          if (($v_result = $this->_extractFileAsString($v_header, $v_string)) != 1) -          { -            // ----- Close the zip file -            $this->_closeFd(); - -            return $v_result; -          } - -          // ----- Get the only interesting attributes -          if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) -          { -            // ----- Close the zip file -            $this->_closeFd(); - -            return $v_result; -          } - -          // ----- Set the file content -          $p_file_list[$v_nb_extracted]['content'] = $v_string; - -          // ----- Next extracted file -          $v_nb_extracted++; -        } -        else { -          // ----- Extracting the file -          if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1) -          { -            // ----- Close the zip file -            $this->_closeFd(); - -            return $v_result; -          } - -          // ----- Get the only interesting attributes -          if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) -          { -            // ----- Close the zip file -            $this->_closeFd(); - -            return $v_result; -          } -        } -      } -    } - -    // ----- Close the zip file -    $this->_closeFd(); - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _extractFile() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_extractFile() -  * -  * { Description } -  * -  */ -  function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params) -  { -    $v_result=1; - -    // ----- Read the file header -    if (($v_result = $this->_readFileHeader($v_header)) != 1) -    { -      // ----- Return -      return $v_result; -    } - - -    // ----- Check that the file header is coherent with $p_entry info -    // TBC - -    // ----- Look for all path to remove -    if ($p_remove_all_path == true) { -        // ----- Get the basename of the path -        $p_entry['filename'] = basename($p_entry['filename']); -    } - -    // ----- Look for path to remove -    else if ($p_remove_path != "") -    { -      //if (strcmp($p_remove_path, $p_entry['filename'])==0) -      if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2) -      { - -        // ----- Change the file status -        $p_entry['status'] = "filtered"; - -        // ----- Return -        return $v_result; -      } - -      $p_remove_path_size = strlen($p_remove_path); -      if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) -      { - -        // ----- Remove the path -        $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); - -      } -    } - -    // ----- Add the path -    if ($p_path != '') -    { -      $p_entry['filename'] = $p_path."/".$p_entry['filename']; -    } - -    // ----- Look for pre-extract callback -    if (   (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT])) -	    && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) { - -      // ----- Generate a local information -      $v_local_header = array(); -      $this->_convertHeader2FileInfo($p_entry, $v_local_header); - -      // ----- Call the callback -      // Here I do not use call_user_func() because I need to send a reference to the -      // header. -      eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT].'(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);'); -      if ($v_result == 0) { -        // ----- Change the file status -        $p_entry['status'] = "skipped"; -        $v_result = 1; -      } - -      // ----- Update the informations -      // Only some fields can be modified -      $p_entry['filename'] = $v_local_header['filename']; -    } - -    // ----- Trace - -    // ----- Look if extraction should be done -    if ($p_entry['status'] == 'ok') { - -    // ----- Look for specific actions while the file exist -    if (file_exists($p_entry['filename'])) -    { - -      // ----- Look if file is a directory -      if (is_dir($p_entry['filename'])) -      { - -        // ----- Change the file status -        $p_entry['status'] = "already_a_directory"; - -        // ----- Return -        //return $v_result; -      } -      // ----- Look if file is write protected -      else if (!is_writeable($p_entry['filename'])) -      { - -        // ----- Change the file status -        $p_entry['status'] = "write_protected"; - -        // ----- Return -        //return $v_result; -      } - -      // ----- Look if the extracted file is older -      else if (filemtime($p_entry['filename']) > $p_entry['mtime']) -      { - -        // ----- Change the file status -        $p_entry['status'] = "newer_exist"; - -        // ----- Return -        //return $v_result; -      } -    } - -    // ----- Check the directory availability and create it if necessary -    else { -      if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) -        $v_dir_to_check = $p_entry['filename']; -      else if (!strstr($p_entry['filename'], "/")) -        $v_dir_to_check = ""; -      else -        $v_dir_to_check = dirname($p_entry['filename']); - -      if (($v_result = $this->_dirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { - -        // ----- Change the file status -        $p_entry['status'] = "path_creation_fail"; - -        // ----- Return -        //return $v_result; -        $v_result = 1; -      } -    } -    } - -    // ----- Look if extraction should be done -    if ($p_entry['status'] == 'ok') { - -      // ----- Do the extraction (if not a folder) -      if (!(($p_entry['external']&0x00000010)==0x00000010)) -      { - -        // ----- Look for not compressed file -        if ($p_entry['compressed_size'] == $p_entry['size']) -        { - -          // ----- Opening destination file -          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) -          { - -            // ----- Change the file status -            $p_entry['status'] = "write_error"; - -            // ----- Return -            return $v_result; -          } - - -          // ----- Read the file by ARCHIVE_ZIP_READ_BLOCK_SIZE octets blocks -          $v_size = $p_entry['compressed_size']; -          while ($v_size != 0) -          { -            $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -            $v_buffer = fread($this->_zip_fd, $v_read_size); -            $v_binary_data = pack('a'.$v_read_size, $v_buffer); -            @fwrite($v_dest_file, $v_binary_data, $v_read_size); -            $v_size -= $v_read_size; -          } - -          // ----- Closing the destination file -          fclose($v_dest_file); - -          // ----- Change the file mtime -          touch($p_entry['filename'], $p_entry['mtime']); -        } -        else -        { -          // ----- Trace - -          // ----- Opening destination file -          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { - -            // ----- Change the file status -            $p_entry['status'] = "write_error"; - -            return $v_result; -          } - - -          // ----- Read the compressed file in a buffer (one shot) -          $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']); - -          // ----- Decompress the file -          $v_file_content = gzinflate($v_buffer); -          unset($v_buffer); - -          // ----- Write the uncompressed data -          @fwrite($v_dest_file, $v_file_content, $p_entry['size']); -          unset($v_file_content); - -          // ----- Closing the destination file -          @fclose($v_dest_file); - -          // ----- Change the file mtime -          touch($p_entry['filename'], $p_entry['mtime']); -        } - -        // ----- Look for chmod option -        if (   (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD])) -		    && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) { - -          // ----- Change the mode of the file -          chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]); -        } - -      } -    } - -    // ----- Look for post-extract callback -    if (   (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT])) -	    && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) { - -      // ----- Generate a local information -      $v_local_header = array(); -      $this->_convertHeader2FileInfo($p_entry, $v_local_header); - -      // ----- Call the callback -      // Here I do not use call_user_func() because I need to send a reference to the -      // header. -      eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT].'(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);'); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _extractFileAsString() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_extractFileAsString() -  * -  * { Description } -  * -  */ -  function _extractFileAsString(&$p_entry, &$p_string) -  { -    $v_result=1; - -    // ----- Read the file header -    $v_header = array(); -    if (($v_result = $this->_readFileHeader($v_header)) != 1) -    { -      // ----- Return -      return $v_result; -    } - - -    // ----- Check that the file header is coherent with $p_entry info -    // TBC - -    // ----- Trace - -    // ----- Do the extraction (if not a folder) -    if (!(($p_entry['external']&0x00000010)==0x00000010)) -    { -      // ----- Look for not compressed file -      if ($p_entry['compressed_size'] == $p_entry['size']) -      { -        // ----- Trace - -        // ----- Reading the file -        $p_string = fread($this->_zip_fd, $p_entry['compressed_size']); -      } -      else -      { -        // ----- Trace - -        // ----- Reading the file -        $v_data = fread($this->_zip_fd, $p_entry['compressed_size']); - -        // ----- Decompress the file -        $p_string = gzinflate($v_data); -      } - -      // ----- Trace -    } -    else { -        // TBC : error : can not extract a folder in a string -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _readFileHeader() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_readFileHeader() -  * -  * { Description } -  * -  */ -  function _readFileHeader(&$p_header) -  { -    $v_result=1; - -    // ----- Read the 4 bytes signature -    $v_binary_data = @fread($this->_zip_fd, 4); -    $v_data = unpack('Vid', $v_binary_data); - -    // ----- Check signature -    if ($v_data['id'] != 0x04034b50) -    { - -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Read the first 42 bytes of the header -    $v_binary_data = fread($this->_zip_fd, 26); - -    // ----- Look for invalid block size -    if (strlen($v_binary_data) != 26) -    { -      $p_header['filename'] = ""; -      $p_header['status'] = "invalid_header"; - -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Extract the values -    $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); - -    // ----- Get filename -    $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']); - -    // ----- Get extra_fields -    if ($v_data['extra_len'] != 0) { -      $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']); -    } -    else { -      $p_header['extra'] = ''; -    } - -    // ----- Extract properties -    $p_header['compression'] = $v_data['compression']; -    $p_header['size'] = $v_data['size']; -    $p_header['compressed_size'] = $v_data['compressed_size']; -    $p_header['crc'] = $v_data['crc']; -    $p_header['flag'] = $v_data['flag']; - -    // ----- Recuperate date in UNIX format -    $p_header['mdate'] = $v_data['mdate']; -    $p_header['mtime'] = $v_data['mtime']; -    if ($p_header['mdate'] && $p_header['mtime']) -    { -      // ----- Extract time -      $v_hour = ($p_header['mtime'] & 0xF800) >> 11; -      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; -      $v_seconde = ($p_header['mtime'] & 0x001F)*2; - -      // ----- Extract date -      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; -      $v_month = ($p_header['mdate'] & 0x01E0) >> 5; -      $v_day = $p_header['mdate'] & 0x001F; - -      // ----- Get UNIX date format -      $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); - -    } -    else -    { -      $p_header['mtime'] = time(); -    } - -    // ----- Other informations - -    // TBC -    //for(reset($v_data); $key = key($v_data); next($v_data)) { -    //} - -    // ----- Set the stored filename -    $p_header['stored_filename'] = $p_header['filename']; - -    // ----- Set the status field -    $p_header['status'] = "ok"; - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _readCentralFileHeader() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_readCentralFileHeader() -  * -  * { Description } -  * -  */ -  function _readCentralFileHeader(&$p_header) -  { -    $v_result=1; - -    // ----- Read the 4 bytes signature -    $v_binary_data = @fread($this->_zip_fd, 4); -    $v_data = unpack('Vid', $v_binary_data); - -    // ----- Check signature -    if ($v_data['id'] != 0x02014b50) -    { - -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Read the first 42 bytes of the header -    $v_binary_data = fread($this->_zip_fd, 42); - -    // ----- Look for invalid block size -    if (strlen($v_binary_data) != 42) -    { -      $p_header['filename'] = ""; -      $p_header['status'] = "invalid_header"; - -      // ----- Error log -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); - -      // ----- Return -      return Archive_Zip::errorCode(); -    } - -    // ----- Extract the values -    $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); - -    // ----- Get filename -    if ($p_header['filename_len'] != 0) -      $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']); -    else -      $p_header['filename'] = ''; - -    // ----- Get extra -    if ($p_header['extra_len'] != 0) -      $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']); -    else -      $p_header['extra'] = ''; - -    // ----- Get comment -    if ($p_header['comment_len'] != 0) -      $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']); -    else -      $p_header['comment'] = ''; - -    // ----- Extract properties - -    // ----- Recuperate date in UNIX format -    if ($p_header['mdate'] && $p_header['mtime']) -    { -      // ----- Extract time -      $v_hour = ($p_header['mtime'] & 0xF800) >> 11; -      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; -      $v_seconde = ($p_header['mtime'] & 0x001F)*2; - -      // ----- Extract date -      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; -      $v_month = ($p_header['mdate'] & 0x01E0) >> 5; -      $v_day = $p_header['mdate'] & 0x001F; - -      // ----- Get UNIX date format -      $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); - -    } -    else -    { -      $p_header['mtime'] = time(); -    } - -    // ----- Set the stored filename -    $p_header['stored_filename'] = $p_header['filename']; - -    // ----- Set default status to ok -    $p_header['status'] = 'ok'; - -    // ----- Look if it is a directory -    if (substr($p_header['filename'], -1) == '/') -    { -      $p_header['external'] = 0x41FF0010; -    } - - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _readEndCentralDir() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_readEndCentralDir() -  * -  * { Description } -  * -  */ -  function _readEndCentralDir(&$p_central_dir) -  { -    $v_result=1; - -    // ----- Go to the end of the zip file -    $v_size = filesize($this->_zipname); -    @fseek($this->_zip_fd, $v_size); -    if (@ftell($this->_zip_fd) != $v_size) { -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, -	                   'Unable to go to the end of the archive \'' -					   .$this->_zipname.'\''); -      return Archive_Zip::errorCode(); -    } - -    // ----- First try : look if this is an archive with no commentaries -	// (most of the time) -    // in this case the end of central dir is at 22 bytes of the file end -    $v_found = 0; -    if ($v_size > 26) { -      @fseek($this->_zip_fd, $v_size-22); -      if (($v_pos = @ftell($this->_zip_fd)) != ($v_size-22)) { -        $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, -		                 'Unable to seek back to the middle of the archive \'' -						 .$this->_zipname.'\''); -        return Archive_Zip::errorCode(); -      } - -      // ----- Read for bytes -      $v_binary_data = @fread($this->_zip_fd, 4); -      $v_data = unpack('Vid', $v_binary_data); - -      // ----- Check signature -      if ($v_data['id'] == 0x06054b50) { -        $v_found = 1; -      } - -      $v_pos = ftell($this->_zip_fd); -    } - -    // ----- Go back to the maximum possible size of the Central Dir End Record -    if (!$v_found) { -      $v_maximum_size = 65557; // 0xFFFF + 22; -      if ($v_maximum_size > $v_size) -        $v_maximum_size = $v_size; -      @fseek($this->_zip_fd, $v_size-$v_maximum_size); -      if (@ftell($this->_zip_fd) != ($v_size-$v_maximum_size)) { -        $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, -		                 'Unable to seek back to the middle of the archive \'' -						 .$this->_zipname.'\''); -        return Archive_Zip::errorCode(); -      } - -      // ----- Read byte per byte in order to find the signature -      $v_pos = ftell($this->_zip_fd); -      $v_bytes = 0x00000000; -      while ($v_pos < $v_size) { -        // ----- Read a byte -        $v_byte = @fread($this->_zip_fd, 1); - -        // -----  Add the byte -        $v_bytes = ($v_bytes << 8) | Ord($v_byte); - -        // ----- Compare the bytes -        if ($v_bytes == 0x504b0506) { -          $v_pos++; -          break; -        } - -        $v_pos++; -      } - -      // ----- Look if not found end of central dir -      if ($v_pos == $v_size) { -        $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, -		                 "Unable to find End of Central Dir Record signature"); -        return Archive_Zip::errorCode(); -      } -    } - -    // ----- Read the first 18 bytes of the header -    $v_binary_data = fread($this->_zip_fd, 18); - -    // ----- Look for invalid block size -    if (strlen($v_binary_data) != 18) { -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, -	                   "Invalid End of Central Dir Record size : " -					   .strlen($v_binary_data)); -      return Archive_Zip::errorCode(); -    } - -    // ----- Extract the values -    $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); - -    // ----- Check the global size -    if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { -      $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, -	                   "Fail to find the right signature"); -      return Archive_Zip::errorCode(); -    } - -    // ----- Get comment -    if ($v_data['comment_size'] != 0) -      $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']); -    else -      $p_central_dir['comment'] = ''; - -    $p_central_dir['entries'] = $v_data['entries']; -    $p_central_dir['disk_entries'] = $v_data['disk_entries']; -    $p_central_dir['offset'] = $v_data['offset']; -    $p_central_dir['size'] = $v_data['size']; -    $p_central_dir['disk'] = $v_data['disk']; -    $p_central_dir['disk_start'] = $v_data['disk_start']; - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _deleteByRule() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_deleteByRule() -  * -  * { Description } -  * -  */ -  function _deleteByRule(&$p_result_list, &$p_params) -  { -    $v_result=1; -    $v_list_detail = array(); - -    // ----- Open the zip file -    if (($v_result=$this->_openFd('rb')) != 1) -    { -      // ----- Return -      return $v_result; -    } - -    // ----- Read the central directory informations -    $v_central_dir = array(); -    if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) -    { -      $this->_closeFd(); -      return $v_result; -    } - -    // ----- Go to beginning of File -    @rewind($this->_zip_fd); - -    // ----- Scan all the files -    // ----- Start at beginning of Central Dir -    $v_pos_entry = $v_central_dir['offset']; -    @rewind($this->_zip_fd); -    if (@fseek($this->_zip_fd, $v_pos_entry)) { -      // ----- Clean -      $this->_closeFd(); - -      $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, -	                   'Invalid archive size'); -      return Archive_Zip::errorCode(); -    } - -    // ----- Read each entry -    $v_header_list = array(); -    $j_start = 0; -    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) { - -      // ----- Read the file header -      $v_header_list[$v_nb_extracted] = array(); -      $v_result -	    = $this->_readCentralFileHeader($v_header_list[$v_nb_extracted]); -      if ($v_result != 1) { -        // ----- Clean -        $this->_closeFd(); - -        return $v_result; -      } - -      // ----- Store the index -      $v_header_list[$v_nb_extracted]['index'] = $i; - -      // ----- Look for the specific extract rules -      $v_found = false; - -      // ----- Look for extract by name rule -      if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) -          && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) { - -          // ----- Look if the filename is in the list -          for ($j=0; -		       ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) -			     && (!$v_found); -			   $j++) { - -              // ----- Look for a directory -              if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == "/") { - -                  // ----- Look if the directory is in the filename path -                  if (   (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) -                      && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) { -                      $v_found = true; -                  } -                  elseif (   (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ -                          && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) { -                      $v_found = true; -                  } -              } -              // ----- Look for a filename -              elseif ($v_header_list[$v_nb_extracted]['stored_filename'] -			          == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) { -                  $v_found = true; -              } -          } -      } - -      // ----- Look for extract by ereg rule -      else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG])) -               && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != "")) { - -          if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG], -		           $v_header_list[$v_nb_extracted]['stored_filename'])) { -              $v_found = true; -          } -      } - -      // ----- Look for extract by preg rule -      else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG])) -               && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != "")) { - -          if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], -		                 $v_header_list[$v_nb_extracted]['stored_filename'])) { -              $v_found = true; -          } -      } - -      // ----- Look for extract by index rule -      else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) -               && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) { - -          // ----- Look if the index is in the list -          for ($j=$j_start; -		       ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) -			     && (!$v_found); -			   $j++) { - -              if (   ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) -			      && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) { -                  $v_found = true; -              } -              if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) { -                  $j_start = $j+1; -              } - -              if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) { -                  break; -              } -          } -      } - -      // ----- Look for deletion -      if ($v_found) { -        unset($v_header_list[$v_nb_extracted]); -      } -      else { -        $v_nb_extracted++; -      } -    } - -    // ----- Look if something need to be deleted -    if ($v_nb_extracted > 0) { - -        // ----- Creates a temporay file -        $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-') -		                   .'.tmp'; - -        // ----- Creates a temporary zip archive -        $v_temp_zip = new Archive_Zip($v_zip_temp_name); - -        // ----- Open the temporary zip file in write mode -        if (($v_result = $v_temp_zip->_openFd('wb')) != 1) { -            $this->_closeFd(); - -            // ----- Return -            return $v_result; -        } - -        // ----- Look which file need to be kept -        for ($i=0; $i<sizeof($v_header_list); $i++) { - -            // ----- Calculate the position of the header -            @rewind($this->_zip_fd); -            if (@fseek($this->_zip_fd,  $v_header_list[$i]['offset'])) { -                // ----- Clean -                $this->_closeFd(); -                $v_temp_zip->_closeFd(); -                @unlink($v_zip_temp_name); - -                $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, -				                 'Invalid archive size'); -                return Archive_Zip::errorCode(); -            } - -            // ----- Read the file header -            if (($v_result = $this->_readFileHeader($v_header_list[$i])) != 1) { -                // ----- Clean -                $this->_closeFd(); -                $v_temp_zip->_closeFd(); -                @unlink($v_zip_temp_name); - -                return $v_result; -            } - -            // ----- Write the file header -            $v_result = $v_temp_zip->_writeFileHeader($v_header_list[$i]); -            if ($v_result != 1) { -                // ----- Clean -                $this->_closeFd(); -                $v_temp_zip->_closeFd(); -                @unlink($v_zip_temp_name); - -                return $v_result; -            } - -            // ----- Read/write the data block -            $v_result = $this->_tool_CopyBlock($this->_zip_fd, -			                                   $v_temp_zip->_zip_fd, -								       $v_header_list[$i]['compressed_size']); -            if ($v_result != 1) { -                // ----- Clean -                $this->_closeFd(); -                $v_temp_zip->_closeFd(); -                @unlink($v_zip_temp_name); - -                return $v_result; -            } -        } - -        // ----- Store the offset of the central dir -        $v_offset = @ftell($v_temp_zip->_zip_fd); - -        // ----- Re-Create the Central Dir files header -        for ($i=0; $i<sizeof($v_header_list); $i++) { -            // ----- Create the file header -            $v_result=$v_temp_zip->_writeCentralFileHeader($v_header_list[$i]); -            if ($v_result != 1) { -            	// ----- Clean -                $v_temp_zip->_closeFd(); -                $this->_closeFd(); -                @unlink($v_zip_temp_name); - -                return $v_result; -            } - -            // ----- Transform the header to a 'usable' info -            $v_temp_zip->_convertHeader2FileInfo($v_header_list[$i], -			                                     $p_result_list[$i]); -        } - - -        // ----- Zip file comment -        $v_comment = ''; - -        // ----- Calculate the size of the central header -        $v_size = @ftell($v_temp_zip->_zip_fd)-$v_offset; - -        // ----- Create the central dir footer -        $v_result = $v_temp_zip->_writeCentralHeader(sizeof($v_header_list), -		                                             $v_size, $v_offset, -													 $v_comment); -        if ($v_result != 1) { -            // ----- Clean -            unset($v_header_list); -            $v_temp_zip->_closeFd(); -            $this->_closeFd(); -            @unlink($v_zip_temp_name); - -            return $v_result; -        } - -        // ----- Close -        $v_temp_zip->_closeFd(); -        $this->_closeFd(); - -        // ----- Delete the zip file -        // TBC : I should test the result ... -        @unlink($this->_zipname); - -        // ----- Rename the temporary file -        // TBC : I should test the result ... -        //@rename($v_zip_temp_name, $this->_zipname); -        $this->_tool_Rename($v_zip_temp_name, $this->_zipname); - -        // ----- Destroy the temporary archive -        unset($v_temp_zip); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _dirCheck() -  // Description : -  //   Check if a directory exists, if not it creates it and all the parents directory -  //   which may be useful. -  // Parameters : -  //   $p_dir : Directory path to check. -  // Return Values : -  //    1 : OK -  //   -1 : Unable to create directory -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_dirCheck() -  * -  * { Description } -  * -  * @param [type] $p_is_dir -  */ -  function _dirCheck($p_dir, $p_is_dir=false) -  { -    $v_result = 1; - -    // ----- Remove the final '/' -    if (($p_is_dir) && (substr($p_dir, -1)=='/')) { -      $p_dir = substr($p_dir, 0, strlen($p_dir)-1); -    } - -    // ----- Check the directory availability -    if ((is_dir($p_dir)) || ($p_dir == "")) { -      return 1; -    } - -    // ----- Extract parent directory -    $p_parent_dir = dirname($p_dir); - -    // ----- Just a check -    if ($p_parent_dir != $p_dir) { -      // ----- Look for parent directory -      if ($p_parent_dir != "") { -        if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) { -          return $v_result; -        } -      } -    } - -    // ----- Create the directory -    if (!@mkdir($p_dir, 0777)) { -      $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL, -	                   "Unable to create directory '$p_dir'"); -      return Archive_Zip::errorCode(); -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _merge() -  // Description : -  //   If $p_archive_to_add does not exist, the function exit with a success result. -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_merge() -  * -  * { Description } -  * -  */ -  function _merge(&$p_archive_to_add) -  { -    $v_result=1; - -    // ----- Look if the archive_to_add exists -    if (!is_file($p_archive_to_add->_zipname)) { -      // ----- Nothing to merge, so merge is a success -      return 1; -    } - -    // ----- Look if the archive exists -    if (!is_file($this->_zipname)) { -      // ----- Do a duplicate -      $v_result = $this->_duplicate($p_archive_to_add->_zipname); - -      return $v_result; -    } - -    // ----- Open the zip file -    if (($v_result=$this->_openFd('rb')) != 1) { -      return $v_result; -    } - -    // ----- Read the central directory informations -    $v_central_dir = array(); -    if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { -      $this->_closeFd(); -      return $v_result; -    } - -    // ----- Go to beginning of File -    @rewind($this->_zip_fd); - -    // ----- Open the archive_to_add file -    if (($v_result=$p_archive_to_add->_openFd('rb')) != 1) { -      $this->_closeFd(); -      return $v_result; -    } - -    // ----- Read the central directory informations -    $v_central_dir_to_add = array(); -    $v_result = $p_archive_to_add->_readEndCentralDir($v_central_dir_to_add); -    if ($v_result != 1) { -      $this->_closeFd(); -      $p_archive_to_add->_closeFd(); -      return $v_result; -    } - -    // ----- Go to beginning of File -    @rewind($p_archive_to_add->_zip_fd); - -    // ----- Creates a temporay file -    $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp'; - -    // ----- Open the temporary file in write mode -    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { -      $this->_closeFd(); -      $p_archive_to_add->_closeFd(); -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -	                   'Unable to open temporary file \'' -					   .$v_zip_temp_name.'\' in binary write mode'); -      return Archive_Zip::errorCode(); -    } - -    // ----- Copy the files from the archive to the temporary file -    // TBC : Here I should better append the file and go back to erase the -	// central dir -    $v_size = $v_central_dir['offset']; -    while ($v_size != 0) { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = fread($this->_zip_fd, $v_read_size); -      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Copy the files from the archive_to_add into the temporary file -    $v_size = $v_central_dir_to_add['offset']; -    while ($v_size != 0) { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = fread($p_archive_to_add->_zip_fd, $v_read_size); -      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Store the offset of the central dir -    $v_offset = @ftell($v_zip_temp_fd); - -    // ----- Copy the block of file headers from the old archive -    $v_size = $v_central_dir['size']; -    while ($v_size != 0) { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = @fread($this->_zip_fd, $v_read_size); -      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Copy the block of file headers from the archive_to_add -    $v_size = $v_central_dir_to_add['size']; -    while ($v_size != 0) { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = @fread($p_archive_to_add->_zip_fd, $v_read_size); -      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Zip file comment -    // TBC : I should merge the two comments -    $v_comment = ''; - -    // ----- Calculate the size of the (new) central header -    $v_size = @ftell($v_zip_temp_fd)-$v_offset; - -    // ----- Swap the file descriptor -    // Here is a trick : I swap the temporary fd with the zip fd, in order to use -    // the following methods on the temporary fil and not the real archive fd -    $v_swap = $this->_zip_fd; -    $this->_zip_fd = $v_zip_temp_fd; -    $v_zip_temp_fd = $v_swap; - -    // ----- Create the central dir footer -    if (($v_result = $this->_writeCentralHeader($v_central_dir['entries'] -	                                          +$v_central_dir_to_add['entries'], -												$v_size, $v_offset, -												$v_comment)) != 1) { -      $this->_closeFd(); -      $p_archive_to_add->_closeFd(); -      @fclose($v_zip_temp_fd); -      $this->_zip_fd = null; - -      // ----- Reset the file list -      unset($v_header_list); - -      // ----- Return -      return $v_result; -    } - -    // ----- Swap back the file descriptor -    $v_swap = $this->_zip_fd; -    $this->_zip_fd = $v_zip_temp_fd; -    $v_zip_temp_fd = $v_swap; - -    // ----- Close -    $this->_closeFd(); -    $p_archive_to_add->_closeFd(); - -    // ----- Close the temporary file -    @fclose($v_zip_temp_fd); - -    // ----- Delete the zip file -    // TBC : I should test the result ... -    @unlink($this->_zipname); - -    // ----- Rename the temporary file -    // TBC : I should test the result ... -    //@rename($v_zip_temp_name, $this->_zipname); -    $this->_tool_Rename($v_zip_temp_name, $this->_zipname); - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _duplicate() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_duplicate() -  * -  * { Description } -  * -  */ -  function _duplicate($p_archive_filename) -  { -    $v_result=1; - -    // ----- Look if the $p_archive_filename exists -    if (!is_file($p_archive_filename)) { - -      // ----- Nothing to duplicate, so duplicate is a success. -      $v_result = 1; - -      // ----- Return -      return $v_result; -    } - -    // ----- Open the zip file -    if (($v_result=$this->_openFd('wb')) != 1) { -      // ----- Return -      return $v_result; -    } - -    // ----- Open the temporary file in write mode -    if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) { -      $this->_closeFd(); -      $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, -	                   'Unable to open archive file \'' -					   .$p_archive_filename.'\' in binary write mode'); -      return Archive_Zip::errorCode(); -    } - -    // ----- Copy the files from the archive to the temporary file -    // TBC : Here I should better append the file and go back to erase the -	// central dir -    $v_size = filesize($p_archive_filename); -    while ($v_size != 0) { -      $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -      $v_buffer = fread($v_zip_temp_fd, $v_read_size); -      @fwrite($this->_zip_fd, $v_buffer, $v_read_size); -      $v_size -= $v_read_size; -    } - -    // ----- Close -    $this->_closeFd(); - -    // ----- Close the temporary file -    @fclose($v_zip_temp_fd); - -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  /** -  * Archive_Zip::_check_parameters() -  * -  * { Description } -  * -  * @param integer $p_error_code -  * @param string $p_error_string -  */ -  function _check_parameters(&$p_params, $p_default) -  { -     -    // ----- Check that param is an array -    if (!is_array($p_params)) { -        $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -		                 'Unsupported parameter, waiting for an array'); -        return Archive_Zip::errorCode(); -    } -     -    // ----- Check that all the params are valid -    for (reset($p_params); list($v_key, $v_value) = each($p_params); ) { -    	if (!isset($p_default[$v_key])) { -            $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, -			                 'Unsupported parameter with key \''.$v_key.'\''); - -            return Archive_Zip::errorCode(); -    	} -    } - -	// ----- Set the default values -    for (reset($p_default); list($v_key, $v_value) = each($p_default); ) { -    	if (!isset($p_params[$v_key])) { -    		$p_params[$v_key] = $p_default[$v_key]; -    	} -    } -     -    // ----- Check specific parameters -    $v_callback_list = array ('callback_pre_add','callback_post_add', -	                          'callback_pre_extract','callback_post_extract'); -    for ($i=0; $i<sizeof($v_callback_list); $i++) { -    	$v_key=$v_callback_list[$i]; -        if (   (isset($p_params[$v_key])) && ($p_params[$v_key] != '')) { -            if (!function_exists($p_params[$v_key])) { -                $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE, -				                 "Callback '".$p_params[$v_key] -								 ."()' is not an existing function for " -								 ."parameter '".$v_key."'"); -                return Archive_Zip::errorCode(); -            } -	    } -    } - -    return(1); -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _errorLog() -  // Description : -  // Parameters : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_errorLog() -  * -  * { Description } -  * -  * @param integer $p_error_code -  * @param string $p_error_string -  */ -  function _errorLog($p_error_code=0, $p_error_string='') -  { -      $this->_error_code = $p_error_code; -      $this->_error_string = $p_error_string; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : _errorReset() -  // Description : -  // Parameters : -  // --------------------------------------------------------------------------- -  /** -  * Archive_Zip::_errorReset() -  * -  * { Description } -  * -  */ -  function _errorReset() -  { -      $this->_error_code = 1; -      $this->_error_string = ''; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : $this->_tool_PathReduction() -  // Description : -  // Parameters : -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * _tool_PathReduction() -  * -  * { Description } -  * -  */ -  function _tool_PathReduction($p_dir) -  { -    $v_result = ""; - -    // ----- Look for not empty path -    if ($p_dir != "") -    { -      // ----- Explode path by directory names -      $v_list = explode("/", $p_dir); - -      // ----- Study directories from last to first -      for ($i=sizeof($v_list)-1; $i>=0; $i--) -      { -        // ----- Look for current path -        if ($v_list[$i] == ".") -        { -          // ----- Ignore this directory -          // Should be the first $i=0, but no check is done -        } -        else if ($v_list[$i] == "..") -        { -          // ----- Ignore it and ignore the $i-1 -          $i--; -        } -        else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0)) -        { -          // ----- Ignore only the double '//' in path, -          // but not the first and last '/' -        } -        else -        { -          $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); -        } -      } -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : $this->_tool_PathInclusion() -  // Description : -  //   This function indicates if the path $p_path is under the $p_dir tree. Or, -  //   said in an other way, if the file or sub-dir $p_path is inside the dir -  //   $p_dir. -  //   The function indicates also if the path is exactly the same as the dir. -  //   This function supports path with duplicated '/' like '//', but does not -  //   support '.' or '..' statements. -  // Parameters : -  // Return Values : -  //   0 if $p_path is not inside directory $p_dir -  //   1 if $p_path is inside directory $p_dir -  //   2 if $p_path is exactly the same as $p_dir -  // --------------------------------------------------------------------------- -  /** -  * _tool_PathInclusion() -  * -  * { Description } -  * -  */ -  function _tool_PathInclusion($p_dir, $p_path) -  { -    $v_result = 1; - -    // ----- Explode dir and path by directory separator -    $v_list_dir = explode("/", $p_dir); -    $v_list_dir_size = sizeof($v_list_dir); -    $v_list_path = explode("/", $p_path); -    $v_list_path_size = sizeof($v_list_path); - -    // ----- Study directories paths -    $i = 0; -    $j = 0; -    while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { - -      // ----- Look for empty dir (path reduction) -      if ($v_list_dir[$i] == '') { -        $i++; -        continue; -      } -      if ($v_list_path[$j] == '') { -        $j++; -        continue; -      } - -      // ----- Compare the items -      if (   ($v_list_dir[$i] != $v_list_path[$j]) -	      && ($v_list_dir[$i] != '') -		  && ( $v_list_path[$j] != ''))  { -        $v_result = 0; -      } - -      // ----- Next items -      $i++; -      $j++; -    } - -    // ----- Look if everything seems to be the same -    if ($v_result) { -      // ----- Skip all the empty items -      while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; -      while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; - -      if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { -        // ----- There are exactly the same -        $v_result = 2; -      } -      else if ($i < $v_list_dir_size) { -        // ----- The path is shorter than the dir -        $v_result = 0; -      } -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : $this->_tool_CopyBlock() -  // Description : -  // Parameters : -  //   $p_mode : read/write compression mode -  //             0 : src & dest normal -  //             1 : src gzip, dest normal -  //             2 : src normal, dest gzip -  //             3 : src & dest gzip -  // Return Values : -  // --------------------------------------------------------------------------- -  /** -  * _tool_CopyBlock() -  * -  * { Description } -  * -  * @param integer $p_mode -  */ -  function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode=0) -  { -    $v_result = 1; - -    if ($p_mode==0) -    { -      while ($p_size != 0) -      { -        $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -        $v_buffer = @fread($p_src, $v_read_size); -        @fwrite($p_dest, $v_buffer, $v_read_size); -        $p_size -= $v_read_size; -      } -    } -    else if ($p_mode==1) -    { -      while ($p_size != 0) -      { -        $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -        $v_buffer = @gzread($p_src, $v_read_size); -        @fwrite($p_dest, $v_buffer, $v_read_size); -        $p_size -= $v_read_size; -      } -    } -    else if ($p_mode==2) -    { -      while ($p_size != 0) -      { -        $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -        $v_buffer = @fread($p_src, $v_read_size); -        @gzwrite($p_dest, $v_buffer, $v_read_size); -        $p_size -= $v_read_size; -      } -    } -    else if ($p_mode==3) -    { -      while ($p_size != 0) -      { -        $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE -		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); -        $v_buffer = @gzread($p_src, $v_read_size); -        @gzwrite($p_dest, $v_buffer, $v_read_size); -        $p_size -= $v_read_size; -      } -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : $this->_tool_Rename() -  // Description : -  //   This function tries to do a simple rename() function. If it fails, it -  //   tries to copy the $p_src file in a new $p_dest file and then unlink the -  //   first one. -  // Parameters : -  //   $p_src : Old filename -  //   $p_dest : New filename -  // Return Values : -  //   1 on success, 0 on failure. -  // --------------------------------------------------------------------------- -  /** -  * _tool_Rename() -  * -  * { Description } -  * -  */ -  function _tool_Rename($p_src, $p_dest) -  { -    $v_result = 1; - -    // ----- Try to rename the files -    if (!@rename($p_src, $p_dest)) { - -      // ----- Try to copy & unlink the src -      if (!@copy($p_src, $p_dest)) { -        $v_result = 0; -      } -      else if (!@unlink($p_src)) { -        $v_result = 0; -      } -    } - -    // ----- Return -    return $v_result; -  } -  // --------------------------------------------------------------------------- - -  // --------------------------------------------------------------------------- -  // Function : $this->_tool_TranslateWinPath() -  // Description : -  //   Translate windows path by replacing '\' by '/' and optionally removing -  //   drive letter. -  // Parameters : -  //   $p_path : path to translate. -  //   $p_remove_disk_letter : true | false -  // Return Values : -  //   The path translated. -  // --------------------------------------------------------------------------- -  /** -  * _tool_TranslateWinPath() -  * -  * { Description } -  * -  * @param [type] $p_remove_disk_letter -  */ -  function _tool_TranslateWinPath($p_path, $p_remove_disk_letter=true) -  { -    if (stristr(php_uname(), 'windows')) { -      // ----- Look for potential disk letter -      if (   ($p_remove_disk_letter) -	      && (($v_position = strpos($p_path, ':')) != false)) { -          $p_path = substr($p_path, $v_position+1); -      } -      // ----- Change potential windows directory separator -      if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { -          $p_path = strtr($p_path, '\\', '/'); -      } -    } -    return $p_path; -  } -  // --------------------------------------------------------------------------- - -  } -  // End of class - -?> diff --git a/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php b/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php index 00b0a7a9..fc12c9d2 100644..100755 --- a/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php +++ b/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: AnsiColorLogger.php,v 1.13 2005/05/26 13:10:51 mrook Exp $ + * $Id: bea608bad3f8bd5733c7eac6451d15b1c937115c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -42,8 +42,8 @@ include_once 'phing/system/util/Properties.php';   *   * The default colors used for differentiating   * the message levels can be changed by editing the - * /org/apache/tools/ant/listener/defaults.properties - * file. + * phing/listener/defaults.properties file. + *   * This file contains 5 key/value pairs:   * AnsiColorLogger.ERROR_COLOR=2;31   * AnsiColorLogger.WARNING_COLOR=2;35 @@ -95,9 +95,9 @@ include_once 'phing/system/util/Properties.php';   * @author     Hans Lellelid <hans@xmpl.org> (Phing)   * @author     Magesh Umasankar (Ant)   * @package    phing.listener - * @version    $Revision: 1.13 $ + * @version    $Id$   */ -final class AnsiColorLogger extends DefaultLogger { +class AnsiColorLogger extends DefaultLogger {      const ATTR_NORMAL = 0;      const ATTR_BRIGHT = 1; @@ -144,11 +144,11 @@ final class AnsiColorLogger extends DefaultLogger {       */      public function __construct() {          parent::__construct(); -        $this->errColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_RED . self::SUFFIX; -        $this->warnColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_MAGENTA . self::SUFFIX; -        $this->infoColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_CYAN . self::SUFFIX; -        $this->verboseColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_GREEN . self::SUFFIX; -        $this->debugColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_BLUE . self::SUFFIX; +        $this->errColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_RED . self::SUFFIX; +        $this->warnColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_MAGENTA . self::SUFFIX; +        $this->infoColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_CYAN . self::SUFFIX; +        $this->verboseColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_GREEN . self::SUFFIX; +        $this->debugColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_BLUE . self::SUFFIX;      }      /** @@ -177,19 +177,19 @@ final class AnsiColorLogger extends DefaultLogger {              $verbose = $prop->getProperty("AnsiColorLogger.VERBOSE_COLOR");              $debug = $prop->getProperty("AnsiColorLogger.DEBUG_COLOR");              if ($err !== null) { -                $errColor = self::PREFIX . $err . self::SUFFIX; +                $this->errColor = self::PREFIX . $err . self::SUFFIX;              }              if ($warn !== null) { -                $warnColor = self::PREFIX . $warn . self::SUFFIX; +                $this->warnColor = self::PREFIX . $warn . self::SUFFIX;              }              if ($info !== null) { -                $infoColor = self::PREFIX . $info . self::SUFFIX; +                $this->infoColor = self::PREFIX . $info . self::SUFFIX;              }              if ($verbose !== null) { -                $verboseColor = self::PREFIX . $verbose . self::SUFFIX; +                $this->verboseColor = self::PREFIX . $verbose . self::SUFFIX;              }              if ($debug !== null) { -                $debugColor = self::PREFIX . $debug . self::SUFFIX; +                $this->debugColor = self::PREFIX . $debug . self::SUFFIX;              }          } catch (IOException $ioe) {              //Ignore exception - we will use the defaults. @@ -198,9 +198,11 @@ final class AnsiColorLogger extends DefaultLogger {      /**       * @see DefaultLogger#printMessage +     * @param string $message +     * @param OutputStream $stream +     * @param int $priority       */ -    protected final function printMessage($message, $priority) { -     +    protected final function printMessage($message, OutputStream $stream, $priority) {          if ($message !== null) {              if (!$this->colorsSet) { @@ -209,23 +211,24 @@ final class AnsiColorLogger extends DefaultLogger {              }              switch ($priority) { -                case PROJECT_MSG_ERR: +                case Project::MSG_ERR:                      $message = $this->errColor . $message . self::END_COLOR;                      break; -                case PROJECT_MSG_WARN: +                case Project::MSG_WARN:                      $message = $this->warnColor . $message . self::END_COLOR;                                          break; -                case PROJECT_MSG_INFO: +                case Project::MSG_INFO:                      $message = $this->infoColor . $message . self::END_COLOR;                      break; -                case PROJECT_MSG_VERBOSE: +                case Project::MSG_VERBOSE:                      $message = $this->verboseColor . $message . self::END_COLOR;                      break; -                case PROJECT_MSG_DEBUG: +                case Project::MSG_DEBUG:                      $message = $this->debugColor . $message . self::END_COLOR;                      break;              } -            print($message."\n"); +             +            $stream->write($message . PHP_EOL);          }      }  } diff --git a/buildscripts/phing/classes/phing/listener/BuildLogger.php b/buildscripts/phing/classes/phing/listener/BuildLogger.php deleted file mode 100644 index d1c5fcb6..00000000 --- a/buildscripts/phing/classes/phing/listener/BuildLogger.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -	/** -	 * $Id: BuildLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $ -	 * -	 * 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/BuildListener.php'; -	/** -	 * Interface used by Phing Ant to log the build output. -	 * -	 * @author Michiel Rook <michiel@trendserver.nl> -	 * @version $Id: BuildLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $ -	 * @package phing.listener -	 */ -	interface BuildLogger extends BuildListener -	{ -		/** -		 * Sets the highest level of message this logger should respond to. -		 * -		 * Only messages with a message level lower than or equal to the -		 * given level should be written to the log. -		 * -		 * @param int the logging level for the logger. -		 */ -		function setMessageOutputLevel($level); -	}; -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/listener/DefaultLogger.php b/buildscripts/phing/classes/phing/listener/DefaultLogger.php index c7387592..31051a75 100644..100755 --- a/buildscripts/phing/classes/phing/listener/DefaultLogger.php +++ b/buildscripts/phing/classes/phing/listener/DefaultLogger.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: DefaultLogger.php,v 1.11 2005/08/25 19:33:43 hlellelid Exp $ + *  $Id: e7f902228f55a3be17b42eed785137cb97e7a29e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,7 +19,7 @@   * <http://phing.info>.   */ -require_once 'phing/BuildListener.php'; +require_once 'phing/listener/StreamRequiredBuildLogger.php';  include_once 'phing/BuildEvent.php';  /** @@ -29,12 +29,12 @@ include_once 'phing/BuildEvent.php';   *  any messages that get logged.   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.11 $ $Date: 2005/08/25 19:33:43 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @see       BuildEvent   *  @package   phing.listener   */ -class DefaultLogger implements BuildListener { +class DefaultLogger implements StreamRequiredBuildLogger {      /**       *  Size of the left column in output. The default char width is 12. @@ -44,29 +44,32 @@ class DefaultLogger implements BuildListener {      /**       *  The message output level that should be used. The default is -     *  <code>PROJECT_MSG_VERBOSE</code>. +     *  <code>Project::MSG_VERBOSE</code>.       *  @var int       */ -    protected $msgOutputLevel = PROJECT_MSG_ERR; +    protected $msgOutputLevel = Project::MSG_ERR;      /**       *  Time that the build started       *  @var int       */      protected $startTime; - +     +    /** +     * @var OutputStream Stream to use for standard output. +     */ +    protected $out; +          /** -     *  Char that should be used to seperate lines. Default is the system -     *  property <em>line.seperator</em>. -     *  @var string +     * @var OutputStream Stream to use for error output.       */ -    protected $lSep; +    protected $err;      /**       *  Construct a new default logger.       */      public function __construct() { -        $this->lSep = Phing::getProperty("line.separator"); +              }      /** @@ -79,22 +82,40 @@ class DefaultLogger implements BuildListener {       *  the levels, from least to most verbose, is:       *       *  <ul> -     *    <li>PROJECT_MSG_ERR</li> -     *    <li>PROJECT_MSG_WARN</li> -     *    <li>PROJECT_MSG_INFO</li> -     *    <li>PROJECT_MSG_VERBOSE</li> -     *    <li>PROJECT_MSG_DEBUG</li> +     *    <li>Project::MSG_ERR</li> +     *    <li>Project::MSG_WARN</li> +     *    <li>Project::MSG_INFO</li> +     *    <li>Project::MSG_VERBOSE</li> +     *    <li>Project::MSG_DEBUG</li>       *  </ul>       * -     *  The default message level for DefaultLogger is PROJECT_MSG_ERR. +     *  The default message level for DefaultLogger is Project::MSG_ERR.       * -     *  @param  integer  the logging level for the logger. -     *  @access public +     * @param int $level The logging level for the logger. +     * @see BuildLogger#setMessageOutputLevel()       */ -    function setMessageOutputLevel($level) { +    public function setMessageOutputLevel($level) {          $this->msgOutputLevel = (int) $level;      } - +     +    /** +     * Sets the output stream. +     * @param OutputStream $output +     * @see BuildLogger#setOutputStream() +     */ +    public function setOutputStream(OutputStream $output) { +        $this->out = $output; +    } +     +    /** +     * Sets the error stream. +     * @param OutputStream $err +     * @see BuildLogger#setErrorStream() +     */ +    public function setErrorStream(OutputStream $err) { +        $this->err = $err; +    } +          /**      *  Sets the start-time when the build started. Used for calculating      *  the build-time. @@ -102,11 +123,10 @@ class DefaultLogger implements BuildListener {      *  @param  object  The BuildEvent      *  @access public      */ - -    function buildStarted(BuildEvent $event) { +    public function buildStarted(BuildEvent $event) {          $this->startTime = Phing::currentTimeMillis(); -        if ($this->msgOutputLevel >= PROJECT_MSG_INFO) { -            $this->printMessage("Buildfile: ".$event->getProject()->getProperty("phing.file"), PROJECT_MSG_INFO); +        if ($this->msgOutputLevel >= Project::MSG_INFO) { +            $this->printMessage("Buildfile: ".$event->getProject()->getProperty("phing.file"), $this->out, Project::MSG_INFO);          }      } @@ -115,34 +135,57 @@ class DefaultLogger implements BuildListener {       *  occured during the build. Also outputs the total build-time.       *       *  @param  object  The BuildEvent -     *  @access public       *  @see    BuildEvent::getException()       */ -    function buildFinished(BuildEvent $event) { +    public function buildFinished(BuildEvent $event) {          $error = $event->getException();          if ($error === null) { -            print($this->lSep . "BUILD FINISHED" . $this->lSep); +            $msg = PHP_EOL . $this->getBuildSuccessfulMessage() . PHP_EOL;          } else { -            print($this->lSep . "BUILD FAILED" . $this->lSep); -            if (PROJECT_MSG_VERBOSE <= $this->msgOutputLevel || !($error instanceof BuildException)) { -                print($error->__toString().$this->lSep); +            $msg = PHP_EOL . $this->getBuildFailedMessage() . PHP_EOL; +            if (Project::MSG_VERBOSE <= $this->msgOutputLevel || !($error instanceof BuildException)) { +                $msg .= $error->__toString().PHP_EOL;              } else { -                print($error->getMessage()); +                $msg .= $error->getMessage();              }          } -        print($this->lSep . "Total time: " .$this->_formatTime(Phing::currentTimeMillis() - $this->startTime) . $this->lSep); +        $msg .= PHP_EOL . "Total time: " .self::formatTime(Phing::currentTimeMillis() - $this->startTime) . PHP_EOL; +         +        if ($error === null) { +            $this->printMessage($msg, $this->out, Project::MSG_VERBOSE); +        } else { +            $this->printMessage($msg, $this->err, Project::MSG_ERR); +        } +    } + +    /** +     * Get the message to return when a build failed. +     * @return string The classic "BUILD FAILED" +     */ +    protected function getBuildFailedMessage() { +        return "BUILD FAILED";      }      /** +     * Get the message to return when a build succeeded. +     * @return string The classic "BUILD FINISHED" +     */ +    protected function getBuildSuccessfulMessage() { +        return "BUILD FINISHED"; +    } +     +    /**       *  Prints the current target name       *       *  @param  object  The BuildEvent       *  @access public       *  @see    BuildEvent::getTarget()       */ -    function targetStarted(BuildEvent $event) { -        if (PROJECT_MSG_INFO <= $this->msgOutputLevel) { -            print($this->lSep . $event->getProject()->getName() . ' > ' . $event->getTarget()->getName() . ':' . $this->lSep); +    public function targetStarted(BuildEvent $event) { +        if (Project::MSG_INFO <= $this->msgOutputLevel) { +            $showLongTargets = $event->getProject()->getProperty("phing.showlongtargets"); +            $msg = PHP_EOL . $event->getProject()->getName() . ' > ' . $event->getTarget()->getName() . ($showLongTargets ? ' [' . $event->getTarget()->getDescription() . ']' : '') . ':' . PHP_EOL; +            $this->printMessage($msg, $this->out, $event->getPriority());          }      } @@ -151,10 +194,9 @@ class DefaultLogger implements BuildListener {       *  event. So the methods are empty.       *       *  @param  object  The BuildEvent -     *  @access public       *  @see    BuildEvent::getException()       */ -    function targetFinished(BuildEvent $event) {} +    public function targetFinished(BuildEvent $event) {}      /**       *  Fired when a task is started. We don't need specific action on this @@ -164,7 +206,7 @@ class DefaultLogger implements BuildListener {       *  @access public       *  @see    BuildEvent::getTask()       */ -    function taskStarted(BuildEvent $event) {} +    public function taskStarted(BuildEvent $event) {}      /**       *  Fired when a task has finished. We don't need specific action on this @@ -174,7 +216,7 @@ class DefaultLogger implements BuildListener {       *  @access public       *  @see    BuildEvent::getException()       */ -    function taskFinished(BuildEvent $event) {} +    public function taskFinished(BuildEvent $event) {}      /**       *  Print a message to the stdout. @@ -183,20 +225,23 @@ class DefaultLogger implements BuildListener {       *  @access public       *  @see    BuildEvent::getMessage()       */ -    function messageLogged(BuildEvent $event) { -        if ($event->getPriority() <= $this->msgOutputLevel) { +    public function messageLogged(BuildEvent $event) { +        $priority = $event->getPriority(); +        if ($priority <= $this->msgOutputLevel) {              $msg = "";              if ($event->getTask() !== null) {                  $name = $event->getTask();                  $name = $name->getTaskName();                  $msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT); -                #for ($i=0; $i < ($this->LEFT_COLUMN_SIZE - strlen($msg)); ++$i) { -                #    print(" "); -                #} -                #print($msg);              } +                          $msg .= $event->getMessage(); -            $this->printMessage($msg, $event->getPriority()); +             +            if ($priority != Project::MSG_ERR) { +                $this->printMessage($msg, $this->out, $priority); +            } else { +                $this->printMessage($msg, $this->err, $priority); +            }          }      } @@ -206,7 +251,7 @@ class DefaultLogger implements BuildListener {       *  @param  integer The time stamp       *  @access private       */ -    function _formatTime($micros) { +    public static function formatTime($micros) {          $seconds = $micros;          $minutes = $seconds / 60;          if ($minutes > 1) { @@ -223,11 +268,12 @@ class DefaultLogger implements BuildListener {       *        * @param string $message  The message to print.        *                 Should not be <code>null</code>. +     * @param resource $stream The stream to use for message printing.       * @param int $priority The priority of the message.        *                 (Ignored in this implementation.)       * @return void       */ -    protected function printMessage($message, $priority) { -        print($message . $this->lSep); +    protected function printMessage($message, OutputStream $stream, $priority) { +        $stream->write($message . PHP_EOL);      }      } diff --git a/buildscripts/phing/classes/phing/listener/HtmlColorLogger.php b/buildscripts/phing/classes/phing/listener/HtmlColorLogger.php new file mode 100755 index 00000000..6514f8d1 --- /dev/null +++ b/buildscripts/phing/classes/phing/listener/HtmlColorLogger.php @@ -0,0 +1,175 @@ +<?php +/* + * $Id: 4b57f4d435b61b6501688394f1ff8534d4b7e93f $ + * + * 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/listener/DefaultLogger.php'; +include_once 'phing/system/util/Properties.php'; + +/** + * Uses CSS class that must be defined in the HTML page + * where the Phing output is displayed. + * + * If used with the -logfile option, the output + * will contain the text wrapped in html <span> elements + * with those css classes. + * + * The default classes used for differentiating + * the message levels can be changed by editing the + * phing/listener/defaults.properties file. + * + * This file can contain 5 key/value pairs: + * HtmlColorLogger.ERROR_CLASS=_your_css_class_name_ + * HtmlColorLogger.WARNING_CLASS=_your_css_class_name_ + * HtmlColorLogger.INFO_CLASS=_your_css_class_name_ + * HtmlColorLogger.VERBOSE_CLASS=_your_css_class_name_ + * HtmlColorLogger.DEBUG_CLASS=_your_css_class_name_ + * + * This stems from the Ansi Color Logger done by Hans Lellelid: + * + * @author     Anton Stöckl <anton@stoeckl.de> (Phing HTML Color Logger) + * @author     Hans Lellelid <hans@xmpl.org> (Phing Ansi Color Logger) + * @author     Magesh Umasankar (Ant) + * @package    phing.listener + * @version    $Id: 4b57f4d435b61b6501688394f1ff8534d4b7e93f $ + */ +class HtmlColorLogger extends DefaultLogger { + +    const CLASS_ERR     = 'phing_err'; +    const CLASS_VERBOSE = 'phing_verbose'; +    const CLASS_DEBUG   = 'phing_debug'; +    const CLASS_WARN    = 'phing_warn'; +    const CLASS_INFO    = 'phing_info'; + +    const PREFIX = '<span class="'; +    const SUFFIX = '">'; +    const END_COLOR = '</span>'; + +    private $errColor; +    private $warnColor; +    private $infoColor; +    private $verboseColor; +    private $debugColor; + +    private $colorsSet = false; + +    /** +     * Construct new HtmlColorLogger +     * Perform initializations that cannot be done in var declarations. +     */ +    public function __construct() { +        parent::__construct(); +        $this->errColor =     self::PREFIX . self::CLASS_ERR     . self::SUFFIX; +        $this->warnColor =    self::PREFIX . self::CLASS_WARN    . self::SUFFIX; +        $this->infoColor =    self::PREFIX . self::CLASS_INFO    . self::SUFFIX; +        $this->verboseColor = self::PREFIX . self::CLASS_VERBOSE . self::SUFFIX; +        $this->debugColor =   self::PREFIX . self::CLASS_DEBUG   . self::SUFFIX; +    } + +    /** +     * Set the colors to use from a property file specified in the +     * special phing property file "phing/listener/defaults.properties". +     */ +    private final function setColors() { + +        $systemColorFile = new PhingFile(Phing::getResourcePath("phing/listener/defaults.properties")); + +        try { +            $prop = new Properties(); + +            $prop->load($systemColorFile); + +            $err     = $prop->getProperty("HtmlColorLogger.ERROR_CLASS"); +            $warn    = $prop->getProperty("HtmlColorLogger.WARNING_CLASS"); +            $info    = $prop->getProperty("HtmlColorLogger.INFO_CLASS"); +            $verbose = $prop->getProperty("HtmlColorLogger.VERBOSE_CLASS"); +            $debug   = $prop->getProperty("HtmlColorLogger.DEBUG_CLASS"); +            if ($err !== null) { +                $this->errColor = self::PREFIX . $err . self::SUFFIX; +            } +            if ($warn !== null) { +                $this->warnColor = self::PREFIX . $warn . self::SUFFIX; +            } +            if ($info !== null) { +                $this->infoColor = self::PREFIX . $info . self::SUFFIX; +            } +            if ($verbose !== null) { +                $this->verboseColor = self::PREFIX . $verbose . self::SUFFIX; +            } +            if ($debug !== null) { +                $this->debugColor = self::PREFIX . $debug . self::SUFFIX; +            } +        } catch (IOException $ioe) { +            //Ignore exception - we will use the defaults. +        } +    } + +    /** +     * @see DefaultLogger#printMessage +     * @param string $message +     * @param OutputStream $stream +     * @param int $priority +     */ +    protected final function printMessage($message, OutputStream $stream, $priority) { +        if ($message !== null) { + +            if (!$this->colorsSet) { +                $this->setColors(); +                $this->colorsSet = true; +            } + +            $search = array('<', '>'); +            $replace = array('<', '>'); +            $message = str_replace($search, $replace, $message); + +            $search = array("\t", "\n", "\r"); +            $replace = array('   ', '<br>', ''); +            $message = str_replace($search, $replace, $message); + +            if (preg_match('@^( +)([^ ].+)@', $message, $matches)) { +                $len = strlen($matches[1]); +                $space = ' '; +                for ($i = 1; $i < $len; $i++) { +                    $space .= ' '; +                } +                $message = $space . $matches[2]; +            } + +            switch ($priority) { +                case Project::MSG_ERR: +                    $message = $this->errColor . $message . self::END_COLOR; +                    break; +                case Project::MSG_WARN: +                    $message = $this->warnColor . $message . self::END_COLOR; +                    break; +                case Project::MSG_INFO: +                    $message = $this->infoColor . $message . self::END_COLOR; +                    break; +                case Project::MSG_VERBOSE: +                    $message = $this->verboseColor . $message . self::END_COLOR; +                    break; +                case Project::MSG_DEBUG: +                    $message = $this->debugColor . $message . self::END_COLOR; +                    break; +            } + +            $stream->write($message . '<br/>'); +        } +    } +} diff --git a/buildscripts/phing/classes/phing/listener/MailLogger.php b/buildscripts/phing/classes/phing/listener/MailLogger.php new file mode 100755 index 00000000..344f3de4 --- /dev/null +++ b/buildscripts/phing/classes/phing/listener/MailLogger.php @@ -0,0 +1,105 @@ +<?php +/* + * $Id: bea608bad3f8bd5733c7eac6451d15b1c937115c $ + * + * 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/listener/DefaultLogger.php'; +include_once 'phing/system/util/Properties.php'; + +/** + * Uses PEAR Mail package to send the build log to one or  + * more recipients. + * + * @author     Michiel Rook <mrook@php.net> + * @package    phing.listener + * @version    $Id$ + */ +class MailLogger extends DefaultLogger +{ +    private $_mailMessage = ""; +     +    private $_from = "phing@phing.info"; +    private $_subject = "Phing build result"; +    private $_tolist = null; +     +    /** +     * Construct new MailLogger +     */ +    public function __construct() { +        parent::__construct(); + +        @require_once 'Mail.php'; + +        if (!class_exists('Mail')) { +            throw new BuildException('Need the PEAR Mail package to send logs'); +        } + +        $from    = Phing::getDefinedProperty('phing.log.mail.from'); +        $subject = Phing::getDefinedProperty('phing.log.mail.subject'); +        $tolist  = Phing::getDefinedProperty('phing.log.mail.recipients'); +         +        if (!empty($from)) { +            $this->_from = $from; +        } +         +        if (!empty($subject)) { +            $this->_subject = $subject; +        } +         +        if (!empty($tolist)) { +            $this->_tolist = $tolist; +        } +    } +     +    /** +     * @see DefaultLogger#printMessage +     * @param string $message +     * @param OutputStream $stream +     * @param int $priority +     */ +    protected final function printMessage($message, OutputStream $stream, $priority) +    { +        if ($message !== null) { +            $this->_mailMessage .= $message . "\n"; +        } +    } +     +    /** +     * Sends the mail +     * +     * @see DefaultLogger#buildFinished +     * @param BuildEvent $event +     */ +    public function buildFinished(BuildEvent $event) +    { +        parent::buildFinished($event); +         +        if (empty($this->_tolist)) { +            return; +        } +         +        $hdrs = array( +            'From'    => $this->_from, +            'Subject' => $this->_subject . (empty($event) ? " (build succesful)" : " (build failed)") +        ); + +        $mail = Mail::factory('mail'); +        $mail->send($this->_tolist, $hdrs, $this->_mailMessage); +    } +} diff --git a/buildscripts/phing/classes/phing/listener/NoBannerLogger.php b/buildscripts/phing/classes/phing/listener/NoBannerLogger.php index e222e10c..887f6678 100644..100755 --- a/buildscripts/phing/classes/phing/listener/NoBannerLogger.php +++ b/buildscripts/phing/classes/phing/listener/NoBannerLogger.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: NoBannerLogger.php,v 1.4 2003/12/24 13:02:08 hlellelid Exp $ + * $Id: d74783e6edb73c6f11fbb93701f0bb6e7ccf06b1 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,16 +19,14 @@   * <http://phing.info>.   */ -include_once 'phing/listener/DefaultLogger.php'; +require_once 'phing/listener/DefaultLogger.php';  /** - *  Extends DefaultLogger to strip out empty targets.  This logger is most - *  commonly used and also enforced by the default phing invokation scripts - *  in bin/. + *  Extends DefaultLogger to strip out empty targets.   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.4 $ $Date: 2003/12/24 13:02:08 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @package   phing.listener   */  class NoBannerLogger extends DefaultLogger { @@ -45,14 +43,14 @@ class NoBannerLogger extends DefaultLogger {      }      function messageLogged(BuildEvent $event) { -        if ($event->getPriority() > $this->msgOutputLevel || -                null === $event->getMessage() || -                         trim($event->getMessage() === "")) { +         +        if ($event->getPriority() > $this->msgOutputLevel || null === $event->getMessage() || trim($event->getMessage() === "")) {              return;          } - +                  if ($this->targetName !== null) { -            print($this->lSep . "Target: ".$this->targetName . $this->lSep); +            $msg = PHP_EOL . $event->getProject()->getName() . ' > ' . $this->targetName . ':' . PHP_EOL; +            $this->printMessage($msg, $this->out, $event->getPriority());              $this->targetName = null;          } diff --git a/buildscripts/phing/classes/phing/listener/PearLogger.php b/buildscripts/phing/classes/phing/listener/PearLogListener.php index 2bea6655..76efdbbb 100644..100755 --- a/buildscripts/phing/classes/phing/listener/PearLogger.php +++ b/buildscripts/phing/classes/phing/listener/PearLogListener.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PearLogger.php,v 1.3 2004/03/15 14:45:06 hlellelid Exp $ + *  $Id: d2d1a761c30c120a07e419622bcbcb9b5e067c24 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,11 +20,9 @@   */  require_once 'phing/BuildListener.php'; -include_once 'phing/BuildEvent.php'; -require_once 'Log.php';  /** - * Writes log messages to PEAR Log. + * Writes build messages to PEAR Log.   *    * By default it will log to file in current directory w/ name 'phing.log'.  You can customize   * this behavior by setting properties: @@ -38,11 +36,11 @@ require_once 'Log.php';   * </code>   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.3 $ $Date: 2004/03/15 14:45:06 $ + * @version   $Id$   * @see       BuildEvent   * @package   phing.listener   */ -class PearLogger implements BuildListener { +class PearLogListener implements BuildListener {      /**       *  Size of the left column in output. The default char width is 12. @@ -51,39 +49,37 @@ class PearLogger implements BuildListener {      const LEFT_COLUMN_SIZE = 12;      /** -     *  The message output level that should be used. The default is -     *  <code>PROJECT_MSG_VERBOSE</code>. -     *  @var int -     */ -    protected $msgOutputLevel = PROJECT_MSG_ERR; - -    /**       *  Time that the build started       *  @var int       */      protected $startTime;      /** -     * Maps Phing PROJECT_MSG_* constants to PEAR_LOG_* constants. +     * Maps Phing Project::MSG_* constants to PEAR_LOG_* constants.       * @var array       */ -    protected static $levelMap = array( PROJECT_MSG_DEBUG => PEAR_LOG_DEBUG, -                                        PROJECT_MSG_INFO => PEAR_LOG_INFO, -                                        PROJECT_MSG_VERBOSE => PEAR_LOG_NOTICE, -                                        PROJECT_MSG_WARN => PEAR_LOG_WARNING, -                                        PROJECT_MSG_ERR => PEAR_LOG_ERR +    protected static $levelMap = array( Project::MSG_DEBUG => PEAR_LOG_DEBUG, +                                        Project::MSG_INFO => PEAR_LOG_INFO, +                                        Project::MSG_VERBOSE => PEAR_LOG_NOTICE, +                                        Project::MSG_WARN => PEAR_LOG_WARNING, +                                        Project::MSG_ERR => PEAR_LOG_ERR                                         );      /**       * Whether logging has been configured.       * @var boolean       */      protected $logConfigured = false; -               +     +    /** +     * @var Log PEAR Log object. +     */ +    protected $logger; +          /**       * Configure the logger.       */      protected function configureLogging() { -     +                  $type = Phing::getDefinedProperty('pear.log.type');          $name = Phing::getDefinedProperty('pear.log.name');          $ident = Phing::getDefinedProperty('pear.log.ident'); @@ -94,6 +90,11 @@ class PearLogger implements BuildListener {          if ($ident === null) $ident = 'phing';          if ($conf === null) $conf = array(); +        include_once 'Log.php'; +        if (!class_exists('Log')) { +            throw new BuildException("Cannot find PEAR Log class for use by PearLogger."); +        } +                  $this->logger = Log::singleton($type, $name, $ident, $conf, self::$levelMap[$this->msgOutputLevel]);      }         @@ -108,112 +109,80 @@ class PearLogger implements BuildListener {          }          return $this->logger;      } -     +      /** -     *  Set the msgOutputLevel this logger is to respond to. -     * -     *  Only messages with a message level lower than or equal to the given -     *  level are output to the log. -     * -     *  <p> Constants for the message levels are in Project.php. The order of -     *  the levels, from least to most verbose, is: -     * -     *  <ul> -     *    <li>PROJECT_MSG_ERR</li> -     *    <li>PROJECT_MSG_WARN</li> -     *    <li>PROJECT_MSG_INFO</li> -     *    <li>PROJECT_MSG_VERBOSE</li> -     *    <li>PROJECT_MSG_DEBUG</li> -     *  </ul> -     * -     *  The default message level for DefaultLogger is PROJECT_MSG_ERR. +     *  Sets the start-time when the build started. Used for calculating +     *  the build-time.       * -     *  @param  integer  the logging level for the logger. -     *  @access public +     * @param  BuildEvent  The BuildEvent       */ -    function setMessageOutputLevel($level) { -        $this->msgOutputLevel = (int) $level; -    } - -    /** -    *  Sets the start-time when the build started. Used for calculating -    *  the build-time. -    * -    *  @param  object  The BuildEvent -    *  @access public -    */ - -    function buildStarted(BuildEvent $event) { +    public function buildStarted(BuildEvent $event) {          $this->startTime = Phing::currentTimeMillis();          $this->logger()->setIdent($event->getProject()->getName());          $this->logger()->info("Starting build with buildfile: ". $event->getProject()->getProperty("phing.file"));      }      /** -     *  Prints whether the build succeeded or failed, and any errors that +     *  Logs whether the build succeeded or failed, and any errors that       *  occured during the build. Also outputs the total build-time.       * -     *  @param  object  The BuildEvent -     *  @access public -     *  @see    BuildEvent::getException() +     * @param  BuildEvent  The BuildEvent +     * @see    BuildEvent::getException()       */ -    function buildFinished(BuildEvent $event) { +    public function buildFinished(BuildEvent $event) {          $error = $event->getException();          if ($error === null) {              $msg = "Finished successful build.";          } else {              $msg = "Build failed. [reason: " . $error->getMessage() ."]";          } -        $this->logger()->log($msg . " Total time: " . $this->_formatTime(Phing::currentTimeMillis() - $this->startTime)); +        $this->logger()->log($msg . " Total time: " . DefaultLogger::formatTime(Phing::currentTimeMillis() - $this->startTime));      }      /** -     *  Prints the current target name +     * Logs the current target name       * -     *  @param  object  The BuildEvent -     *  @access public -     *  @see    BuildEvent::getTarget() +     * @param  BuildEvent  The BuildEvent +     * @see    BuildEvent::getTarget()       */ -    function targetStarted(BuildEvent $event) {} +    public function targetStarted(BuildEvent $event) {}      /**       *  Fired when a target has finished. We don't need specific action on this       *  event. So the methods are empty.       * -     *  @param  object  The BuildEvent +     *  @param  BuildEvent  The BuildEvent       *  @access public       *  @see    BuildEvent::getException()       */ -    function targetFinished(BuildEvent $event) {} +    public function targetFinished(BuildEvent $event) {}      /**       *  Fired when a task is started. We don't need specific action on this       *  event. So the methods are empty.       * -     *  @param  object  The BuildEvent +     *  @param  BuildEvent  The BuildEvent       *  @access public       *  @see    BuildEvent::getTask()       */ -    function taskStarted(BuildEvent $event) {} +    public function taskStarted(BuildEvent $event) {}      /**       *  Fired when a task has finished. We don't need specific action on this       *  event. So the methods are empty.       * -     *  @param  object  The BuildEvent -     *  @access public -     *  @see    BuildEvent::getException() +     * @param  BuildEvent  The BuildEvent +     * @see    BuildEvent::getException()       */ -    function taskFinished(BuildEvent $event) {} +    public function taskFinished(BuildEvent $event) {}      /** -     *  Print a message to the stdout. +     *  Logs a message to the configured PEAR logger.       * -     *  @param  object  The BuildEvent -     *  @access public -     *  @see    BuildEvent::getMessage() +     * @param  BuildEvent  The BuildEvent +     * @see    BuildEvent::getMessage()       */ -    function messageLogged(BuildEvent $event) { +    public function messageLogged(BuildEvent $event) {          if ($event->getPriority() <= $this->msgOutputLevel) {                          $msg = "";              if ($event->getTask() !== null) { @@ -225,22 +194,4 @@ class PearLogger implements BuildListener {              $this->logger()->log($msg, self::$levelMap[$event->getPriority()]);          }      } - -    /** -     *  Formats a time micro integer to human readable format. -     * -     *  @param  integer The time stamp -     *  @access private -     */ -    function _formatTime($micros) { -        $seconds = $micros; -        $minutes = $seconds / 60; -        if ($minutes > 1) { -            return sprintf("%1.0f minute%s %0.2f second%s", -                                    $minutes, ($minutes === 1 ? " " : "s "), -                                    $seconds - floor($seconds/60) * 60, ($seconds%60 === 1 ? "" : "s")); -        } else { -            return sprintf("%0.4f second%s", $seconds, ($seconds%60 === 1 ? "" : "s")); -        } -    }           } diff --git a/buildscripts/phing/classes/phing/listener/StreamRequiredBuildLogger.php b/buildscripts/phing/classes/phing/listener/StreamRequiredBuildLogger.php new file mode 100755 index 00000000..c463a59d --- /dev/null +++ b/buildscripts/phing/classes/phing/listener/StreamRequiredBuildLogger.php @@ -0,0 +1,39 @@ +<?php +/* + *  $Id: e0daef8de8e5be892b2eaaa7a42fa5d04ad540b5 $ + * + * 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/BuildLogger.php'; + +/** + * Interface for build loggers that require that out/err streams be set in order to function. + *  + * This is just an empty sub-interface to BuildLogger, but is used by Phing to throw
 + * graceful errors when classes like phing.listener.DefaultLogger are being used as 
 + * -listener. + * + * @author    Hans Lellelid <hans@xmpl.org> + * @version   $Id$ + * @see       BuildEvent + * @see       Project::addBuildListener() + * @package   phing + */ +interface StreamRequiredBuildLogger extends BuildLogger { + +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/listener/XmlLogger.php b/buildscripts/phing/classes/phing/listener/XmlLogger.php index 07ff031e..25ff0ba2 100644..100755 --- a/buildscripts/phing/classes/phing/listener/XmlLogger.php +++ b/buildscripts/phing/classes/phing/listener/XmlLogger.php @@ -1,265 +1,354 @@  <?php -	/** -	 * $Id: XmlLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $ -	 * -	 * 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/listener/BuildLogger.php'; -	require_once 'phing/listener/DefaultLogger.php'; -	require_once 'phing/system/util/Timer.php'; -	/** -	 * Generates a file in the current directory with -	 * an XML description of what happened during a build. -	 * The default filename is "log.xml", but this can be overridden -	 * with the property <code>XmlLogger.file</code>. -	 * -	 * @author Michiel Rook <michiel@trendserver.nl> -	 * @version $Id: XmlLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $ -	 * @package phing.listener -	 */	 -	class XmlLogger implements BuildLogger -	{ -		/** XML element name for a build. */ -		const BUILD_TAG = "build"; -		/** XML element name for a target. */ -		const TARGET_TAG = "target"; -		/** XML element name for a task. */ -		const TASK_TAG = "task"; -		/** XML element name for a message. */ -		const MESSAGE_TAG = "message"; -		/** XML attribute name for a name. */ -		const NAME_ATTR = "name"; -		/** XML attribute name for a time. */ -		const TIME_ATTR = "time"; -		/** XML attribute name for a message priority. */ -		const PRIORITY_ATTR = "priority"; -		/** XML attribute name for a file location. */ -		const LOCATION_ATTR = "location"; -		/** XML attribute name for an error description. */ -		const ERROR_ATTR = "error"; -		/** XML element name for a stack trace. */ -		const STACKTRACE_TAG = "stacktrace"; -		 -		private $doc = NULL; -		 -		private $buildStartTime = 0; -		private $targetStartTime = 0; -		private $taskStartTime = 0; -		 -		private $buildElement = NULL; -		 -		private $msgOutputLevel = PROJECT_MSG_DEBUG; -		 -		/** -		 *  Constructs a new BuildListener that logs build events to an XML file. -		 */ -		function __construct() -		{ -			$this->doc = new DOMDocument(); -			$this->doc->formatOutput = true; -			 -			$this->buildTimer = new Timer(); -			$this->targetTimer = new Timer(); -			$this->taskTimer = new Timer(); -		} -		 -		/** -		 * Fired when the build starts, this builds the top-level element for the -		 * document and remembers the time of the start of the build. -		 * -		 * @param BuildEvent Ignored. -		 */ -		function buildStarted(BuildEvent $event) -		{ -			$this->buildTimerStart = Phing::currentTimeMillis(); -			$this->buildElement = $this->doc->createElement(XmlLogger::BUILD_TAG); -		} -		 -		/** -		 * Fired when the build finishes, this adds the time taken and any -		 * error stacktrace to the build element and writes the document to disk. -		 * -		 * @param BuildEvent An event with any relevant extra information. -		 *              Will not be <code>null</code>. -		 */ -		function buildFinished(BuildEvent $event) -		{ -			$this->buildTimer->stop(); -			 -			$elapsedTime = Phing::currentTimeMillis() - $this->buildTimerStart; -			 -			$this->buildElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::_formatTime($elapsedTime)); -			 -			if ($event->getException() != null) -			{ -				$this->buildElement->setAttribute(XmlLogger::ERROR_ATTR, $event->getException()->toString()); -				 -				$errText = $this->doc->createCDATASection($event->getException()->getTraceAsString()); -				$stacktrace = $this->doc->createElement(XmlLogger::STACKTRACE_TAG); -				$stacktrace->appendChild($errText); -				$this->buildElement->appendChild($stacktrace); -			} -			 -			$outFilename = $event->getProject()->getProperty("XmlLogger.file"); -			 -			if ($outFilename == "") -			{ -				$outFilename = "log.xml"; -			} -			$writer = new FileWriter($outFilename); -			 -			$writer->write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); -			$writer->write($this->doc->saveXML($this->buildElement)); -			$writer->close(); -		} -		/** -		 * Fired when a target starts building, remembers the current time and the name of the target. -		 * -		 * @param BuildEvent An event with any relevant extra information. -		 *              Will not be <code>null</code>. -		 */ -		function targetStarted(BuildEvent $event) -		{ -			$target = $event->getTarget(); -			 -			$this->targetTimerStart = Phing::currentTimeMillis(); -			 -			$this->targetElement = $this->doc->createElement(XmlLogger::TARGET_TAG); -			$this->targetElement->setAttribute(XmlLogger::NAME_ATTR, $target->getName()); -		} -		 -		/** -		 * Fired when a target finishes building, this adds the time taken -		 * to the appropriate target element in the log. -		 * -		 * @param BuildEvent An event with any relevant extra information. -		 *              Will not be <code>null</code>. -		 */ -		function targetFinished(BuildEvent $event) -		{ -			$target = $event->getTarget(); -			 -			$elapsedTime = Phing::currentTimeMillis() - $this->targetTimerStart; -			 -			$this->targetElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::_formatTime($elapsedTime)); -			 -			$this->buildElement->appendChild($this->targetElement); -		} -		 -		/** -		 * Fired when a task starts building, remembers the current time and the name of the task. -		 * -		 * @param BuildEvent An event with any relevant extra information. -		 *              Will not be <code>null</code>. -		 */ -		function taskStarted(BuildEvent $event) -		{ -			$task = $event->getTask(); -			 -			$this->taskTimerStart = Phing::currentTimeMillis(); -			 -			$this->taskElement = $this->doc->createElement(XmlLogger::TASK_TAG); -			$this->taskElement->setAttribute(XmlLogger::NAME_ATTR, $task->getTaskName()); -			$this->taskElement->setAttribute(XmlLogger::LOCATION_ATTR, $task->getLocation()->toString()); -		} -		/** -		 * Fired when a task finishes building, this adds the time taken -		 * to the appropriate task element in the log. -		 * -		 * @param BuildEvent An event with any relevant extra information. -		 *              Will not be <code>null</code>. -		 */		 -		function taskFinished(BuildEvent $event) -		{ -			$task = $event->getTask(); -			 -			$elapsedTime = Phing::currentTimeMillis() - $this->taskTimerStart; -			$this->taskElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::_formatTime($elapsedTime)); -			 -			$this->targetElement->appendChild($this->taskElement); -		} -		 -		/** -		 * Fired when a message is logged, this adds a message element to the -		 * most appropriate parent element (task, target or build) and records -		 * the priority and text of the message. -		 * -		 * @param BuildEvent An event with any relevant extra information. -		 *              Will not be <code>null</code>. -		 */ -		function messageLogged(BuildEvent $event) -		{ -			$priority = $event->getPriority(); -			 -			if ($priority > $this->msgOutputLevel) -			{ -				return; -			} -			 -			$messageElement = $this->doc->createElement(XmlLogger::MESSAGE_TAG); -			 -			switch ($priority) -			{ -				case PROJECT_MSG_ERR:  -					$name = "error";  -					break; -					 -				case PROJECT_MSG_WARN: -					$name = "warn"; -					break; -				 -				case PROJECT_MSG_INFO: -					$name = "info"; -					break; -					 -				default: -					$name = "debug"; -					break; -			} -			 -			$messageElement->setAttribute(XmlLogger::PRIORITY_ATTR, $name); -			 -			$messageText = $this->doc->createCDATASection($event->getMessage()); -			 -			$messageElement->appendChild($messageText); -			 -			if ($event->getTask() != null) -			{ -				$this->taskElement->appendChild($messageElement); -			} -			else -			if ($event->getTarget() != null) -			{ -				$this->targetElement->appendChild($messageElement); -			} -			else -			if ($this->buildElement != null) -			{			 -				$this->buildElement->appendChild($messageElement); -			} -		} -		 -		/** -		 * Set the logging level when using this as a Logger -		 */ -		function setMessageOutputLevel($level) -		{ -			$this->msgOutputLevel = $level; -		} -	}; -?>
\ No newline at end of file +/** + * $Id: aaf7d77e9952319b9598d786c556be005d34c188 $ + * + * 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/BuildLogger.php'; +require_once 'phing/listener/DefaultLogger.php'; +require_once 'phing/system/util/Timer.php'; + +/** + * Generates a file in the current directory with + * an XML description of what happened during a build. + * The default filename is "log.xml", but this can be overridden + * with the property <code>XmlLogger.file</code>. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: aaf7d77e9952319b9598d786c556be005d34c188 $ + * @package phing.listener + */  +class XmlLogger implements BuildLogger { +     +    /** XML element name for a build. */ +    const BUILD_TAG = "build"; +     +    /** XML element name for a target. */ +    const TARGET_TAG = "target"; +     +    /** XML element name for a task. */ +    const TASK_TAG = "task"; +     +    /** XML element name for a message. */ +    const MESSAGE_TAG = "message"; +     +    /** XML attribute name for a name. */ +    const NAME_ATTR = "name"; +     +    /** XML attribute name for a time. */ +    const TIME_ATTR = "time"; +     +    /** XML attribute name for a message priority. */ +    const PRIORITY_ATTR = "priority"; +     +    /** XML attribute name for a file location. */ +    const LOCATION_ATTR = "location"; +     +    /** XML attribute name for an error description. */ +    const ERROR_ATTR = "error"; +     +    /** XML element name for a stack trace. */ +    const STACKTRACE_TAG = "stacktrace"; +     +    /** +     * @var DOMDocument The XML document created by this logger.  +     */ +    private $doc; +     +    /** +     * @var int Start time for entire build. +     */ +    private $buildTimerStart = 0; +     +    /** +     * @var DOMElement Top-level (root) build element +     */ +    private $buildElement; +     +    /** +     * @var array DOMElement[] The parent of the element being processed. +     */ +    private $elementStack = array(); +     +    /** +     * @var array int[] Array of millisecond times for the various elements being processed. +     */ +    private $timesStack = array(); +     +    /** +     * @var int +     */ +    private $msgOutputLevel = Project::MSG_DEBUG; +     +    /** +     * @var OutputStream Stream to use for standard output. +     */ +    private $out; +    +    /** +     * @var OutputStream Stream to use for error output. +     */ +    private $err; +     +    /** +     * @var string Name of filename to create. +     */ +    private $outFilename; +     +    /** +     *  Constructs a new BuildListener that logs build events to an XML file. +     */ +    public function __construct() { +        $this->doc = new DOMDocument("1.0", "UTF-8"); +        $this->doc->formatOutput = true; +    } +     +    /** +     * Fired when the build starts, this builds the top-level element for the +     * document and remembers the time of the start of the build. +     * +     * @param BuildEvent Ignored. +     */ +    function buildStarted(BuildEvent $event) { +        $this->buildTimerStart = Phing::currentTimeMillis(); +        $this->buildElement = $this->doc->createElement(XmlLogger::BUILD_TAG); +        array_push($this->elementStack, $this->buildElement); +        array_push($this->timesStack, $this->buildTimerStart); +    } +     +    /** +     * Fired when the build finishes, this adds the time taken and any +     * error stacktrace to the build element and writes the document to disk. +     * +     * @param BuildEvent $event An event with any relevant extra information. +     *              Will not be <code>null</code>. +     */ +    public function buildFinished(BuildEvent $event) { +         +        $elapsedTime = Phing::currentTimeMillis() - $this->buildTimerStart; +         +        $this->buildElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::formatTime($elapsedTime)); +         +        if ($event->getException() != null) { +            $this->buildElement->setAttribute(XmlLogger::ERROR_ATTR, $event->getException()->getMessage()); +            $errText = $this->doc->createCDATASection($event->getException()->getTraceAsString()); +            $stacktrace = $this->doc->createElement(XmlLogger::STACKTRACE_TAG); +            $stacktrace->appendChild($errText); +            $this->buildElement->appendChild($stacktrace); +        } +         +        $this->doc->appendChild($this->buildElement); +         +        $outFilename = $event->getProject()->getProperty("XmlLogger.file"); +        if ($outFilename == null) { +            $outFilename = "log.xml"; +        } +         +        try { +            $stream = $this->out; +            if ($stream === null) { +                $stream = new FileOutputStream($outFilename);  +            } +             +            // Yes, we could just stream->write() but this will eventually be the better +            // way to do this (when we need to worry about charset conversions.  +            $writer = new OutputStreamWriter($stream); +            $writer->write($this->doc->saveXML()); +            $writer->close(); +        } catch (IOException $exc) { +            try { +                $stream->close(); // in case there is a stream open still ... +            } catch (Exception $x) {} +            throw new BuildException("Unable to write log file.", $exc); +        } +         +         // cleanup:remove the buildElement +        $this->buildElement = null; +        +        array_pop($this->elementStack); +        array_pop($this->timesStack); +    } +         +     +    /** +     * Fired when a target starts building, remembers the current time and the name of the target. +     * +     * @param BuildEvent $event An event with any relevant extra information. +     *              Will not be <code>null</code>. +     */ +    public function targetStarted(BuildEvent $event) { +        $target = $event->getTarget(); +         +        $targetElement = $this->doc->createElement(XmlLogger::TARGET_TAG); +        $targetElement->setAttribute(XmlLogger::NAME_ATTR, $target->getName()); +         +        array_push($this->timesStack, Phing::currentTimeMillis()); +        array_push($this->elementStack, $targetElement); +    } +     +    /** +     * Fired when a target finishes building, this adds the time taken +     * to the appropriate target element in the log. +     * +     * @param BuildEvent $event An event with any relevant extra information. +     *              Will not be <code>null</code>. +     */ +    public function targetFinished(BuildEvent $event) { +        $targetTimerStart = array_pop($this->timesStack); +        $targetElement = array_pop($this->elementStack); +         +        $elapsedTime = Phing::currentTimeMillis() - $targetTimerStart; +        $targetElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::formatTime($elapsedTime)); +         +        $parentElement = $this->elementStack[ count($this->elementStack) - 1 ]; +        $parentElement->appendChild($targetElement); +    } +     +    /** +     * Fired when a task starts building, remembers the current time and the name of the task. +     * +     * @param BuildEvent $event An event with any relevant extra information. +     *              Will not be <code>null</code>. +     */ +    public function taskStarted(BuildEvent $event) { +        $task = $event->getTask(); +         +        $taskElement = $this->doc->createElement(XmlLogger::TASK_TAG); +        $taskElement->setAttribute(XmlLogger::NAME_ATTR, $task->getTaskName()); +        $taskElement->setAttribute(XmlLogger::LOCATION_ATTR, $task->getLocation()->toString()); +         +        array_push($this->timesStack, Phing::currentTimeMillis()); +        array_push($this->elementStack, $taskElement); +    } +     +    /** +     * Fired when a task finishes building, this adds the time taken +     * to the appropriate task element in the log. +     * +     * @param BuildEvent $event An event with any relevant extra information. +     *              Will not be <code>null</code>. +     */      +    public function taskFinished(BuildEvent $event) { +        $taskTimerStart = array_pop($this->timesStack); +        $taskElement = array_pop($this->elementStack); +         +        $elapsedTime = Phing::currentTimeMillis() - $taskTimerStart; +        $taskElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::formatTime($elapsedTime)); +         +        $parentElement = $this->elementStack[ count($this->elementStack) - 1 ]; +        $parentElement->appendChild($taskElement); +    } +     +    /** +     * Fired when a message is logged, this adds a message element to the +     * most appropriate parent element (task, target or build) and records +     * the priority and text of the message. +     * +     * @param BuildEvent An event with any relevant extra information. +     *              Will not be <code>null</code>. +     */ +    public function messageLogged(BuildEvent $event) +    { +        $priority = $event->getPriority(); +         +        if ($priority > $this->msgOutputLevel) { +            return; +        } +         +        $messageElement = $this->doc->createElement(XmlLogger::MESSAGE_TAG); +         +        switch ($priority) { +            case Project::MSG_ERR:  +                $name = "error";  +                break; +            case Project::MSG_WARN: +                $name = "warn"; +                break; +            case Project::MSG_INFO: +                $name = "info"; +                break; +            default: +                $name = "debug"; +                break; +        } +         +        $messageElement->setAttribute(XmlLogger::PRIORITY_ATTR, $name); +         +        if (function_exists('mb_convert_encoding')) +        { +            $messageConverted = mb_convert_encoding($event->getMessage(), 'UTF-8'); +        } +        else +        { +            $messageConverted = utf8_encode($event->getMessage()); +        } +         +        $messageText = $this->doc->createCDATASection($messageConverted); +         +        $messageElement->appendChild($messageText); +         +        if (!empty($this->elementStack)) { +            $this->elementStack[count($this->elementStack)-1]->appendChild($messageElement); +        } +    } + +    /** +     *  Set the msgOutputLevel this logger is to respond to. +     * +     *  Only messages with a message level lower than or equal to the given +     *  level are output to the log. +     * +     *  <p> Constants for the message levels are in Project.php. The order of +     *  the levels, from least to most verbose, is: +     * +     *  <ul> +     *    <li>Project::MSG_ERR</li> +     *    <li>Project::MSG_WARN</li> +     *    <li>Project::MSG_INFO</li> +     *    <li>Project::MSG_VERBOSE</li> +     *    <li>Project::MSG_DEBUG</li> +     *  </ul> +     * +     *  The default message level for DefaultLogger is Project::MSG_ERR. +     * +     * @param int $level The logging level for the logger. +     * @see BuildLogger#setMessageOutputLevel() +     */ +    public function setMessageOutputLevel($level) { +        $this->msgOutputLevel = (int) $level; +    } +     +    /** +     * Sets the output stream. +     * @param OutputStream $output +     * @see BuildLogger#setOutputStream() +     */ +    public function setOutputStream(OutputStream $output) { +        $this->out = $output; +    } +     +    /** +     * Sets the error stream. +     * @param OutputStream $err +     * @see BuildLogger#setErrorStream() +     */ +    public function setErrorStream(OutputStream $err) { +        $this->err = $err; +    } +     +} diff --git a/buildscripts/phing/classes/phing/listener/defaults.properties b/buildscripts/phing/classes/phing/listener/defaults.properties index f60a3fd5..4a4dec68 100644 --- a/buildscripts/phing/classes/phing/listener/defaults.properties +++ b/buildscripts/phing/classes/phing/listener/defaults.properties @@ -36,8 +36,8 @@  #  #################################################### -AnsiColorLogger.ERROR_COLOR=2;31 -AnsiColorLogger.WARNING_COLOR=2;35 -AnsiColorLogger.INFO_COLOR=2;36 -AnsiColorLogger.VERBOSE_COLOR=2;32 -AnsiColorLogger.DEBUG_COLOR=2;34 +AnsiColorLogger.ERROR_COLOR=01;31 +AnsiColorLogger.WARNING_COLOR=01;35 +AnsiColorLogger.INFO_COLOR=00;36 +AnsiColorLogger.VERBOSE_COLOR=00;32 +AnsiColorLogger.DEBUG_COLOR=01;34 diff --git a/buildscripts/phing/classes/phing/mappers/FileNameMapper.php b/buildscripts/phing/classes/phing/mappers/FileNameMapper.php index c8f1f8a9..f4306b4c 100644..100755 --- a/buildscripts/phing/classes/phing/mappers/FileNameMapper.php +++ b/buildscripts/phing/classes/phing/mappers/FileNameMapper.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: FileNameMapper.php,v 1.7 2004/01/22 03:29:13 hlellelid Exp $ + *  $Id: 24c9367363b11f9ab97509532739bf2353023034 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,7 +24,7 @@   *   * @author Andreas Aderhold, andi@binarycloud.com   * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.7 $ + * @version $Id$   * @package phing.mappers   */  interface FileNameMapper { diff --git a/buildscripts/phing/classes/phing/mappers/FlattenMapper.php b/buildscripts/phing/classes/phing/mappers/FlattenMapper.php index fea5c1e4..55ed4113 100644..100755 --- a/buildscripts/phing/classes/phing/mappers/FlattenMapper.php +++ b/buildscripts/phing/classes/phing/mappers/FlattenMapper.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: FlattenMapper.php,v 1.9 2005/05/26 13:10:51 mrook Exp $ + *  $Id: c18f079545fa2c53e9a129ec1dcf32447b597c09 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ require_once 'phing/mappers/FileNameMapper.php';   * Removes any directory information from the passed path.   *   * @author   Andreas Aderhold <andi@binarycloud.com> - * @version  $Revision: 1.9 $ + * @version  $Id$   * @package  phing.mappers   */  class FlattenMapper implements FileNameMapper { diff --git a/buildscripts/phing/classes/phing/mappers/GlobMapper.php b/buildscripts/phing/classes/phing/mappers/GlobMapper.php index 3c178620..79df94d6 100644..100755 --- a/buildscripts/phing/classes/phing/mappers/GlobMapper.php +++ b/buildscripts/phing/classes/phing/mappers/GlobMapper.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: GlobMapper.php,v 1.10 2004/01/22 03:29:13 hlellelid Exp $ + *  $Id: 464f98975210eee84faed74ef4a53c83d23aa079 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ include_once 'phing/mappers/FileNameMapper.php';   * description here   *   * @author   Andreas Aderhold, andi@binarycloud.com - * @version  $Revision: 1.10 $ + * @version  $Id$   * @package   phing.mappers   */  class GlobMapper implements FileNameMapper { diff --git a/buildscripts/phing/classes/phing/mappers/IdentityMapper.php b/buildscripts/phing/classes/phing/mappers/IdentityMapper.php index daf80c25..e608a71d 100644..100755 --- a/buildscripts/phing/classes/phing/mappers/IdentityMapper.php +++ b/buildscripts/phing/classes/phing/mappers/IdentityMapper.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: IdentityMapper.php,v 1.7 2004/01/22 03:29:13 hlellelid Exp $ + *  $Id: aa11e8f44255c1b191df3230336c57664daf5f4f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ require_once 'phing/mappers/FileNameMapper.php';   *    * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.7 $ + * @version   $Id$   * @package   phing.mappers   */  class IdentityMapper implements FileNameMapper { diff --git a/buildscripts/phing/classes/phing/mappers/MergeMapper.php b/buildscripts/phing/classes/phing/mappers/MergeMapper.php index f10f41c0..dc60ab34 100644..100755 --- a/buildscripts/phing/classes/phing/mappers/MergeMapper.php +++ b/buildscripts/phing/classes/phing/mappers/MergeMapper.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: MergeMapper.php,v 1.8 2004/01/22 03:29:13 hlellelid Exp $ + *  $Id: 9f014a901932e99fd50820d3f3a78387929f06ee $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ include_once 'phing/mappers/FileNameMapper.php';   * was set for "to".   *   * @author    Andreas Aderhold <andi@binarycloud.com> - * @version   $Revision: 1.8 $ + * @version   $Id$   * @package   phing.mappers   */  class MergeMapper implements FileNameMapper { @@ -37,10 +37,10 @@ class MergeMapper implements FileNameMapper {      /**       * The mapper implementation. Basically does nothing in this case.       * -     * @param    mixed     The data the mapper works on -     * @returns  mixed     The data after the mapper has been applied -     * @access   public -     * @author   Andreas Aderhold, andi@binarycloud.com +     * @param   mixed     The data the mapper works on +     * @return  mixed     The data after the mapper has been applied +     * @access  public +     * @author  Andreas Aderhold, andi@binarycloud.com       */      function main($sourceFileName) {          if ($this->mergedFile === null) {             @@ -52,10 +52,10 @@ class MergeMapper implements FileNameMapper {      /**       * Accessor. Sets the to property       * -     * @param    string     To what this mapper should convert the from string -     * @returns  boolean    True -     * @access   public -     * @author   Andreas Aderhold, andi@binarycloud.com +     * @param   string     To what this mapper should convert the from string +     * @return  boolean    True +     * @access  public +     * @author  Andreas Aderhold, andi@binarycloud.com       */      function setTo($to) {          $this->mergedFile = $to; diff --git a/buildscripts/phing/classes/phing/mappers/RegexpMapper.php b/buildscripts/phing/classes/phing/mappers/RegexpMapper.php index a3d51976..ca387241 100644..100755 --- a/buildscripts/phing/classes/phing/mappers/RegexpMapper.php +++ b/buildscripts/phing/classes/phing/mappers/RegexpMapper.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: RegexpMapper.php,v 1.9 2004/03/15 17:11:15 hlellelid Exp $ + *  $Id: 96aee1ffd32ba919d42e1141129068006e709976 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@ include_once 'phing/util/regexp/Regexp.php';   *   * @author Andreas Aderhold <andi@binarycloud.com>   * @author Hans Lellelid <hans@velum.net> - * @version $Revision: 1.9 $ + * @version $Id$   * @package phing.mappers   */  class RegexpMapper implements FileNameMapper { diff --git a/buildscripts/phing/classes/phing/parser/AbstractHandler.php b/buildscripts/phing/classes/phing/parser/AbstractHandler.php index 6f8d7705..1837bbbf 100644..100755 --- a/buildscripts/phing/classes/phing/parser/AbstractHandler.php +++ b/buildscripts/phing/classes/phing/parser/AbstractHandler.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: AbstractHandler.php,v 1.6 2004/02/27 18:16:10 hlellelid Exp $ + * $Id: 3d81ac2784333ce8108cf32818b8dfc335993507 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,8 +26,8 @@ include_once 'phing/parser/ExpatParseException.php';   * This is an abstract class all SAX handler classes must extend   *   * @author    Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.6 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @package   phing.parser   */  abstract class AbstractHandler { diff --git a/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php b/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php index 60cf0c11..449386e7 100644..100755 --- a/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php +++ b/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: AbstractSAXParser.php,v 1.13 2004/03/20 03:33:06 hlellelid Exp $ + *  $Id: 948cef29e65fb684d99cbddc7c633183740a91a8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,8 +27,8 @@   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.13 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @package   phing.parser   */  abstract class AbstractSAXParser { @@ -60,26 +60,18 @@ abstract class AbstractSAXParser {      /**       * Method that gets invoked when the parser runs over a XML start element.       * -     * This method is called by PHP's internal parser funcitons and registered +     * This method is called by PHP's internal parser functions and registered       * in the actual parser implementation.       * It gives control to the current active handler object by calling the       * <code>startElement()</code> method.       *  -     * BECAUSE OF PROBLEMS WITH EXCEPTIONS BUBBLING UP THROUGH xml_parse() THIS -     * METHOD WILL CALL Phing::halt(-1) ON EXCEPTION. -     *       * @param  object  the php's internal parser handle       * @param  string  the open tag name       * @param  array   the tag's attributes if any +     * @throws Exception - Exceptions may be thrown by the Handler       */      function startElement($parser, $name, $attribs) { -        try { -            $this->handler->startElement($name, $attribs);         -        } catch (Exception $e) { -            print "[Exception in XML parsing]\n"; -            print $e; -            Phing::halt(-1); -        } +        $this->handler->startElement($name, $attribs);      }      /** @@ -91,20 +83,12 @@ abstract class AbstractSAXParser {       * It gives control to the current active handler object by calling the       * <code>endElement()</code> method.       * -     * BECAUSE OF PROBLEMS WITH EXCEPTIONS BUBBLING UP THROUGH xml_parse() THIS -     * METHOD WILL CALL Phing::halt(-1) ON EXCEPTION. -     *        * @param   object  the php's internal parser handle       * @param   string  the closing tag name +     * @throws Exception - Exceptions may be thrown by the Handler       */      function endElement($parser, $name) { -        try { -            $this->handler->endElement($name); -        } catch (Exception $e) { -            print "[Exception in XML parsing]\n"; -            print $e; -            Phing::halt(-1); -        } +        $this->handler->endElement($name);      }      /** @@ -116,20 +100,12 @@ abstract class AbstractSAXParser {       * It gives control to the current active handler object by calling the       * <code>characters()</code> method. That processes the given CDATA.       * -     * BECAUSE OF PROBLEMS WITH EXCEPTIONS BUBBLING UP THROUGH xml_parse() THIS -     * METHOD WILL CALL Phing::halt(-1) ON EXCEPTION. -     *        * @param resource $parser php's internal parser handle.       * @param string $data the CDATA +     * @throws Exception - Exceptions may be thrown by the Handler       */      function characters($parser, $data) { -        try {      -            $this->handler->characters($data);         -        } catch (Exception $e) { -            print "[Exception in XML parsing]\n"; -            print $e; -            Phing::halt(-1); -        } +        $this->handler->characters($data);      }      /** diff --git a/buildscripts/phing/classes/phing/parser/DataTypeHandler.php b/buildscripts/phing/classes/phing/parser/DataTypeHandler.php index 37d757c4..7531baaf 100644..100755 --- a/buildscripts/phing/classes/phing/parser/DataTypeHandler.php +++ b/buildscripts/phing/classes/phing/parser/DataTypeHandler.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: DataTypeHandler.php,v 1.8 2005/11/02 13:55:33 hlellelid Exp $ + *  $Id: dbae47cfbf1ad4a3ac68909118f69175cf1d45f4 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,9 +29,9 @@ include_once 'phing/RuntimeConfigurable.php';   * If PHP would support nested classes. All the phing/parser/*Filter   * classes would be nested within this class   * - * @author      Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.8 $ $Date: 2005/11/02 13:55:33 $ + * @author    Andreas Aderhold <andi@binarycloud.com> + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @access    public   * @package   phing.parser   */ diff --git a/buildscripts/phing/classes/phing/parser/ExpatParseException.php b/buildscripts/phing/classes/phing/parser/ExpatParseException.php index d5086c30..65461576 100644..100755 --- a/buildscripts/phing/classes/phing/parser/ExpatParseException.php +++ b/buildscripts/phing/classes/phing/parser/ExpatParseException.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ExpatParseException.php,v 1.5 2003/11/19 05:48:28 hlellelid Exp $ + *  $Id: c384bde6ba2bb6902b1f943e35afd9f8b5d4efd8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ require_once 'phing/BuildException.php';   * This class throws errors for Expat, the XML processor.   *   * @author   Andreas Aderhold, andi@binarycloud.com - * @version  $Revision: 1.5 $ $Date: 2003/11/19 05:48:28 $ + * @version  $Id$   * @package  phing.parser   */  class ExpatParseException extends BuildException {} diff --git a/buildscripts/phing/classes/phing/parser/ExpatParser.php b/buildscripts/phing/classes/phing/parser/ExpatParser.php index 82046f8d..ef5348e5 100644..100755 --- a/buildscripts/phing/classes/phing/parser/ExpatParser.php +++ b/buildscripts/phing/classes/phing/parser/ExpatParser.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ExpatParser.php,v 1.8 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 0363c59b524447dc74014b03d913fa5a25ada33a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -34,9 +34,9 @@ include_once 'phing/system/io/FileReader.php';   * Those methods then invoke the represenatative methods in the registered   * handler classes.   * - * @author      Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.8 $ $Date: 2005/05/26 13:10:52 $ + * @author    Andreas Aderhold <andi@binarycloud.com> + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @access    public   * @package   phing.parser   */ diff --git a/buildscripts/phing/classes/phing/parser/Location.php b/buildscripts/phing/classes/phing/parser/Location.php index fd79866c..4110bd00 100644..100755 --- a/buildscripts/phing/classes/phing/parser/Location.php +++ b/buildscripts/phing/classes/phing/parser/Location.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Location.php,v 1.6 2003/12/24 13:02:09 hlellelid Exp $ + *  $Id: ffb9bc98eef0f4e535f60388d52b7495c539f682 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,9 +22,9 @@  /**   * Stores the file name and line number of a XML file   * - * @author      Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.6 $ $Date: 2003/12/24 13:02:09 $ + * @author    Andreas Aderhold <andi@binarycloud.com> + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @access    public   * @package   phing.parser   */ @@ -69,4 +69,8 @@ class Location {          }          return (string) $buf;      } + +    function __toString () { +      return $this->toString(); +    }  } diff --git a/buildscripts/phing/classes/phing/parser/NestedElementHandler.php b/buildscripts/phing/classes/phing/parser/NestedElementHandler.php index 8ecd0ed3..15d0e173 100644..100755 --- a/buildscripts/phing/classes/phing/parser/NestedElementHandler.php +++ b/buildscripts/phing/classes/phing/parser/NestedElementHandler.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: NestedElementHandler.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $ + *  $Id: 94cdf9380aea8a52cb09663489c2d2c5e28740aa $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,9 +29,9 @@ include_once 'phing/TaskContainer.php';   * datatypes (fileset, patternset, etc) and it's possible nested tags. It   * introspects the implementation of the class and sets up the data structures.   * - * @author      Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.10 $ $Date: 2005/10/04 19:13:44 $ + * @author    Andreas Aderhold <andi@binarycloud.com> + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @access    public   * @package   phing.parser   */ @@ -173,14 +173,14 @@ class NestedElementHandler extends AbstractHandler {       */      function startElement($name, $attrs) {          //print(get_class($this) . " name = $name, attrs = " . implode(",",$attrs) . "\n"); -		if ($this->child instanceof TaskContainer) { +        if ($this->child instanceof TaskContainer) {                  // taskcontainer nested element can contain other tasks - no other                  // nested elements possible -			$tc = new TaskHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target); -			$tc->init($name, $attrs); -		} else { -			$neh = new NestedElementHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target); -        	$neh->init($name, $attrs); -		} +            $tc = new TaskHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target); +            $tc->init($name, $attrs); +        } else { +            $neh = new NestedElementHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target); +            $neh->init($name, $attrs); +        }      }  } diff --git a/buildscripts/phing/classes/phing/parser/PhingXMLContext.php b/buildscripts/phing/classes/phing/parser/PhingXMLContext.php new file mode 100755 index 00000000..0e2dd0f4 --- /dev/null +++ b/buildscripts/phing/classes/phing/parser/PhingXMLContext.php @@ -0,0 +1,81 @@ +<?php +/* + * $Id: bfc85569ff437f8ee382c9dee6fc8eb55ecb9839 $ + * + * 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>. + */ + +/** + * Track the current state of the Xml parse operation. + * + * @author    Bryan Davis <bpd@keynetics.com> + * @version   $Id$ + * @access    public + * @package   phing.parser + */ +class PhingXMLContext { + +    /** +     * Constructor +     * @param $project the project to which this antxml context belongs to +     */ +    public function __construct ($project) { +      $this->project = $project; +    } + +    /** The project to configure. */ +    private $project; + +    private $configurators = array(); + +    public function startConfigure ($cfg) { +      $this->configurators[] = $cfg; +    } + +    public function endConfigure () { +      array_pop($this->configurators); +    } + +    public function getConfigurator () { +      $l = count($this->configurators); +      if (0 == $l) { +        return null; +      } else { +        return $this->configurators[$l - 1]; +      } +    } + +    /** Impoerted files */ +    private $importStack = array(); + +    public function addImport ($file) { +      $this->importStack[] = $file; +    } + +    public function getImportStack () { +      return $this->importStack; +    } + +    /** +     * find out the project to which this context belongs +     * @return project +     */ +    public function getProject() { +        return $this->project; +    } + +} //end PhingXMLContext diff --git a/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php b/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php index 6b69e955..90471336 100644..100755 --- a/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php +++ b/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: ProjectConfigurator.php,v 1.17 2006/01/06 14:57:18 hlellelid Exp $ + * $Id: ae9b63bef4c1423d88bb36ddfc5196763828123e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,6 +24,8 @@ include_once 'phing/system/io/FileReader.php';  include_once 'phing/BuildException.php';  include_once 'phing/system/lang/FileNotFoundException.php';  include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/parser/PhingXMLContext.php'; +include_once 'phing/IntrospectionHelper.php';  /**   * The datatype handler class. @@ -31,9 +33,9 @@ include_once 'phing/system/io/PhingFile.php';   * This class handles the occurance of registered datatype tags like   * FileSet   * - * @author      Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.17 $ $Date: 2006/01/06 14:57:18 $ + * @author    Andreas Aderhold <andi@binarycloud.com> + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id: ae9b63bef4c1423d88bb36ddfc5196763828123e $   * @access    public   * @package   phing.parser   */ @@ -44,7 +46,24 @@ class ProjectConfigurator {      public $buildFile;      public $buildFileParent; -         + +    /** Targets in current file */ +    private $currentTargets; + +    /** Synthetic target that will be called at the end to the parse phase */ +    private $parseEndTarget; + +    /** Name of the current project */ +    private $currentProjectName; + +    private $isParsing = true; + +    /** +     * Indicates whether the project tag attributes are to be ignored +     * when processing a particular build file. +     */ +    private $ignoreProjectTag = false; +      /**       * Static call to ProjectConfigurator. Use this to configure a       * project. Do not use the new operator. @@ -71,6 +90,64 @@ class ProjectConfigurator {          $this->project = $project;          $this->buildFile = new PhingFile($buildFile->getAbsolutePath());          $this->buildFileParent = new PhingFile($this->buildFile->getParent()); +        $this->currentTargets = array(); +        $this->parseEndTarget = new Target(); +    } + +    /** +     * find out the build file +     * @return  the build file to which the xml context belongs +     */ +    public function getBuildFile() { +        return $this->buildFile; +    } + +    /** +     * find out the parent build file of this build file +     * @return the parent build file of this build file +     */ +    public function getBuildFileParent() { +        return $this->buildFileParent; +    } + +    /** +     * find out the current project name +     * @return current project name +     */ +    public function getCurrentProjectName() { +        return $this->currentProjectName; +    } + +    /** +     * set the name of the current project +     * @param name name of the current project +     */ +    public function setCurrentProjectName($name) { +        $this->currentProjectName = $name; +    } + +    /** +     * tells whether the project tag is being ignored +     * @return whether the project tag is being ignored +     */ +    public function isIgnoringProjectTag() { +        return $this->ignoreProjectTag; +    } + +    /** +     *  sets the flag to ignore the project tag +     * @param flag to ignore the project tag +     */ +    public function setIgnoreProjectTag($flag) { +        $this->ignoreProjectTag = $flag; +    } + +    public function &getCurrentTargets () { +      return $this->currentTargets; +    } + +    public function isParsing () { +      return $this->isParsing;      }      /** @@ -82,21 +159,56 @@ class ProjectConfigurator {       * @access private       */      protected function parse() { -        try { +      try { +        // get parse context +        $ctx = $this->project->getReference("phing.parsing.context"); +        if (null == $ctx) { +          // make a new context and register it with project +          $ctx = new PhingXMLContext($this->project); +          $this->project->addReference("phing.parsing.context", $ctx); +        } + +        //record this parse with context +        $ctx->addImport($this->buildFile); + +        if (count($ctx->getImportStack()) > 1) { +          // this is an imported file +          // modify project tag parse behavior +          $this->setIgnoreProjectTag(true); +        } +        // push action onto global stack +        $ctx->startConfigure($this); +              $reader = new BufferedReader(new FileReader($this->buildFile)); -            $reader->open();              $parser = new ExpatParser($reader);              $parser->parserSetOption(XML_OPTION_CASE_FOLDING,0);              $parser->setHandler(new RootHandler($parser, $this)); -            $this->project->log("parsing buildfile ".$this->buildFile->getName(), PROJECT_MSG_VERBOSE); +            $this->project->log("parsing buildfile ".$this->buildFile->getName(), Project::MSG_VERBOSE);              $parser->parse();              $reader->close(); + +            // mark parse phase as completed +            $this->isParsing = false; +            // execute delayed tasks +            $this->parseEndTarget->main(); +            // pop this action from the global stack +            $ctx->endConfigure();          } catch (Exception $exc) {              throw new BuildException("Error reading project file", $exc);          }      }      /** +     * Delay execution of a task until after the current parse phase has  +     * completed. +     * +     * @param Task $task Task to execute after parse +     */ +    public function delayTaskUntilParseEnd ($task) { +      $this->parseEndTarget->addTask($task); +    } + +    /**       * Configures an element and resolves eventually given properties.       *       * @param  object  the element to configure @@ -106,22 +218,22 @@ class ProjectConfigurator {       * @throws BuildException if attributes can not be configured       * @access public       */ -    function configure($target, $attrs, Project $project) {                +    public static function configure($target, $attrs, Project $project) {                         if ($target instanceof TaskAdapter) {              $target = $target->getProxy();          } -		// if the target is an UnknownElement, this means that the tag had not been registered -		// when the enclosing element (task, target, etc.) was configured.  It is possible, however,  -		// that the tag was registered (e.g. using <taskdef>) after the original configuration. -		// ... so, try to load it again: -		if ($target instanceof UnknownElement) { -			$tryTarget = $project->createTask($target->getTaskType()); -			if ($tryTarget) { -				$target = $tryTarget; -			} -		} +        // if the target is an UnknownElement, this means that the tag had not been registered +        // when the enclosing element (task, target, etc.) was configured.  It is possible, however,  +        // that the tag was registered (e.g. using <taskdef>) after the original configuration. +        // ... so, try to load it again: +        if ($target instanceof UnknownElement) { +            $tryTarget = $project->createTask($target->getTaskType()); +            if ($tryTarget) { +                $target = $tryTarget; +            } +        }          $bean = get_class($target);          $ih = IntrospectionHelper::getHelper($bean); @@ -151,7 +263,7 @@ class ProjectConfigurator {       * @param  string  the element's #CDATA       * @access public       */ -    function addText($project, $target, $text = null) { +    public static function addText($project, $target, $text = null) {          if ($text === null || strlen(trim($text)) === 0) {              return;          }     @@ -169,12 +281,12 @@ class ProjectConfigurator {       * @param  string  the XML tagname       * @access public       */ -    function storeChild($project, $parent, $child, $tag) { +    public static function storeChild($project, $parent, $child, $tag) {          $ih = IntrospectionHelper::getHelper(get_class($parent));          $ih->storeElement($project, $parent, $child, $tag);      } -    // The following two properties are a sort of hack +    // The following three properties are a sort of hack      // to enable a static function to serve as the callback      // for preg_replace_callback().  Clearly we cannot use object      // variables, since the replaceProperties() is called statically. @@ -182,19 +294,21 @@ class ProjectConfigurator {      private static $propReplaceProject;      private static $propReplaceProperties; +    private static $propReplaceLogLevel = Project::MSG_VERBOSE;      /**       * Replace ${} style constructions in the given value with the       * string value of the corresponding data types. This method is       * static.       * -     * @param  object  the project that should be used for property look-ups -     * @param  string  the string to be scanned for property references -     * @param  array   proeprty keys +     * @param  object  $project  the project that should be used for property look-ups +     * @param  string  $value    the string to be scanned for property references +     * @param  array   $keys     property keys +     * @param  integer $logLevel the level of generated log messages       * @return string  the replaced string or <code>null</code> if the string       *                 itself was null       */ -    public static function replaceProperties(Project $project, $value, $keys) { +    public static function replaceProperties(Project $project, $value, $keys, $logLevel = Project::MSG_VERBOSE) {          if ($value === null) {              return null; @@ -205,13 +319,29 @@ class ProjectConfigurator {          // make sure these get initialized every time                  self::$propReplaceProperties = $keys;          self::$propReplaceProject = $project; +        self::$propReplaceLogLevel = $logLevel;          // Because we're not doing anything special (like multiple passes),          // regex is the simplest / fastest.  PropertyTask, though, uses          // the old parsePropertyString() method, since it has more stringent          // requirements. + +        $sb = $value; +        $iteration = 0; +         +        // loop to recursively replace tokens +        while (strpos($sb, '${') !== false) +        {  +            $sb = preg_replace_callback('/\$\{([^\$}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $sb); + +            // keep track of iterations so we can break out of otherwise infinite loops. +            $iteration++; +            if ($iteration == 5) +            { +                return $sb; +            } +        } -        $sb = preg_replace_callback('/\$\{([^}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $value);          return $sb;              } @@ -223,12 +353,23 @@ class ProjectConfigurator {      {          $propertyName = $matches[1];          if (!isset(self::$propReplaceProperties[$propertyName])) { -                    self::$propReplaceProject->log('Property ${'.$propertyName.'} has not been set.', PROJECT_MSG_VERBOSE); -                    return $matches[0]; +            self::$propReplaceProject->log('Property ${'.$propertyName.'} has not been set.', self::$propReplaceLogLevel); +            return $matches[0];          } else { -			self::$propReplaceProject->log('Property ${'.$propertyName.'} => ' . self::$propReplaceProperties[$propertyName], PROJECT_MSG_DEBUG); -		} -        return self::$propReplaceProperties[$propertyName]; +            self::$propReplaceProject->log('Property ${'.$propertyName.'} => ' . self::$propReplaceProperties[$propertyName], self::$propReplaceLogLevel); +        } +         +        $propertyValue = self::$propReplaceProperties[$propertyName]; +         +        if (is_bool($propertyValue)) { +            if ($propertyValue === true) { +                $propertyValue = "true"; +            } else { +                $propertyValue = "false"; +            } +        } +         +        return $propertyValue;      }                 /** @@ -238,7 +379,7 @@ class ProjectConfigurator {       * @param object the element's object       * @param array  the element's attributes       */ -    function configureId(&$target, $attr) { +    public function configureId($target, $attr) {          if (isset($attr['id']) && $attr['id'] !== null) {              $this->project->addReference($attr['id'], $target);          } diff --git a/buildscripts/phing/classes/phing/parser/ProjectHandler.php b/buildscripts/phing/classes/phing/parser/ProjectHandler.php index 54486ec9..a027c1e6 100644..100755 --- a/buildscripts/phing/classes/phing/parser/ProjectHandler.php +++ b/buildscripts/phing/classes/phing/parser/ProjectHandler.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: ProjectHandler.php,v 1.14 2005/10/04 19:13:44 hlellelid Exp $ + * $Id: 393b1f3d8758281af2fd0153ffc6151333457527 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@ require_once 'phing/system/io/PhingFile.php';   *   * @author      Andreas Aderhold <andi@binarycloud.com>   * @copyright (c) 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.14 $ $Date: 2005/10/04 19:13:44 $ + * @version   $Id: 393b1f3d8758281af2fd0153ffc6151333457527 $   * @access    public   * @package   phing.parser   */ @@ -67,7 +67,9 @@ class ProjectHandler extends AbstractHandler {          $def = null;          $name = null;          $id    = null; +        $desc = null;          $baseDir = null; +        $ver = null;          // some shorthands          $project = $this->configurator->project; @@ -82,38 +84,62 @@ class ProjectHandler extends AbstractHandler {                  $id = $value;              } elseif ($key === "basedir") {                  $baseDir = $value; +            } elseif ($key === "description") { +                $desc = $value; +            } elseif ($key === "phingVersion") { +                $ver = $value;              } else {                  throw new ExpatParseException("Unexpected attribute '$key'");              }          } -        if ($def === null) { -            throw new ExpatParseException("The default attribute of project is required"); +        // these things get done no matter what +        if (null != $name) { +          $canonicalName = self::canonicalName($name); +          $this->configurator->setCurrentProjectName($canonicalName); +          $project->setUserProperty("phing.file.{$canonicalName}", +              (string) $this->configurator->getBuildFile());          } -        $project->setDefaultTarget($def); -        if ($name !== null) { +        if (!$this->configurator->isIgnoringProjectTag()) { +          if ($def === null) { +            throw new ExpatParseException( +                "The default attribute of project is required"); +          } +          $project->setDefaultTarget($def); + +          if ($name !== null) {              $project->setName($name);              $project->addReference($name, $project); -        } -        if ($id !== null) { +          } + +          if ($id !== null) {              $project->addReference($id, $project); -        } +          } + +          if ($desc !== null) { +            $project->setDescription($desc); +          }         -        if ($project->getProperty("project.basedir") !== null) { +          if($ver !== null) { +              $project->setPhingVersion($ver); +          } + +          if ($project->getProperty("project.basedir") !== null) {              $project->setBasedir($project->getProperty("project.basedir")); -        } else { +          } else {              if ($baseDir === null) { -                $project->setBasedir($buildFileParent->getAbsolutePath()); +              $project->setBasedir($buildFileParent->getAbsolutePath());              } else { -                // check whether the user has specified an absolute path -                $f = new PhingFile($baseDir); -                if ($f->isAbsolute()) { -                    $project->setBasedir($baseDir); -                } else { -                    $project->setBaseDir($project->resolveFile($baseDir, $buildFileParent)); -                } +              // check whether the user has specified an absolute path +              $f = new PhingFile($baseDir); +              if ($f->isAbsolute()) { +                $project->setBasedir($baseDir); +              } else { +                $project->setBaseDir($project->resolveFile($baseDir, new PhingFile(getcwd()))); +              }              } +          }          }      } @@ -128,19 +154,23 @@ class ProjectHandler extends AbstractHandler {       */      function startElement($name, $attrs) { -		$project = $this->configurator->project; +        $project = $this->configurator->project;          $types = $project->getDataTypeDefinitions(); -		 -		if ($name == "target") { -			$tf = new TargetHandler($this->parser, $this, $this->configurator); -			$tf->init($name, $attrs); -		} elseif (isset($types[$name])) { +         +        if ($name == "target") { +            $tf = new TargetHandler($this->parser, $this, $this->configurator); +            $tf->init($name, $attrs); +        } elseif (isset($types[$name])) {             $tyf = new DataTypeHandler($this->parser, $this, $this->configurator);             $tyf->init($name, $attrs);          } else { -			$tf = new TaskHandler($this->parser, $this, $this->configurator); -			$tf->init($name, $attrs); +            $tf = new TaskHandler($this->parser, $this, $this->configurator); +            $tf->init($name, $attrs);          }      } + +    static function canonicalName ($name) { +      return preg_replace('/\W/', '_', strtolower($name)); +    }  } diff --git a/buildscripts/phing/classes/phing/parser/RootHandler.php b/buildscripts/phing/classes/phing/parser/RootHandler.php index 28afb5d5..435aae40 100644..100755 --- a/buildscripts/phing/classes/phing/parser/RootHandler.php +++ b/buildscripts/phing/classes/phing/parser/RootHandler.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: RootHandler.php,v 1.7 2003/12/24 13:02:09 hlellelid Exp $ + *  $Id: 061d3ffe06257d551822050020d0e64689663334 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -30,8 +30,8 @@ include_once 'phing/parser/ProjectHandler.php';   * specific parsing starts. RootHandler decides what to do next.   *   * @author    Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.7 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id$   * @package   phing.parser   */  class RootHandler extends AbstractHandler { diff --git a/buildscripts/phing/classes/phing/parser/TargetHandler.php b/buildscripts/phing/classes/phing/parser/TargetHandler.php index 7ca94b44..a6c4d037 100644..100755 --- a/buildscripts/phing/classes/phing/parser/TargetHandler.php +++ b/buildscripts/phing/classes/phing/parser/TargetHandler.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: TargetHandler.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $ + * $Id: f73d7c67a353cf16f048af3ba013d84ec726a926 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ require_once 'phing/parser/AbstractHandler.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @copyright  2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.10 $ + * @version   $Id: f73d7c67a353cf16f048af3ba013d84ec726a926 $   * @package   phing.parser   */  class TargetHandler extends AbstractHandler { @@ -82,6 +82,7 @@ class TargetHandler extends AbstractHandler {          $unlessCond = null;          $id = null;          $description = null; +        $isHidden = false;          foreach($attrs as $key => $value) {              if ($key==="name") { @@ -94,6 +95,8 @@ class TargetHandler extends AbstractHandler {                  $unlessCond = (string) $value;              } else if ($key==="id") {                  $id = (string) $value; +            } else if ($key==="hidden") { +                $isHidden = ($value == 'true' || $value == '1') ? true : false;              } else if ($key==="description") {                  $description = (string)$value;              } else { @@ -108,22 +111,54 @@ class TargetHandler extends AbstractHandler {          // shorthand          $project = $this->configurator->project; +        // check to see if this target is a dup within the same file +        if (isset($this->configurator->getCurrentTargets[$name])) { +          throw new BuildException("Duplicate target: $targetName",   +              $this->parser->getLocation()); +        } +          $this->target = new Target();          $this->target->setName($name); +        $this->target->setHidden($isHidden);          $this->target->setIf($ifCond);          $this->target->setUnless($unlessCond);          $this->target->setDescription($description); - -        $project->addTarget($name, $this->target); - -        if ($id !== null && $id !== "") { -            $project->addReference($id, $this->target); -        }          // take care of dependencies          if (strlen($depends) > 0) {              $this->target->setDepends($depends);          } +        $usedTarget = false; +        // check to see if target with same name is already defined +        $projectTargets = $project->getTargets(); +        if (isset($projectTargets[$name])) { +          $project->log("Already defined in main or a previous import, " . +            "ignore {$name}", Project::MSG_VERBOSE); +        } else { +          $project->addTarget($name, $this->target); +          if ($id !== null && $id !== "") { +            $project->addReference($id, $this->target); +          } +          $usedTarget = true; +        } + +        if ($this->configurator->isIgnoringProjectTag() &&  +            $this->configurator->getCurrentProjectName() != null &&  +            strlen($this->configurator->getCurrentProjectName()) != 0) { +          // In an impored file (and not completely +          // ignoring the project tag) +          $newName = $this->configurator->getCurrentProjectName() . "." . $name; +          if ($usedTarget) { +            // clone needs to make target->children a shared reference +            $newTarget = clone $this->target; +          } else { +            $newTarget = $this->target; +          } +          $newTarget->setName($newName); +          $ct = $this->configurator->getCurrentTargets(); +          $ct[$newName] = $newTarget; +          $project->addTarget($newName, $newTarget); +        }      }      /** @@ -146,4 +181,16 @@ class TargetHandler extends AbstractHandler {              $tmp->init($name, $attrs);          }      } +     +    /** +     * Checks if this target has dependencies and/or nested tasks. +     * If the target has neither, show a warning. +     */ +    protected function finished() +    { +        if (!count($this->target->getDependencies()) && !count($this->target->getTasks())) { +            $this->configurator->project->log("Warning: target '" . $this->target->getName() . +                "' has no tasks or dependencies", Project::MSG_WARN); +        } +    }  } diff --git a/buildscripts/phing/classes/phing/parser/TaskHandler.php b/buildscripts/phing/classes/phing/parser/TaskHandler.php index 976aebf2..53e07a56 100644..100755 --- a/buildscripts/phing/classes/phing/parser/TaskHandler.php +++ b/buildscripts/phing/classes/phing/parser/TaskHandler.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TaskHandler.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $ + *  $Id: 3b31bb3e2c1ae122411833c67617e7cebf6967b8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,9 +28,9 @@ include_once 'phing/UnknownElement.php';   * nested tags (datatypes and tasks) that may be unknown off bat and are   * initialized on the fly.   * - * @author      Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.10 $ + * @author    Andreas Aderhold <andi@binarycloud.com> + * @copyright 2001,2002 THYRELL. All rights reserved + * @version   $Id: 3b31bb3e2c1ae122411833c67617e7cebf6967b8 $   * @package   phing.parser   */  class TaskHandler extends AbstractHandler { @@ -55,20 +55,20 @@ class TaskHandler extends AbstractHandler {       * @var Task       */      private $task; -	 -	/** - 	 * Wrapper for the parent element, if any. The wrapper for this -	 * element will be added to this wrapper as a child. -	 * @var RuntimeConfigurable -	 */ -	private $parentWrapper; -	 -	/** -	 * Wrapper for this element which takes care of actually configuring -	 * the element, if this element is contained within a target. -	 * Otherwise the configuration is performed with the configure method. -	 * @see ProjectHelper::configure(Object,AttributeList,Project) -	 */ +     +    /** +     * Wrapper for the parent element, if any. The wrapper for this +     * element will be added to this wrapper as a child. +     * @var RuntimeConfigurable +     */ +    private $parentWrapper; +     +    /** +     * Wrapper for this element which takes care of actually configuring +     * the element, if this element is contained within a target. +     * Otherwise the configuration is performed with the configure method. +     * @see ProjectHelper::configure(Object,AttributeList,Project) +     */      private $wrapper;      /** @@ -84,7 +84,7 @@ class TaskHandler extends AbstractHandler {       * @param object $parentHandler The parent handler that invoked this handler       * @param ProjectConfigurator $configurator       * @param TaskContainer $container The container object this task is contained in (null for top-level tasks). -	 * @param RuntimeConfigurable $parentWrapper  Wrapper for the parent element, if any. +     * @param RuntimeConfigurable $parentWrapper  Wrapper for the parent element, if any.       * @param Target $target The target object this task is contained in (null for top-level tasks).       */      function __construct(AbstractSAXParser $parser, $parentHandler, ProjectConfigurator $configurator, $container = null, $parentWrapper = null, $target = null) { @@ -94,16 +94,16 @@ class TaskHandler extends AbstractHandler {          if (($container !== null) && !($container instanceof TaskContainer)) {              throw new Exception("Argument expected to be a TaskContainer, got something else");          } -		if (($parentWrapper !== null) && !($parentWrapper instanceof RuntimeConfigurable)) { +        if (($parentWrapper !== null) && !($parentWrapper instanceof RuntimeConfigurable)) {              throw new Exception("Argument expected to be a RuntimeConfigurable, got something else.");          }          if (($target !== null) && !($target instanceof Target)) {              throw new Exception("Argument expected to be a Target, got something else");          } -		$this->configurator = $configurator; +        $this->configurator = $configurator;          $this->container = $container; -		$this->parentWrapper = $parentWrapper; +        $this->parentWrapper = $parentWrapper;          $this->target = $target;      } @@ -149,25 +149,30 @@ class TaskHandler extends AbstractHandler {          // add file position information to the task (from parser)          // should be used in task exceptions to provide details          $this->task->setLocation($this->parser->getLocation()); -        $configurator->configureId($task, $attrs); -		 -		if ($this->container) { -			$this->container->addTask($this->task); -		} -		 +        $configurator->configureId($this->task, $attrs); +         +        if ($this->container) { +            $this->container->addTask($this->task); +        } +                  // Top level tasks don't have associated targets -		// FIXME: if we do like Ant 1.6 and create an implicitTarget in the projectconfigurator object -		// then we don't need to check for null here ... but there's a lot of stuff that will break if we -		// do that at this point. +        // FIXME: if we do like Ant 1.6 and create an implicitTarget in the projectconfigurator object +        // then we don't need to check for null here ... but there's a lot of stuff that will break if we +        // do that at this point.          if ($this->target !== null) {              $this->task->setOwningTarget($this->target);              $this->task->init();              $this->wrapper = $this->task->getRuntimeConfigurableWrapper();              $this->wrapper->setAttributes($attrs); -			if ($this->parentWrapper !== null) { // this may not make sense only within this if-block, but it -												// seems to address current use cases adequately -		    	$this->parentWrapper->addChild($this->wrapper); -			} +            /* +            Commenting this out as per thread on Premature configurate of ReuntimeConfigurables  +            with Matthias Pigulla: http://phing.tigris.org/servlets/ReadMsg?list=dev&msgNo=251 +             +            if ($this->parentWrapper !== null) { // this may not make sense only within this if-block, but it +                                                // seems to address current use cases adequately +                $this->parentWrapper->addChild($this->wrapper); +            } +            */          } else {              $this->task->init();              $configurator->configure($this->task, $attrs, $project); @@ -178,11 +183,11 @@ class TaskHandler extends AbstractHandler {       * Executes the task at once if it's directly beneath the <project> tag.       */      protected function finished() { -        if ($this->task !== null && $this->target === null) { +        if ($this->task !== null && $this->target === null && $this->container === null) {              try { -                $this->task->main(); +                $this->task->perform();              } catch (Exception $e) { -                $this->task->log($e->getMessage(), PROJECT_MSG_ERR); +                $this->task->log($e->getMessage(), Project::MSG_ERR);                  throw $e;              }          } diff --git a/buildscripts/phing/classes/phing/system/io/BufferedReader.php b/buildscripts/phing/classes/phing/system/io/BufferedReader.php index 4946985c..a392f5be 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/BufferedReader.php +++ b/buildscripts/phing/classes/phing/system/io/BufferedReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: BufferedReader.php,v 1.6 2005/12/27 19:12:13 hlellelid Exp $ + *  $Id: 98ea5952d7a41ce47ce95008e336f38758946aaa $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,15 +21,15 @@  include_once 'phing/system/io/Reader.php'; -/* +/**   * Convenience class for reading files.   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> - * @version   $Revision: 1.6 $ $Date: 2005/12/27 19:12:13 $ + * @version   $Id$   * @access    public   * @see       FilterReader   * @package   phing.system.io -*/ + */  class BufferedReader extends Reader {      private $bufferSize = 0; @@ -53,37 +53,36 @@ class BufferedReader extends Reader {      }      /** -     * Reads and returns $_bufferSize chunk of data. +     * Reads and returns a chunk of data. +     * @param int $len Number of bytes to read.  Default is to read configured buffer size number of bytes.       * @return mixed buffer or -1 if EOF.       */      function read($len = null) { -        // ignore $len param, not sure how to hanlde it, since  -        // this should only read bufferSize amount of data. -        if ($len !== null) { -            $this->currentPosition = ftell($this->fd); -        } -        if ( ($data = $this->in->read($this->bufferSize)) !== -1 ) { -		 -			// not all files end with a newline character, so we also need to check EOF -			if (!$this->in->eof()) { -			 -	            $notValidPart = strrchr($data, "\n"); -	            $notValidPartSize = strlen($notValidPart); -	         -	            if ( $notValidPartSize > 1 ) { -	                // Block doesn't finish on a EOL -	                // Find the last EOL and forgot all following stuff -	                $dataSize = strlen($data); -	                $validSize = $dataSize - $notValidPartSize + 1; -	             -	                $data = substr($data, 0, $validSize); -	 -	                // Rewind to the begining of the forgotten stuff. -	                $this->in->skip(-$notValidPartSize+1); -	            } -				 -			} // if !EOF +        // if $len is specified, we'll use that; otherwise, use the configured buffer size. +        if ($len === null) $len = $this->bufferSize;  +         +        if ( ($data = $this->in->read($len)) !== -1 ) { +         +            // not all files end with a newline character, so we also need to check EOF +            if (!$this->in->eof()) { +             +                $notValidPart = strrchr($data, "\n"); +                $notValidPartSize = strlen($notValidPart); +             +                if ( $notValidPartSize > 1 ) { +                    // Block doesn't finish on a EOL +                    // Find the last EOL and forget all following stuff +                    $dataSize = strlen($data); +                    $validSize = $dataSize - $notValidPartSize + 1; +                 +                    $data = substr($data, 0, $validSize); +     +                    // Rewind to the begining of the forgotten stuff. +                    $this->in->skip(-$notValidPartSize+1); +                } +                 +            } // if !EOF          }          return $data;      } @@ -167,4 +166,3 @@ class BufferedReader extends Reader {          return $this->in->getResource();      }      } -?> diff --git a/buildscripts/phing/classes/phing/system/io/BufferedWriter.php b/buildscripts/phing/classes/phing/system/io/BufferedWriter.php index c982db28..88520ce9 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/BufferedWriter.php +++ b/buildscripts/phing/classes/phing/system/io/BufferedWriter.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: BufferedWriter.php,v 1.10 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 8a155d3b04ca1a938bc22f59aba8509e0910ad33 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ include_once 'phing/system/io/Writer.php';   * Convenience class for writing files.   *   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.10 $ + * @version   $Id$   * @package   phing.system.io    */  class BufferedWriter extends Writer { @@ -36,37 +36,36 @@ class BufferedWriter extends Writer {      private $bufferSize    = 0;      /** -     * The Writer we are buffering output to. +     * @var Writer The Writer we are buffering output to.       */      private $out; -    function __construct(Writer $writer, $buffsize = 8192) { +    public function __construct(Writer $writer, $buffsize = 8192) {          $this->out = $writer;          $this->bufferSize = $buffsize;      } -    function write($buf, $off = null, $len = null) { +    public function write($buf, $off = null, $len = null) {          return $this->out->write($buf, $off, $len);      } -    function newLine() { -        $this->write(Phing::getProperty('line.separator')); +    public function newLine() { +        $this->write(PHP_EOL);      } -    function getResource() { +    public function getResource() {          return $this->out->getResource();      } - -    function reset() { -        return $this->out->reset(); -    } -    function close() { -        return $this->out->close(); +    public function flush() { +        $this->out->flush();      } -    function open() { -        return $this->out->open(); +    /** +     * Close attached stream. +     */ +    public function close() { +        return $this->out->close();      }  } diff --git a/buildscripts/phing/classes/phing/system/io/ConsoleReader.php b/buildscripts/phing/classes/phing/system/io/ConsoleReader.php index 33b37619..048f1866 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/ConsoleReader.php +++ b/buildscripts/phing/classes/phing/system/io/ConsoleReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ConsoleReader.php,v 1.4 2004/08/12 16:26:12 matthewh Exp $ + *  $Id: 7abe7afba50cc541e695c323da811186549ba1d9 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ include_once 'phing/system/io/Reader.php';   *    * @author Hans Lellelid <hans@xmpl.org>   * @author Matthew Hershberger <matthewh@lightsp.com> - * @version $Revision: 1.4 $ + * @version $Id$   * @package phing.system.io   */  class ConsoleReader extends Reader { @@ -58,11 +58,11 @@ class ConsoleReader extends Reader {      }         function close() { -		// STDIN is always open +        // STDIN is always open      }      function open() { -		// STDIN is always open +        // STDIN is always open      }      /** @@ -81,4 +81,4 @@ class ConsoleReader extends Reader {          return "console";      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/FileInputStream.php b/buildscripts/phing/classes/phing/system/io/FileInputStream.php new file mode 100644 index 00000000..64778860 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/FileInputStream.php @@ -0,0 +1,79 @@ +<?php +/* + *  $Id: 9ddd30a90f5a934a1294f912ae881a4523b74e18 $   + *  + * 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/system/io/InputStream.php'; +require_once 'phing/system/io/PhingFile.php'; + +/** + * Input stream subclass for file streams. + *  + * @package   phing.system.io + */ +class FileInputStream extends InputStream { +     +    /** +     * The associated file. +     * @var PhingFile +     */ +    protected $file; +     +    /** +     * Construct a new FileInputStream. +     *  +     * @param PhingFile|string $file Path to the file +     * @param boolean $append Whether to append (ignored) +     * @throws Exception - if invalid argument specified. +     * @throws IOException - if unable to open file. +     */ +    public function __construct($file, $append = false) { +        if ($file instanceof PhingFile) { +            $this->file = $file; +        } elseif (is_string($file)) { +            $this->file = new PhingFile($file); +        } else { +            throw new Exception("Invalid argument type for \$file."); +        } +         +        $stream = @fopen($this->file->getAbsolutePath(), "rb"); +        if ($stream === false) { +            throw new IOException("Unable to open " . $this->file->__toString() . " for reading: " . $php_errormsg); +        } +         +        parent::__construct($stream); +    } +     +    /** +     * Returns a string representation of the attached file. +     * @return string +     */ +    public function __toString() { +        return $this->file->getPath(); +    } +     +    /** +     * Mark is supported by FileInputStream. +     * @return boolean TRUE +     */ +    public function markSupported() { +        return true; +    } +} + diff --git a/buildscripts/phing/classes/phing/system/io/FileOutputStream.php b/buildscripts/phing/classes/phing/system/io/FileOutputStream.php new file mode 100644 index 00000000..35457d17 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/FileOutputStream.php @@ -0,0 +1,71 @@ +<?php +/* + *  $Id: 9c9b6bc291caf11baf9d5eeef38c50bf155b2099 $   + *  + * 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/system/io/OutputStream.php'; +require_once 'phing/system/io/PhingFile.php'; + +/** + * Output stream subclass for file streams. + *  + * @package   phing.system.io + */ +class FileOutputStream extends OutputStream { +     +    /** +     * @var PhingFile The associated file. +     */ +    protected $file; +     +    /** +     * Construct a new FileOutputStream. +     * @param mixed $file +     * @param boolean $append Whether to append bytes to end of file rather than beginning. +     * @throws Exception - if invalid argument specified. +     * @throws IOException - if unable to open file. +     */ +    public function __construct($file, $append = false) { +        if ($file instanceof PhingFile) { +            $this->file = $file; +        } elseif (is_string($file)) { +            $this->file = new PhingFile($file); +        } else { +            throw new Exception("Invalid argument type for \$file."); +        } +        if ($append) { +            $stream = @fopen($this->file->getAbsolutePath(), "ab"); +        } else { +            $stream = @fopen($this->file->getAbsolutePath(), "wb"); +        } +        if ($stream === false) { +            throw new IOException("Unable to open " . $this->file->__toString() . " for writing: " . $php_errormsg); +        } +        parent::__construct($stream); +    } +     +    /** +     * Returns a string representation of the attached file. +     * @return string +     */ +    public function __toString() { +        return $this->file->getPath(); +    } +} + diff --git a/buildscripts/phing/classes/phing/system/io/FileReader.php b/buildscripts/phing/classes/phing/system/io/FileReader.php index cbea2c7e..43ebda69 100644 --- a/buildscripts/phing/classes/phing/system/io/FileReader.php +++ b/buildscripts/phing/classes/phing/system/io/FileReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FileReader.php,v 1.9 2005/05/26 13:10:52 mrook Exp $ + *  $Id: e7142ab98e9562743781ba0cc4005e08fd62ae83 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -18,162 +18,24 @@   * and is licensed under the LGPL. For more information please see   * <http://phing.info>.    */ -  -include_once 'phing/system/io/PhingFile.php'; -include_once 'phing/system/io/Reader.php'; + +require_once 'phing/system/io/InputStreamReader.php'; +require_once 'phing/system/io/FileInputStream.php';  /** - * Convenience class for reading files. The constructor of this - *  @package   phing.system.io + * Convenience class for reading files. + * @package   phing.system.io   */ +class FileReader extends InputStreamReader { -class FileReader extends Reader { - -    protected $file; -    protected $fd; - -    protected $currentPosition = 0; -    protected $mark = 0; - -    function __construct($file, $exclusive = false) { -     -        if ($file instanceof PhingFile) { -            $this->file = $file; -        } elseif (is_string($file)) { -            $this->file = new PhingFile($file); -        } else { -            throw new Exception("Illegal argument type to " . __METHOD__); -        } -    } - -    function skip($n) { -        $this->open(); - -        $start = $this->currentPosition; - -        $ret = @fseek($this->fd, $n, SEEK_CUR); -        if ( $ret === -1 ) -            return -1; - -        $this->currentPosition = ftell($this->fd); - -        if ( $start > $this->currentPosition ) -            $skipped = $start - $this->currentPosition; -        else -            $skipped = $this->currentPosition - $start; - -        return $skipped; -    } -          /** -     * Read data from file. -     * @param int $len Num chars to read. -     * @return string chars read or -1 if eof. +     * Construct a new FileReader. +     * @param mixed $file PhingFile or string pathname.       */ -    function read($len = null) { -        $this->open(); -        if (feof($this->fd)) { -            return -1; -        } - -        // Compute length to read -        // possible that filesize($this->file) will be larger than  -        // available bytes to read, but that's fine -- better to err on high end -        $length = ($len === null) ? filesize($this->file->getAbsolutePath()) : $len; - -        // Read data -        $out = fread($this->fd, $length + 1); // adding 1 seems to ensure that next call to read() will return EOF (-1) -        $this->currentPosition = ftell($this->fd); - -        return $out; -    }     -     -    function mark($n = null) { -        $this->mark = $this->currentPosition; -    } -     -    function reset() { -        // goes back to last mark, by default this would be 0 (i.e. rewind file). -        fseek($this->fd, SEEK_SET, $this->mark); -        $this->mark = 0; -    } - -    function close() { -        if ($this->fd === null) { -            return true; -        } - -        if (false === @fclose($this->fd)) { -            // FAILED. -            $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg"; -            throw new IOException($msg); -        } else { -            $this->fd = null; -            return true; -        } +    public function __construct($file) { +        $in = new FileInputStream($file); +        parent::__construct($in);      } - -    function open() { -        global $php_errormsg; -        if ($this->fd === null) { -            $this->fd = @fopen($this->file->getAbsolutePath(), "rb"); -        } - -        if ($this->fd === false) { -            // fopen FAILED. -            // Add error from php to end of log message. $php_errormsg. -            $msg = "Cannot fopen ".$this->file->getAbsolutePath().". $php_errormsg"; -            throw new IOException($msg); -        } - -        if (false) { -            // Locks don't seem to work on windows??? HELP!!!!!!!!! -            // if (FALSE === @flock($fp, LOCK_EX)) { // FAILED. -            $msg = "Cannot acquire flock on $file. $php_errormsg"; -            throw new IOException($msg); -        } - -        return true; -    } - -    /** -     * Whether eof has been reached with stream. -     * @return boolean -     */ -    function eof() { -        return feof($this->fd); -    } -      -    /** -     * Reads a entire file and stores the data in the variable -     * passed by reference. -     * -     * @param    string $file    String. Path and/or name of file to read. -     * @param    object &$rBuffer    Reference. Variable of where to put contents. -     * -     * @return    TRUE on success. Err object on failure. -     * @author  Charlie Killian, charlie@tizac.com -     */ -    function readInto(&$rBuffer) { - -        $this->open(); - -        $fileSize = $this->file->length(); -        if ($fileSize === false) { -            $msg = "Cannot get filesize of " . $this->file->__toString() . " $php_errormsg"; -            throw new IOException($msg); -        } -        $rBuffer = fread($this->fd, $fileSize); -        $this->close(); -    } -     -    /** -     * Returns path to file we are reading. -     * @return string -     */ -    function getResource() { -        return $this->file->toString(); -    }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/FileSystem.php b/buildscripts/phing/classes/phing/system/io/FileSystem.php index 2802ddfb..284be830 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/FileSystem.php +++ b/buildscripts/phing/classes/phing/system/io/FileSystem.php @@ -1,7 +1,7 @@  <?php  /*  - *  $Id: FileSystem.php,v 1.11 2005/12/01 20:56:59 hlellelid Exp $ + *  $Id: 235081905c0eafcd98da2fec63404fa2ebee090a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -30,30 +30,50 @@   * *FileSystem drivers to access the real filesystem via this class using natives.   *   * FIXME: - *  - Error handling reduced to min fallthrough runtime excetions + *  - Error handling reduced to min fallthrough runtime exceptions   *    more precise errorhandling is done by the PhingFile class   *       * @author Charlie Killian <charlie@tizac.com>   * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.11 $ + * @version $Id$   * @package phing.system.io   */  abstract class FileSystem {     -    /* properties for simple boolean attributes */ +    /** +     * @var int +     */      const BA_EXISTS    = 0x01; +     +    /** +     * @var int +     */      const BA_REGULAR   = 0x02; +     +    /** +     * @var int +     */      const BA_DIRECTORY = 0x04; +     +    /** +     * @var int +     */      const BA_HIDDEN    = 0x08; -    /** Instance for getFileSystem() method. */ +    /** +     * Instance for getFileSystem() method. +     * @var FileSystem +     */      private static $fs;      /**       * Static method to return the FileSystem singelton representing       * this platform's local filesystem driver. +     *  +     * @return FileSystem +     * @throws IOException       */ -    function getFileSystem() { +    public static function getFileSystem() {          if (self::$fs === null) {              switch(Phing::getProperty('host.fstype')) {                  case 'UNIX': @@ -69,7 +89,7 @@ abstract class FileSystem {                      self::$fs = new WinNTFileSystem();                  break;                  default: -                    throw new Exception("Host uses unsupported filesystem, unable to proceed"); +                    throw new IOException("Host uses unsupported filesystem, unable to proceed");              }          }          return self::$fs; @@ -90,12 +110,16 @@ abstract class FileSystem {      /**       * Convert the given pathname string to normal form.  If the string is       * already in normal form then it is simply returned. +     *  +     * @param string $strPath       */      abstract function normalize($strPath);      /**       * Compute the length of this pathname string's prefix.  The pathname       * string must be in normal form. +     *  +     * @param string $pathname       */      abstract function prefixLength($pathname); @@ -103,12 +127,17 @@ abstract class FileSystem {       * Resolve the child pathname string against the parent.       * Both strings must be in normal form, and the result       * will be a string in normal form. +     *  +     * @param string $parent +     * @param string $child       */      abstract function resolve($parent, $child);      /**       * Resolve the given abstract pathname into absolute form.  Invoked by the       * getAbsolutePath and getCanonicalPath methods in the PhingFile class. +     *  +     * @param PhingFile $f       */      abstract function resolveFile(PhingFile $f); @@ -124,18 +153,23 @@ abstract class FileSystem {       * win32, e.g., to transform "/c:/foo" into "c:/foo".  The path string       * still has slash separators; code in the PhingFile class will translate them       * after this method returns. +     *  +     * @param string $path       */      abstract function fromURIPath($path); - +          /* -- Path operations -- */      /**       * Tell whether or not the given abstract pathname is absolute. +     *  +     * @param PhingFile $f       */      abstract function isAbsolute(PhingFile $f);      /**        * canonicalize filename by checking on disk  +     * @param string $strPath        * @return mixed Canonical path or false if the file doesn't exist.       */      function canonicalize($strPath) { @@ -148,9 +182,11 @@ abstract class FileSystem {       * Return the simple boolean attributes for the file or directory denoted       * by the given abstract pathname, or zero if it does not exist or some       * other I/O error occurs. +     *  +     * @param PhingFile $f       */      function getBooleanAttributes($f) { -        throw new Exception("SYSTEM ERROR method getBooleanAttributes() not implemented by fs driver"); +        throw new IOException("getBooleanAttributes() not implemented by fs driver");      }      /** @@ -160,6 +196,9 @@ abstract class FileSystem {       * argument is true, then a check for write (not read-write)       * access is made.  Return false if access is denied or an I/O error       * occurs. +     *  +     * @param PhingFile $f +     * @param boolean   $write       */      function checkAccess(PhingFile $f, $write = false) {          // we clear stat cache, its expensive to look up from scratch, @@ -189,11 +228,27 @@ abstract class FileSystem {              return (boolean) @is_writable($strPath);          }      } - +     +    /** +     * Whether file can be deleted. +     * @param PhingFile $f +     * @return boolean +     */ +    function canDelete(PhingFile $f) +    { +        clearstatcache();  +        $dir = dirname($f->getAbsolutePath());  +        return (bool) @is_writable($dir);  +    } +          /**       * Return the time at which the file or directory denoted by the given       * abstract pathname was last modified, or zero if it does not exist or       * some other I/O error occurs. +     *  +     * @param  PhingFile $f +     * @return int +     * @throws IOException       */      function getLastModifiedTime(PhingFile $f) { @@ -203,20 +258,35 @@ abstract class FileSystem {          @clearstatcache();          $strPath = (string) $f->getPath(); -        $mtime = @filemtime($strPath); -        if (false === $mtime) { -            // FAILED. Log and return err. -            $msg = "FileSystem::Filemtime() FAILED. Cannot can not get modified time of $strPath. $php_errormsg"; -            throw new Exception($msg); +         +        if (@is_link($strPath)) { +            $stats = @lstat($strPath); +             +            if (!isset($stats['mtime'])) { +                $mtime = false; +            } else { +                $mtime = $stats['mtime']; +            }           } else { -            return (int) $mtime; +            $mtime = @filemtime($strPath); +        } +             +        if (false === $mtime) { +            $msg = "FileSystem::getLastModifiedTime() FAILED. Can not get modified time of $strPath. $php_errormsg"; +            throw new IOException($msg);          } +             +        return (int) $mtime;      }      /**       * Return the length in bytes of the file denoted by the given abstract       * pathname, or zero if it does not exist, is a directory, or some other       * I/O error occurs. +     *  +     * @param  PhingFile $f +     * @throws IOException +     * @return int       */      function getLength(PhingFile $f) {          $strPath = (string) $f->getAbsolutePath(); @@ -225,7 +295,7 @@ abstract class FileSystem {              return $fs;          } else {              $msg = "FileSystem::Read() FAILED. Cannot get filesize of $strPath. $php_errormsg"; -            throw new Exception($msg); +            throw new IOException($msg);          }      } @@ -237,9 +307,9 @@ abstract class FileSystem {       * file or directory with the given pathname already exists.  Throw an       * IOException if an I/O error occurs.       * -     * @param       string      Path of the file to be created. -     *      -     * @throws      IOException +     * @param  string $strPathname Path of the file to be created. +     * @throws IOException +     * @return boolean       */      function createNewFile($strPathname) {          if (@file_exists($strPathname)) @@ -257,10 +327,14 @@ abstract class FileSystem {      /**       * Delete the file or directory denoted by the given abstract pathname,       * returning true if and only if the operation succeeds. +     *  +     * @param PhingFile $f +     * @param boolean $recursive +     * @return void       */ -    function delete(PhingFile $f) { +    function delete(PhingFile $f, $recursive = false) {          if ($f->isDirectory()) { -            return $this->rmdir($f->getPath()); +            return $this->rmdir($f->getPath(), $recursive);          } else {              return $this->unlink($f->getPath());          } @@ -269,16 +343,21 @@ abstract class FileSystem {      /**       * Arrange for the file or directory denoted by the given abstract       * pathname to be deleted when Phing::shutdown is called, returning -    * true if and only if the operation succeeds. +     * true if and only if the operation succeeds. +     *  +     * @param  PhingFile $f +     * @throws IOException       */      function deleteOnExit($f) { -        throw new Exception("deleteOnExit() not implemented by local fs driver"); +        throw new IOException("deleteOnExit() not implemented by local fs driver");      }      /**       * List the elements of the directory denoted by the given abstract       * pathname.  Return an array of strings naming the elements of the       * directory if successful; otherwise, return <code>null</code>. +     *  +     * @param PhingFile $f       */      function listDir(PhingFile $f) {          $strPath = (string) $f->getAbsolutePath(); @@ -300,9 +379,18 @@ abstract class FileSystem {      /**       * Create a new directory denoted by the given abstract pathname,       * returning true if and only if the operation succeeds. +     * +     * NOTE: umask() is reset to 0 while executing mkdir(), and restored afterwards +     *  +     * @param PhingFile $f +     * @param  int $mode +     * @return boolean       */ -    function createDirectory(&$f) { -        return @mkdir($f->getAbsolutePath(),0755); +    function createDirectory(&$f, $mode = 0755) { +        $old_umask = umask(0); +        $return = @mkdir($f->getAbsolutePath(), $mode); +        umask($old_umask); +        return $return;      }      /** @@ -313,7 +401,7 @@ abstract class FileSystem {       * @param PhingFile $f1 abstract source file       * @param PhingFile $f2 abstract destination file       * @return void     -     * @throws Exception if rename cannot be performed +     * @throws IOException if rename cannot be performed       */      function rename(PhingFile $f1, PhingFile $f2) {                  // get the canonical paths of the file to rename @@ -321,7 +409,7 @@ abstract class FileSystem {          $dest = $f2->getAbsolutePath();          if (false === @rename($src, $dest)) {              $msg = "Rename FAILED. Cannot rename $src to $dest. $php_errormsg"; -            throw new Exception($msg); +            throw new IOException($msg);          }      } @@ -329,14 +417,17 @@ abstract class FileSystem {       * Set the last-modified time of the file or directory denoted by the       * given abstract pathname returning true if and only if the       * operation succeeds. +     *  +     * @param  PhingFile $f +     * @param  int $time       * @return void -     * @throws Exception +     * @throws IOException       */      function setLastModifiedTime(PhingFile $f, $time) {                  $path = $f->getPath();          $success = @touch($path, $time);          if (!$success) { -            throw new Exception("Could not create directory due to: $php_errormsg"); +            throw new IOException("Could not touch '" . $path . "' due to: $php_errormsg");          }      } @@ -344,27 +435,34 @@ abstract class FileSystem {       * Mark the file or directory denoted by the given abstract pathname as       * read-only, returning <code>true</code> if and only if the operation       * succeeds. +     *  +     * @param  PhingFile $f +     * @throws IOException       */      function setReadOnly($f) { -        throw new Exception("setReadonle() not implemented by local fs driver"); +        throw new IOException("setReadonly() not implemented by local fs driver");      }      /* -- Filesystem interface -- */      /**       * List the available filesystem roots, return array of PhingFile objects +     * @throws IOException       */      function listRoots() { -        throw new Exception("SYSTEM ERROR [listRoots() not implemented by local fs driver]"); +        throw new IOException("listRoots() not implemented by local fs driver");      }      /* -- Basic infrastructure -- */      /**       * Compare two abstract pathnames lexicographically. +     *  +     * @param PhingFile $f1 +     * @param PhingFile $f2       */ -    function compare($f1, $f2) { -        throw new Exception("SYSTEM ERROR [compare() not implemented by local fs driver]"); +    function compare(PhingFile $f1, PhingFile $f2) { +        throw new IOException("compare() not implemented by local fs driver");      }      /** @@ -374,17 +472,23 @@ abstract class FileSystem {       * @param PhingFile $dest Destination path and name of new file.       *       * @return void      -     * @throws Exception if file cannot be copied. +     * @throws IOException if file cannot be copied.       */      function copy(PhingFile $src, PhingFile $dest) {          global $php_errormsg; +         +        // Recursively copy a directory +        if($src->isDirectory()) { +            return $this->copyr($src->getAbsolutePath(), $dest->getAbsolutePath()); +        } +                  $srcPath  = $src->getAbsolutePath();          $destPath = $dest->getAbsolutePath();          if (false === @copy($srcPath, $destPath)) { // Copy FAILED. Log and return err.              // Add error from php to end of log message. $php_errormsg.              $msg = "FileSystem::copy() FAILED. Cannot copy $srcPath to $destPath. $php_errormsg"; -            throw new Exception($msg); +            throw new IOException($msg);          }          try { @@ -394,28 +498,106 @@ abstract class FileSystem {              // eat it up for now.          }      } +     +    /** +     * Copy a file, or recursively copy a folder and its contents +     * +     * @author      Aidan Lister <aidan@php.net> +     * @version     1.0.1 +     * @link        http://aidanlister.com/repos/v/function.copyr.php +     * @param       string   $source    Source path +     * @param       string   $dest      Destination path +     * @return      bool     Returns TRUE on success, FALSE on failure +     */ +    function copyr($source, $dest) +    { +        // Check for symlinks +        if (is_link($source)) { +            return symlink(readlink($source), $dest); +        } +     +        // Simple copy for a file +        if (is_file($source)) { +            return copy($source, $dest); +        } +     +        // Make destination directory +        if (!is_dir($dest)) { +            mkdir($dest); +        } +     +        // Loop through the folder +        $dir = dir($source); +        while (false !== $entry = $dir->read()) { +            // Skip pointers +            if ($entry == '.' || $entry == '..') { +                continue; +            } +     +            // Deep copy directories +            $this->copyr("$source/$entry", "$dest/$entry"); +        } +     +        // Clean up +        $dir->close(); +        return true; +    } + +    /** +     * Change the ownership on a file or directory. +     * +     * @param    string $pathname Path and name of file or directory. +     * @param    string $user The user name or number of the file or directory. See http://us.php.net/chown +     * +     * @return void +     * @throws Exception if operation failed. +     */ +    function chown($pathname, $user) { +        if (false === @chown($pathname, $user)) {// FAILED. +            $msg = "FileSystem::chown() FAILED. Cannot chown $pathname. User $user." . (isset($php_errormsg) ? ' ' . $php_errormsg : ""); +            throw new IOException($msg); +        } +    } +     +    /** +     * Change the group on a file or directory. +     * +     * @param  string $pathname Path and name of file or directory. +     * @param  string $group The group of the file or directory. See http://us.php.net/chgrp +     * +     * @return void +     * @throws IOException if operation failed. +     */ +    function chgrp($pathname, $group) { +        if (false === @chgrp($pathname, $group)) {// FAILED. +            $msg = "FileSystem::chgrp() FAILED. Cannot chown $pathname. Group $group." . (isset($php_errormsg) ? ' ' . $php_errormsg : ""); +            throw new IOException($msg); +        } +    }      /**       * Change the permissions on a file or directory.       * -     * @param    pathname    String. Path and name of file or directory. -     * @param    mode        Int. The mode (permissions) of the file or -     *                        directory. If using octal add leading 0. eg. 0777. -     *                        Mode is affected by the umask system setting. +     * @param  string $pathname Path and name of file or directory. +     * @param  int    $mode     The mode (permissions) of the file or +     *                          directory. If using octal add leading 0. eg. 0777. +     *                          Mode is affected by the umask system setting.       *       * @return void      -     * @throws Exception if operation failed. +     * @throws IOException if operation failed.       */      function chmod($pathname, $mode) {              $str_mode = decoct($mode); // Show octal in messages.              if (false === @chmod($pathname, $mode)) {// FAILED. -            $msg = "FileSystem::chmod() FAILED. Cannot chmod $pathname. Mode $str_mode. $php_errormsg"; -            throw new Exception($msg); +            $msg = "FileSystem::chmod() FAILED. Cannot chmod $pathname. Mode $str_mode." . (isset($php_errormsg) ? ' ' . $php_errormsg : ""); +            throw new IOException($msg);          }      }      /**       * Locks a file and throws an Exception if this is not possible. +     *  +     * @param  PhingFile $f       * @return void       * @throws Exception       */ @@ -425,14 +607,15 @@ abstract class FileSystem {          $result = @flock($fp, LOCK_EX);          @fclose($fp);          if (!$result) { -            throw new Exception("Could not lock file '$filename'"); +            throw new IOException("Could not lock file '$filename'");          }      }      /**       * Unlocks a file and throws an IO Error if this is not possible.       * -     * @throws Exception +     * @param  PhingFile $f +     * @throws IOException       * @return void       */      function unlock(PhingFile $f) { @@ -448,16 +631,16 @@ abstract class FileSystem {      /**       * Delete a file.       * -     * @param    file    String. Path and/or name of file to delete. +     * @param  string $file Path and/or name of file to delete.       *       * @return void -     * @throws Exception - if an error is encountered. +     * @throws IOException - if an error is encountered.       */      function unlink($file) {          global $php_errormsg;          if (false === @unlink($file)) {              $msg = "FileSystem::unlink() FAILED. Cannot unlink '$file'. $php_errormsg"; -            throw new Exception($msg); +            throw new IOException($msg);          }      } @@ -478,7 +661,7 @@ abstract class FileSystem {          if (false === @symlink($target, $link)) {              // Add error from php to end of log message. $php_errormsg.              $msg = "FileSystem::Symlink() FAILED. Cannot symlink '$target' to '$link'. $php_errormsg"; -            throw new Exception($msg); +            throw new IOException($msg);          }      } diff --git a/buildscripts/phing/classes/phing/system/io/FileWriter.php b/buildscripts/phing/classes/phing/system/io/FileWriter.php index d6265777..d58b0513 100644 --- a/buildscripts/phing/classes/phing/system/io/FileWriter.php +++ b/buildscripts/phing/classes/phing/system/io/FileWriter.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FileWriter.php,v 1.7 2005/05/26 13:10:52 mrook Exp $   + *  $Id: 52ca0f8163c260b3f9f14cd83fa292292674a060 $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -18,122 +18,25 @@   * and is licensed under the LGPL. For more information please see   * <http://phing.info>.   */ -  -include_once 'phing/system/io/PhingFile.php'; -include_once 'phing/system/io/Writer.php'; + +require_once 'phing/system/io/OutputStreamWriter.php'; +require_once 'phing/system/io/FileOutputStream.php';  /** - * Convenience class for reading files. The constructor of this + * Convenience class for performing file write operations.   *   * @package   phing.system.io   */ -class FileWriter extends Writer { - -    protected $file; -    protected $fd; -     -    /** Whether to append contents to file. */ -    protected $append; -     -    /** Whether we should attempt to lock the file (currently disabled). */ -    protected $exclusive; +class FileWriter extends OutputStreamWriter {      /**       * Construct a new FileWriter.       * @param mixed $file PhingFile or string pathname.       * @param boolean $append Append to existing file? -     * @param boolean $exclusive Lock file? (currently disabled due to windows incompatibility)       */ -    function __construct($file, $append = false, $exclusive = false) { -        if ($file instanceof PhingFile) { -            $this->file = $file; -        } elseif (is_string($file)) { -            $this->file = new PhingFile($file); -        } else { -            throw new Exception("Invalid argument type for \$file."); -        } -        $this->append = $append; -        $this->exclusive = $exclusive; -    } - -    function close() { -        if ($this->fd === null) { -            return true; -        } - -        if (false === @fclose($this->fd)) { -            // FAILED. -            $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg"; -            throw new IOException($msg); -        } else { -            $this->fd = null; -            return true; -        } -    } - -    function open() { -        if ($this->fd === null) { -            if ($this->append) { $flags = "ab"; } else { $flags = "wb"; } -            $this->fd = @fopen($this->file->getPath(), $flags); -        } - -        if ($this->fd === false) { -            // fopen FAILED. -            // Add error from php to end of log message. $php_errormsg. -            $msg = "Cannot fopen ".$this->file->getPath()." $php_errormsg"; -            throw new IOException($msg); -        } - -        if (false) { -            // Locks don't seem to work on windows??? HELP!!!!!!!!! -            // if (FALSE === @flock($fp, LOCK_EX)) { // FAILED. -            $msg = "Cannot acquire flock on $file. $php_errormsg"; -            throw new IOException($msg); -        } - -        return true; -    } -     -    function reset() { -        // FIXME -- what exactly should this do, if anything? -        // reset to beginning of file (i.e. re-open)? -    } -     -    function writeBuffer($buffer) { - -        if (!$this->file->canWrite()) { -            throw new IOException("No permission to write to file: " . $this->file->__toString()); -        } - -        $this->open(); -        $result = @fwrite($this->fd, $buffer); -        $this->close(); - -        if ($result === false) { -            throw new IOException("Error writing file: ". $this->file->toString()); -        } else { -            return true; -        } -    } - -    function write($buf, $off = null, $len = null) { -        if ( $off === null && $len === null ) -            $to_write = $buf; -        else -            $to_write = substr($buf, $off, $len); - -        $this->open(); -        $result = @fwrite($this->fd, $to_write); - -        if ( $result === false ) { -            throw new IOException("Error writing file."); -        } else { -            return true; -        } -    } -     -    function getResource() { -        return $this->file->toString(); +    function __construct($file, $append = false) { +        $out = new FileOutputStream($file, $append); +        parent::__construct($out);      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/FilterReader.php b/buildscripts/phing/classes/phing/system/io/FilterReader.php index 8c683408..527ce17f 100644 --- a/buildscripts/phing/classes/phing/system/io/FilterReader.php +++ b/buildscripts/phing/classes/phing/system/io/FilterReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FilterReader.php,v 1.6 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 70652dbec76165f9ab0311daffde790df58eaf8e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,21 +19,21 @@   * <http://phing.info>.    */ -include_once 'phing/system/io/Reader.php'; +require_once 'phing/system/io/Reader.php';  /** - * Convenience class for reading files. The constructor of this - *  @package   phing.system.io - * - * TODO: All filters should be ProjectComponents, too! + * Wrapper class for readers, which can be used to apply filters. + * @package phing.system.io   */  class FilterReader extends Reader { +    /**  +     * @var Reader +     */      protected $in;      function __construct(Reader $in = null) {          $this->in = $in; -        //parent::__construct(new FileReader($file, $exclusive));      }      public function setReader(Reader $in) { @@ -61,12 +61,8 @@ class FilterReader extends Reader {          return $this->in->close();      } -    public function open() { -        return $this->in->open(); -    } -      function getResource() {          return $this->in->getResource();      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/IOException.php b/buildscripts/phing/classes/phing/system/io/IOException.php index e2c73b27..8aa1465f 100644 --- a/buildscripts/phing/classes/phing/system/io/IOException.php +++ b/buildscripts/phing/classes/phing/system/io/IOException.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: IOException.php,v 1.4 2005/02/27 20:52:09 mrook Exp $ + *  $Id: 8a019e4034b2236c19058ea849b12fb88d3e2f43 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,4 +25,3 @@   * @package   phing.system.io   */  class IOException extends Exception {} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/system/io/InputStream.php b/buildscripts/phing/classes/phing/system/io/InputStream.php new file mode 100644 index 00000000..f25fbe61 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/InputStream.php @@ -0,0 +1,178 @@ +<?php +/* + *  $Id: 3ec0be3a0e0c81568513a11cbf4d4b453928a338 $ + * + * 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>.  + */ + +/** + * Wrapper class for PHP stream that supports read operations. + *  + * @package   phing.system.io + */ +class InputStream { +     +    /** +     * @var resource The attached PHP stream. +     */ +    protected $stream; +     +    /** +     * @var int Position of stream cursor. +     */ +    protected $currentPosition = 0; +     +    /** +     * @var int Marked position of stream cursor. +     */ +    protected $mark = 0; +     +    /** +     * Construct a new InputStream. +     * @param resource $stream Configured PHP stream for writing. +     */ +    public function __construct($stream) { +        if (!is_resource($stream)) { +            throw new IOException("Passed argument is not a valid stream."); +        } +        $this->stream = $stream; +    } + +    /** +     * Skip over $n bytes. +     * @param int $n +     */ +    public function skip($n) { +        $start = $this->currentPosition; + +        $ret = @fseek($this->stream, $n, SEEK_CUR); +        if ( $ret === -1 ) +            return -1; + +        $this->currentPosition = ftell($this->stream); + +        if ( $start > $this->currentPosition ) +            $skipped = $start - $this->currentPosition; +        else +            $skipped = $this->currentPosition - $start; + +        return $skipped; +    } +     +    /** +     * Read data from stream until $len chars or EOF. +     * @param int $len Num chars to read.  If not specified this stream will read until EOF. +     * @return string chars read or -1 if eof. +     */ +    public function read($len = null) { +         +        if ($this->eof()) { +            return -1; +        } +         +        if ($len === null) { // we want to keep reading until we get an eof +            $out = ""; +            while(!$this->eof()) { +                $out .= fread($this->stream, 8192); +                $this->currentPosition = ftell($this->stream); +            } +        } else { +            $out = fread($this->stream, $len); // adding 1 seems to ensure that next call to read() will return EOF (-1) +            $this->currentPosition = ftell($this->stream); +        } + +        return $out; +    }     +     +    /** +     * Marks the current position in this input stream. +     * @throws IOException - if the underlying stream doesn't support this method. +     */ +    public function mark() { +        if (!$this->markSupported()) { +            throw new IOException(get_class($this) . " does not support mark() and reset() methods."); +        } +        $this->mark = $this->currentPosition; +    } +     +    /** +     * Whether the input stream supports mark and reset methods. +     * @return boolean +     */ +    public function markSupported() { +        return false; +    } +     +    /** +     * Repositions this stream to the position at the time the mark method was last called on this input stream. +     * @throws IOException - if the underlying stream doesn't support this method. +     */ +    function reset() { +        if (!$this->markSupported()) { +            throw new IOException(get_class($this) . " does not support mark() and reset() methods."); +        } +        // goes back to last mark, by default this would be 0 (i.e. rewind file). +        fseek($this->stream, SEEK_SET, $this->mark); +        $this->mark = 0; +    } +     +    /** +     * Closes stream. +     * @throws IOException if stream cannot be closed (note that calling close() on an already-closed stream will not raise an exception) +     */ +    public function close() { +        if ($this->stream === null) { +            return; +        } +        if (false === @fclose($this->stream)) { +            // FAILED. +            $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg"; +            throw new IOException($msg); +        } +        $this->stream = null; +    } +     +    /** +     * Whether eof has been reached with stream. +     * @return boolean +     */ +    public function eof() { +        return feof($this->stream); +    } +      +    /** +     * Reads a entire until EOF and places contents in passed-in variable.  Stream is closed after read. +     * +     * @param string &$rBuffer String variable where read contents will be put. +     * @return TRUE on success. +     * @author  Charlie Killian, charlie@tizac.com +     * @throws IOException - if there is an error reading from stream. +     * @deprecated - Instead, use the read() method or a BufferedReader. +     */ +    public function readInto(&$rBuffer) { +        $rBuffer = $this->read(); +        $this->close(); +    } +     +    /** +     * Returns string representation of attached stream. +     * @return string +     */ +    public function __toString() { +        return (string) $this->stream; +    } +} diff --git a/buildscripts/phing/classes/phing/system/io/InputStreamReader.php b/buildscripts/phing/classes/phing/system/io/InputStreamReader.php new file mode 100644 index 00000000..a21f9f05 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/InputStreamReader.php @@ -0,0 +1,127 @@ +<?php +/* + *  $Id: 823f584f1834166724cd370f91fa1bd2c66b0e94 $ + * + * 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>.  + */ +  +include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/system/io/Reader.php'; + +/** + * Writer class for OutputStream objects. + *  + * Unlike the Java counterpart, this class does not (yet) handle + * character set transformations.  This will be an important function + * of this class with move to supporting PHP6. + * + * @package   phing.system.io + */ +class InputStreamReader extends Reader { +     +    /** +     * @var InputStream +     */ +    protected $inStream; +     +    /** +     * Construct a new InputStreamReader. +     * @param InputStream $$inStream InputStream to read from +     */ +    public function __construct(InputStream $inStream) { +        $this->inStream = $inStream; +    } +     +    /** +     * Close the stream. +     */ +    public function close() { +        return $this->inStream->close(); +    } +     +    /** +     * Skip over $n bytes. +     * @param int $n +     */ +    public function skip($n) { +        return $this->inStream->skip($n); +    } +     +    /** +     * Read data from file. +     * @param int $len Num chars to read. +     * @return string chars read or -1 if eof. +     */ +    public function read($len = null) { +        return $this->inStream->read($len); +    } +     +    /** +     * Marks the current position in this input stream. +     * @throws IOException - if the underlying stream doesn't support this method. +     */ +    public function mark() { +        $this->inStream->mark(); +    } +     +    /** +     * Whether the attached stream supports mark/reset. +     * @return boolean +     */ +    public function markSupported() { +        return $this->inStream->markSupported(); +    } +     +    /** +     * Repositions this stream to the position at the time the mark method was last called on this input stream. +     * @throws IOException - if the underlying stream doesn't support this method. +     */ +    public function reset() { +        $this->inStream->reset(); +    } + +    /** +     * Whether eof has been reached with stream. +     * @return boolean +     */ +    public function eof() { +        return $this->inStream->eof(); +    } +      +    /** +     * Reads a entire file and stores the data in the variable +     * passed by reference. +     * +     * @param    string $file    String. Path and/or name of file to read. +     * @param    object &$rBuffer    Reference. Variable of where to put contents. +     * +     * @return    TRUE on success. Err object on failure. +     * @author  Charlie Killian, charlie@tizac.com +     * @deprecated Use read() or BufferedReader instead. +     */ +    public function readInto(&$rBuffer) { +        return $this->inStream->readInto($rBuffer); +    } +     +    /** +     * Returns string representation of attached stream. +     * @return string +     */ +    public function getResource() { +        return $this->inStream->__toString(); +    } +} diff --git a/buildscripts/phing/classes/phing/system/io/OutputStream.php b/buildscripts/phing/classes/phing/system/io/OutputStream.php new file mode 100644 index 00000000..09e15c0e --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/OutputStream.php @@ -0,0 +1,108 @@ +<?php +/* + *  $Id: 3ef1bb9c45c0e679debf227c5e4699f88f692943 $   + *  + * 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>. + */ + +/** + * Wrapper class for PHP stream that supports write operations. + *  + * @package   phing.system.io + */ +class OutputStream { +     +    /** +     * @var resource The configured PHP stream. +     */ +    protected $stream; + +    /** +     * Construct a new OutputStream. +     * @param resource $stream Configured PHP stream for writing. +     */ +    public function __construct($stream) { +        if (!is_resource($stream)) { +            throw new IOException("Passed argument is not a valid stream."); +        } +        $this->stream = $stream; +    } +     +    /** +     * Closes attached stream, flushing output first. +     * @throws IOException if cannot close stream (note that attempting to close an already closed stream will not raise an IOException) +     * @return void +     */ +    public function close() { +        if ($this->stream === null) { +            return; +        } +        $this->flush(); +        if (false === @fclose($this->stream)) { +            $msg = "Cannot close " . $this->getResource() . ": $php_errormsg"; +            throw new IOException($msg); +        } +        $this->stream = null; +    } +     +    /** +     * Flushes stream. +     *  +     * @throws IOException if unable to flush data (e.g. stream is not open). +     */ +    public function flush() { +        if (false === @fflush($this->stream)) { +            throw new IOException("Could not flush stream: " . $php_errormsg); +        } +    } +     +    /** +     * Writes data to stream. +     * +     * @param string $buf Binary/character data to write. +     * @param int $off (Optional) offset. +     * @param int $len (Optional) number of bytes/chars to write.  +     * @return void +     * @throws IOException - if there is an error writing to stream +     */ +    public function write($buf, $off = null, $len = null) { +        if ( $off === null && $len === null ) { +            $to_write = $buf; +        } elseif ($off !== null && $len === null) { +            $to_write = substr($buf, $off); +        } elseif ($off === null && $len !== null) { +            $to_write = substr($buf, 0, $len); +        } else { +            $to_write = substr($buf, $off, $len); +        } +         +        $result = @fwrite($this->stream, $to_write); + +        if ( $result === false ) { +            throw new IOException("Error writing to stream."); +        } +    } +     +    /** +     * Returns a string representation of the attached PHP stream. +     * @return string +     */ +    public function __toString() { +        return (string) $this->stream; +    } +} + diff --git a/buildscripts/phing/classes/phing/system/io/OutputStreamWriter.php b/buildscripts/phing/classes/phing/system/io/OutputStreamWriter.php new file mode 100644 index 00000000..0b821e67 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/OutputStreamWriter.php @@ -0,0 +1,84 @@ +<?php +/* + *  $Id: c1446fc1a19aef45f74766420ec89c2c37b32e01 $   + *  + * 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>. + */ +  +include_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/Writer.php'; + +/** + * Writer class for OutputStream objects. + *  + * Unlike the Java counterpart, this class does not (yet) handle + * character set transformations.  This will be an important function + * of this class with move to supporting PHP6. + * + * @package   phing.system.io + */ +class OutputStreamWriter extends Writer { + +    /** +     * @var OutputStream +     */ +    protected $outStream; +     +    /** +     * Construct a new OutputStreamWriter. +     * @param OutputStream $outStream OutputStream to write to +     */ +    public function __construct(OutputStream $outStream) { +        $this->outStream = $outStream; +    } +     +    /** +     * Close the stream. +     */ +    public function close() { +        return $this->outStream->close(); +    } +     +    /** +     * Write char data to stream. +     * +     * @param unknown_type $buf +     * @param unknown_type $off +     * @param unknown_type $len +     * @return unknown +     */ +    public function write($buf, $off = null, $len = null) { +        return $this->outStream->write($buf, $off, $len); +    } +     +    /** +     * Flush output to the stream. +     */ +    public function flush() { +        $this->outStream->flush(); +    } +     +    /** +     * Gets a string representation of attached stream resource. +     * +     * @return string String representation of output stream +     */ +    public function getResource() { +        return $this->outStream->__toString(); +    } +} + diff --git a/buildscripts/phing/classes/phing/system/io/PhingFile.php b/buildscripts/phing/classes/phing/system/io/PhingFile.php index cd881963..871afedd 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/PhingFile.php +++ b/buildscripts/phing/classes/phing/system/io/PhingFile.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PhingFile.php,v 1.1 2005/05/26 13:10:52 mrook Exp $ + *  $Id: d2cfaf834a2cc605a3aedf37285f547010b8b4f4 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ include_once 'phing/system/lang/NullPointerException.php';  /**   * An abstract representation of file and directory pathnames.   * - * @version   $Revision: 1.1 $ + * @version   $Id$   * @package   phing.system.io   */  class PhingFile { @@ -43,7 +43,10 @@ class PhingFile {       */      private $path = null; -    /** The length of this abstract pathname's prefix, or zero if it has no prefix. */ +    /** +     * The length of this abstract pathname's prefix, or zero if it has no prefix. +     * @var int +     */      private $prefixLength = 0;      /** constructor */ @@ -71,14 +74,23 @@ class PhingFile {          }      } -    /** Returns the length of this abstract pathname's prefix. */ +    /** +     * Returns the length of this abstract pathname's prefix. +     *  +     * @return int +     */      function getPrefixLength() {          return (int) $this->prefixLength;      }      /* -- constructors not called by signature match, so we need some helpers --*/ -    function _constructPathname($pathname) { +    /** +     *  +     * Enter description here ... +     * @param unknown_type $pathname +     */ +    protected function _constructPathname($pathname) {          // obtain ref to the filesystem layer          $fs = FileSystem::getFileSystem(); @@ -90,7 +102,13 @@ class PhingFile {          $this->prefixLength = (int) $fs->prefixLength($this->path);      } -    function _constructStringParentStringChild($parent, $child = null) { +    /** +     *  +     * Enter description here ... +     * @param unknown_type $parent +     * @param unknown_type $child +     */ +    protected function _constructStringParentStringChild($parent, $child = null) {          // obtain ref to the filesystem layer          $fs = FileSystem::getFileSystem(); @@ -109,7 +127,13 @@ class PhingFile {          $this->prefixLength = (int) $fs->prefixLength($this->path);      } -    function _constructFileParentStringChild($parent, $child = null) { +    /** +     *  +     * Enter description here ... +     * @param unknown_type $parent +     * @param unknown_type $child +     */ +    protected function _constructFileParentStringChild($parent, $child = null) {          // obtain ref to the filesystem layer          $fs = FileSystem::getFileSystem(); @@ -166,7 +190,7 @@ class PhingFile {          // that's a lastIndexOf          $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);          if ($index < $this->prefixLength) { -            if (($this->prefixLength > 0) && (strlen($this->path > $this->prefixLength))) { +            if (($this->prefixLength > 0) && (strlen($this->path) > $this->prefixLength)) {                  return substr($this->path, 0, $this->prefixLength);              }              return null; @@ -200,20 +224,42 @@ class PhingFile {       * string uses the default name-separator character to separate the names       * in the name sequence.       * -     * @return  The string form of this abstract pathname +     * @return string The string form of this abstract pathname       */      function getPath() {          return (string) $this->path;      }      /** +     * Returns path without leading basedir. +     * +     * @param string $basedir Base directory to strip +     * +     * @return string Path without basedir +     * +     * @uses getPath() +     */ +    function getPathWithoutBase($basedir) +    { +        if (!StringHelper::endsWith(self::$separator, $basedir)) { +            $basedir .= self::$separator; +        } +        $path = $this->getPath(); +        if (!substr($path, 0, strlen($basedir)) == $basedir) { +            //path does not begin with basedir, we don't modify it +            return $path; +        } +        return substr($path, strlen($basedir)); +    } + +    /**       * Tests whether this abstract pathname is absolute.  The definition of       * absolute pathname is system dependent.  On UNIX systems, a pathname is       * absolute if its prefix is "/".  On Win32 systems, a pathname is absolute       * if its prefix is a drive specifier followed by "\\", or if its prefix       * is "\\".       * -     * @return  true if this abstract pathname is absolute, false otherwise +     * @return boolean true if this abstract pathname is absolute, false otherwise       */      function isAbsolute() {          return ($this->prefixLength !== 0); @@ -235,9 +281,9 @@ class PhingFile {       * pathname, if any; if not, it is resolved against the current user       * directory.       * -     * @return  The absolute pathname string denoting the same file or -     *          directory as this abstract pathname -     * @see     #isAbsolute() +     * @return string The absolute pathname string denoting the same file or +     *                directory as this abstract pathname +     * @see    #isAbsolute()       */      function getAbsolutePath() {          $fs = FileSystem::getFileSystem();         @@ -248,8 +294,8 @@ class PhingFile {       * Returns the absolute form of this abstract pathname.  Equivalent to       * getAbsolutePath.       * -     * @return  The absolute abstract pathname denoting the same file or -     *          directory as this abstract pathname +     * @return string The absolute abstract pathname denoting the same file or +     *                directory as this abstract pathname       */      function getAbsoluteFile() {          return new PhingFile((string) $this->getAbsolutePath()); @@ -277,8 +323,8 @@ class PhingFile {       * file or directory may be different from the canonical form of the same       * pathname after the file or directory is deleted.       * -     * @return  The canonical pathname string denoting the same file or -     *          directory as this abstract pathname +     * @return string The canonical pathname string denoting the same file or +     *                directory as this abstract pathname       */      function getCanonicalPath() {          $fs = FileSystem::getFileSystem(); @@ -309,8 +355,8 @@ class PhingFile {       * URI, via the toURI() method, and then converting the URI       * into a URL via the URI::toURL()       * -     * @return  A URL object representing the equivalent file URL -     * +     * @return void A URL object representing the equivalent file URL +     * @todo   Not implemented yet       *       */      function toURL() { @@ -322,7 +368,8 @@ class PhingFile {      /**       * Constructs a file: URI that represents this abstract pathname. -     * Not implemented yet +     * @todo   Not implemented yet +     * @return void       */      function toURI() {          /* @@ -334,6 +381,13 @@ class PhingFile {          */      } +    /** +     *  +     * Enter description here ... +     * @param  PhingFile|string $path +     * @param  boolean $isDirectory +     * @return string +     */      function _slashify($path, $isDirectory) {          $p = (string) $path; @@ -358,15 +412,15 @@ class PhingFile {       * Tests whether the application can read the file denoted by this       * abstract pathname.       * -     * @return  true if and only if the file specified by this -     *          abstract pathname exists and can be read by the -     *          application; false otherwise +     * @return boolean true if and only if the file specified by this +     *                 abstract pathname exists and can be read by the +     *                 application; false otherwise       */      function canRead() {          $fs = FileSystem::getFileSystem();          if ($fs->checkAccess($this)) { -            return (boolean) @is_readable($this->getAbsolutePath()); +            return (boolean) @is_link($this->getAbsolutePath()) || @is_readable($this->getAbsolutePath());          }          return false;      } @@ -375,11 +429,10 @@ class PhingFile {       * Tests whether the application can modify to the file denoted by this       * abstract pathname.       * -     * @return  true if and only if the file system actually -     *          contains a file denoted by this abstract pathname and -     *          the application is allowed to write to the file; -     *          false otherwise. -     * +     * @return boolean true if and only if the file system actually +     *                 contains a file denoted by this abstract pathname and +     *                 the application is allowed to write to the file; +     *                 false otherwise.       */      function canWrite() {          $fs = FileSystem::getFileSystem(); @@ -389,13 +442,16 @@ class PhingFile {      /**       * Tests whether the file denoted by this abstract pathname exists.       * -     * @return  true if and only if the file denoted by this -     *          abstract pathname exists; false otherwise -     * +     * @return boolean true if and only if the file denoted by this +     *                 abstract pathname exists; false otherwise       */      function exists() {                 -        if ($this->isFile()) { -            return @file_exists($this->path); +        clearstatcache(); +         +        if (is_link($this->path)) { +            return true; +        } else if ($this->isFile()) { +            return @file_exists($this->path) || is_link($this->path);          } else {              return @is_dir($this->path);          } @@ -405,17 +461,17 @@ class PhingFile {       * Tests whether the file denoted by this abstract pathname is a       * directory.       * -     * @return true if and only if the file denoted by this -     *         abstract pathname exists and is a directory; -     *         false otherwise -     * +     * @return boolean true if and only if the file denoted by this +     *                 abstract pathname exists and is a directory; +     *                 false otherwise       */      function isDirectory() { +        clearstatcache();          $fs = FileSystem::getFileSystem();          if ($fs->checkAccess($this) !== true) {              throw new IOException("No read access to ".$this->path);          } -        return @is_dir($this->path); +        return @is_dir($this->path) && !@is_link($this->path);      }      /** @@ -424,11 +480,12 @@ class PhingFile {       * addition, satisfies other system-dependent criteria.  Any non-directory       * file created by a Java application is guaranteed to be a normal file.       * -     * @return  true if and only if the file denoted by this -     *          abstract pathname exists and is a normal file; -     *          false otherwise +     * @return boolean true if and only if the file denoted by this +     *                 abstract pathname exists and is a normal file; +     *                 false otherwise       */      function isFile() { +        clearstatcache();          //$fs = FileSystem::getFileSystem();          return @is_file($this->path);      } @@ -441,9 +498,9 @@ class PhingFile {       * hidden if it has been marked as such in the filesystem. Currently there       * seems to be no way to dermine isHidden on Win file systems via PHP       * -     * @return  true if and only if the file denoted by this -     *          abstract pathname is hidden according to the conventions of the -     *          underlying platform +     * @return boolean true if and only if the file denoted by this +     *                 abstract pathname is hidden according to the conventions of the +     *                 underlying platform       */      function isHidden() {          $fs = FileSystem::getFileSystem(); @@ -452,15 +509,42 @@ class PhingFile {          }          return (($fs->getBooleanAttributes($this) & $fs->BA_HIDDEN) !== 0);      } +     +    /** +     * Tests whether the file denoted by this abstract pathname is a symbolic link. +     * +     * @return boolean true if and only if the file denoted by this +     *                 abstract pathname exists and is a symbolic link; +     *                 false otherwise +     */ +    public function isLink() +    { +        clearstatcache(); +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No read access to ".$this->path); +        } +        return @is_link($this->path); +    } + +    /** +     * Returns the target of the symbolic link denoted by this abstract pathname +     * +     * @return string the target of the symbolic link denoted by this abstract pathname +     */ +    public function getLinkTarget() +    { +        return @readlink($this->path); +    }      /**       * Returns the time that the file denoted by this abstract pathname was       * last modified.       * -     * @return  A integer value representing the time the file was -     *          last modified, measured in milliseconds since the epoch -     *          (00:00:00 GMT, January 1, 1970), or 0 if the -     *          file does not exist or if an I/O error occurs +     * @return int An integer value representing the time the file was +     *             last modified, measured in milliseconds since the epoch +     *             (00:00:00 GMT, January 1, 1970), or 0 if the +     *             file does not exist or if an I/O error occurs       */      function lastModified() {          $fs = FileSystem::getFileSystem(); @@ -474,8 +558,8 @@ class PhingFile {       * Returns the length of the file denoted by this abstract pathname.       * The return value is unspecified if this pathname denotes a directory.       * -     * @return  The length, in bytes, of the file denoted by this abstract -     *          pathname, or 0 if the file does not exist +     * @return int The length, in bytes, of the file denoted by this abstract +     *             pathname, or 0 if the file does not exist       */      function length() {          $fs = FileSystem::getFileSystem(); @@ -507,9 +591,9 @@ class PhingFile {       * are a single operation that is atomic with respect to all other       * filesystem activities that might affect the file.       * -     * @return  true if the named file does not exist and was -     *          successfully created; <code>false</code> if the named file -     *          already exists +     * @return boolean true if the named file does not exist and was +     *                 successfully created; <code>false</code> if the named file +     *                 already exists       * @throws IOException if file can't be created       */      function createNewFile($parents=true, $mode=0777) { @@ -522,15 +606,15 @@ class PhingFile {       * this pathname denotes a directory, then the directory must be empty in       * order to be deleted.       * -     * @return  true if and only if the file or directory is -     *          successfully deleted; false otherwise +     * @return boolean true if and only if the file or directory is +     *                 successfully deleted; false otherwise       */ -    function delete() { +    function delete($recursive = false) {          $fs = FileSystem::getFileSystem(); -        if ($fs->checkAccess($this, true) !== true) { -            throw new IOException("No read access to " . $this->path."\n"); +        if ($fs->canDelete($this) !== true) { +            throw new IOException("Cannot delete " . $this->path . "\n");           } -        return $fs->delete($this); +        return $fs->delete($this, $recursive);      }      /** @@ -563,18 +647,23 @@ class PhingFile {       * will appear in any specific order; they are not, in particular,       * guaranteed to appear in alphabetical order.       * -     * @return  An array of strings naming the files and directories in the -     *          directory denoted by this abstract pathname.  The array will be -     *          empty if the directory is empty.  Returns null if -     *          this abstract pathname does not denote a directory, or if an -     *          I/O error occurs. -     * +     * @param $filter string +     * @return array An array of strings naming the files and directories in the +     *               directory denoted by this abstract pathname.  The array will be +     *               empty if the directory is empty.  Returns null if +     *               this abstract pathname does not denote a directory, or if an +     *               I/O error occurs.       */      function listDir($filter = null) {          $fs = FileSystem::getFileSystem();          return $fs->lister($this, $filter);      } +    /** +     *  +     * Enter description here ... +     * @param PhingFile[] $filter +     */      function listFiles($filter = null) {          $ss = $this->listDir($filter);          if ($ss === null) { @@ -594,46 +683,46 @@ class PhingFile {       * operation fails it may have succeeded in creating some of the necessary       * parent directories.       * -     * @return  true if and only if the directory was created, -     *          along with all necessary parent directories; false -     *          otherwise -     * @throws  IOException +     * @return boolean true if and only if the directory was created, +     *                 along with all necessary parent directories; false +     *                 otherwise +     * @throws IOException       */ -    function mkdirs() { +    function mkdirs($mode = 0755) {          if ($this->exists()) {              return false;          } -		try { -			if ($this->mkdir()) { -	            return true; -	        } -		} catch (IOException $ioe) { -			// IOException from mkdir() means that directory propbably didn't exist. -		}         +        try { +            if ($this->mkdir($mode)) { +                return true; +            } +        } catch (IOException $ioe) { +            // IOException from mkdir() means that directory propbably didn't exist. +        }                  $parentFile = $this->getParentFile(); -        return (($parentFile !== null) && ($parentFile->mkdirs() && $this->mkdir())); +        return (($parentFile !== null) && ($parentFile->mkdirs($mode) && $this->mkdir($mode)));      }      /**       * Creates the directory named by this abstract pathname.       * -     * @return  true if and only if the directory was created; false otherwise -     * @throws  IOException +     * @return boolean true if and only if the directory was created; false otherwise +     * @throws IOException       */ -    function mkdir() { +    function mkdir($mode = 0755) {          $fs = FileSystem::getFileSystem();          if ($fs->checkAccess(new PhingFile($this->path), true) !== true) {              throw new IOException("No write access to " . $this->getPath());          } -        return $fs->createDirectory($this); +        return $fs->createDirectory($this, $mode);      }      /**       * Renames the file denoted by this abstract pathname.       * -     * @param   destFile  The new abstract pathname for the named file -     * @return  true if and only if the renaming succeeded; false otherwise +     * @param  PhingFile $destFile The new abstract pathname for the named file +     * @return boolean true if and only if the renaming succeeded; false otherwise       */      function renameTo(PhingFile $destFile) {          $fs = FileSystem::getFileSystem(); @@ -647,8 +736,8 @@ class PhingFile {       * Simple-copies file denoted by this abstract pathname into another       * PhingFile       * -     * @param PhingFile $destFile  The new abstract pathname for the named file -     * @return true if and only if the renaming succeeded; false otherwise +     * @param  PhingFile $destFile  The new abstract pathname for the named file +     * @return boolean true if and only if the renaming succeeded; false otherwise       */      function copyTo(PhingFile $destFile) {          $fs = FileSystem::getFileSystem(); @@ -674,9 +763,9 @@ class PhingFile {       * lastModified method will return the (possibly truncated) time argument       * that was passed to this method.       * -     * @param  time  The new last-modified time, measured in milliseconds since -     *               the epoch (00:00:00 GMT, January 1, 1970) -     * @return true if and only if the operation succeeded; false otherwise +     * @param  int $time The new last-modified time, measured in milliseconds since +     *                   the epoch (00:00:00 GMT, January 1, 1970) +     * @return boolean true if and only if the operation succeeded; false otherwise       */      function setLastModified($time) {          $time = (int) $time; @@ -684,11 +773,7 @@ class PhingFile {              throw new Exception("IllegalArgumentException, Negative $time\n");          } -        // FIXME check if accessible          $fs = FileSystem::getFileSystem(); -        if ($fs->checkAccess($this, true) !== true) { -            throw new IOException("File::setLastModified(). No write access to file\n"); -        }          return $fs->setLastModifiedTime($this, $time);      } @@ -699,7 +784,7 @@ class PhingFile {       * marked to allow write access.  Whether or not a read-only file or       * directory may be deleted depends upon the underlying system.       * -     * @return true if and only if the operation succeeded; false otherwise +     * @return boolean true if and only if the operation succeeded; false otherwise       */      function setReadOnly() {          $fs = FileSystem::getFileSystem(); @@ -711,6 +796,40 @@ class PhingFile {      }      /** +     * Sets the owner of the file. +     * @param mixed $user User name or number. +     */ +    public function setUser($user) { +        $fs = FileSystem::getFileSystem(); +        return $fs->chown($this->getPath(), $user); +    } +     +    /** +     * Retrieve the owner of this file. +     * @return int User ID of the owner of this file.  +     */ +    function getUser() { +        return @fileowner($this->getPath()); +    } +     +    /** +     * Sets the group of the file. +     * @param mixed $user User name or number. +     */ +    public function setGroup($group) { +        $fs = FileSystem::getFileSystem(); +        return $fs->chgrp($this->getPath(), $group); +    } +     +    /** +     * Retrieve the group of this file. +     * @return int User ID of the owner of this file.  +     */ +    function getGroup() { +        return @filegroup($this->getPath()); +    } + +    /**       * Sets the mode of the file       * @param int $mode Ocatal mode.       */ @@ -757,10 +876,10 @@ class PhingFile {       * platform will be returned by this method, while PhingFile       * objects containing UNC pathnames will not be returned by this method.       * -     * @return  An array of PhingFile objects denoting the available -     *          filesystem roots, or null if the set of roots -     *          could not be determined.  The array will be empty if there are -     *          no filesystem roots. +     * @return array An array of PhingFile objects denoting the available +     *               filesystem roots, or null if the set of roots +     *               could not be determined.  The array will be empty if there are +     *               no filesystem roots.       */      function listRoots() {          $fs = FileSystem::getFileSystem(); @@ -771,8 +890,9 @@ class PhingFile {      /**       * Returns the path to the temp directory. +     * @return string       */ -    function getTempDir() { +    public static function getTempDir() {          return Phing::getProperty('php.tmpdir');      } @@ -782,11 +902,11 @@ class PhingFile {       * is a reference to a PhingFile Object.       * Then, the file is locked for exclusive reading/writing.       * -     * @author      manuel holtgrewe, grin@gmx.net -     * @throws      IOException -     * @access      public +     * @author manuel holtgrewe, grin@gmx.net +     * @throws IOException +     * @return PhingFile       */ -    function createTempFile($prefix, $suffix, PhingFile $directory) { +    public static function createTempFile($prefix, $suffix, PhingFile $directory) {          // quick but efficient hack to create a unique filename ;-)          $result = null; @@ -853,14 +973,24 @@ class PhingFile {          return false;      } -    /** Backwards compatibility -- use PHP5's native __tostring method. */ -    function toString() { -        return $this->getPath(); +    /** +     * Backwards compatibility - @see __toString() +     *  +     * @return string +     */ +    public function toString() +    { +        return $this->__toString();      } -    /** PHP5's native method. */ -    function __toString() { +    /** +     * Return string representation of the object +     *  +     * @return string +     */ +    public function __toString() +    {          return $this->getPath();      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/Reader.php b/buildscripts/phing/classes/phing/system/io/Reader.php index 1e377378..92159469 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/Reader.php +++ b/buildscripts/phing/classes/phing/system/io/Reader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Reader.php,v 1.5 2003/12/24 12:38:40 hlellelid Exp $ + *  $Id: c6154b0ec9b7789f9e3f8b961e16e1b1ada091ed $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,32 +21,31 @@  /**   * Abstract class for reading character streams. + *    * @author Hans Lellelid <hans@xmpl.org>   * @author Yannick Lecaillez <yl@seasonfive.com> - * @version $Revision: 1.5 $ + * @version $Id$   * @package phing.system.io   */  abstract class Reader {      /**       * Read data from source. +     *        * If length is specified, then only that number of chars is read,       * otherwise stream is read until EOF. +     *        * @param int $len       */      abstract public function read($len = null);      /**       * Close stream. +     * @throws IOException if there is an error closing stream       */      abstract public function close();      /** -     * Open stream for reading. -     */ -    abstract public function open(); -     -    /**       * Returns the filename, url, etc. that is being read from.       * This is critical for, e.g., ExpatParser's ability to know       * the filename that is throwing an ExpatParserException, etc. @@ -76,13 +75,17 @@ abstract class Reader {       * Whether marking is supported.       * @return boolean       */ -    public function markSupported() {} +    public function markSupported() { +        return false; +    }      /**       * Is stream ready for reading.       * @return boolean       */ -    public function ready() {} +    public function ready() { +        return true; +    }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/StringReader.php b/buildscripts/phing/classes/phing/system/io/StringReader.php index 689a2115..e8b493e9 100644 --- a/buildscripts/phing/classes/phing/system/io/StringReader.php +++ b/buildscripts/phing/classes/phing/system/io/StringReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: StringReader.php,v 1.8 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 2fba6ccfe1849d1f94b1dd91daf51e64e05cace2 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,13 +20,24 @@   */  /** - * Dummy class for reading character streams.  + * Dummy class for reading from string of characters.    * @package phing.system.io   */  class StringReader extends Reader { -    private    $_string; +    /** +     * @var string +     */ +    private $_string; +     +    /** +     * @var int +     */      private $mark = 0; +     +    /** +     * @var int +     */      private $currPos = 0;      function __construct($string) { @@ -70,4 +81,4 @@ class StringReader extends Reader {          return '(string) "'.$this->_string . '"';      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php b/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php index fb4e49b4..739ff6f6 100644..100755 --- a/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php +++ b/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: UnixFileSystem.php,v 1.10 2005/05/26 13:10:52 mrook Exp $ + *  $Id: ccfae0e7f76e6a02bfb20fc4b6f30eddf86d169f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -39,7 +39,7 @@ include_once 'phing/system/io/FileSystem.php';   *  - Error handling reduced to min, error are handled by PhingFile mainly   *   * @author    Andreas Aderhold, andi@binarycloud.com - * @version   $Revision: 1.10 $ + * @version   $Id$   * @package   phing.system.io   */  class UnixFileSystem extends FileSystem { @@ -68,7 +68,7 @@ class UnixFileSystem extends FileSystem {       */      function normalize($strPathname) { -        if (empty($strPathname)) { +        if (!strlen($strPathname)) {              return;          } @@ -191,7 +191,7 @@ class UnixFileSystem extends FileSystem {      /* -- most of the following is mapped to the php natives wrapped by FileSystem */          /* -- Attribute accessors -- */ -    function getBooleanAttributes(&$f) { +    function getBooleanAttributes($f) {          //$rv = getBooleanAttributes0($f);          $name = $f->getName();          $hidden = (strlen($name) > 0) && ($name{0} == '.'); @@ -207,23 +207,47 @@ class UnixFileSystem extends FileSystem {              $perms = (int) (@fileperms($strPath) & 0444);              return FileSystem::Chmod($strPath, $perms);          } else { -            throw new Exception("IllegalArgutmentType: Argument is not File"); +            throw new Exception("IllegalArgumentType: Argument is not File");          }      }      /**       * compares file paths lexicographically       */ -    function compare($f1, $f2) { -        if ( ($f1 instanceof PhingFile) && ($f2 instanceof PhingFile) ) { -            $f1Path = $f1->getPath(); -            $f2Path = $f2->getPath(); -            return (boolean) strcmp((string) $f1Path, (string) $f2Path); -        } else { -            throw new Exception("IllegalArgutmentType: Argument is not PhingFile"); -        } +    function compare(PhingFile $f1, PhingFile $f2) { +        $f1Path = $f1->getPath(); +        $f2Path = $f2->getPath(); +        return strcmp((string) $f1Path, (string) $f2Path);      } +    /** +     * Copy a file, takes care of symbolic links +     * +     * @param PhingFile $src Source path and name file to copy. +     * @param PhingFile $dest Destination path and name of new file. +     * +     * @return void      +     * @throws Exception if file cannot be copied. +     */ +    function copy(PhingFile $src, PhingFile $dest) { +        global $php_errormsg; +         +        if (!$src->isLink()) +        { +            return parent::copy($src, $dest); +        } +         +        $srcPath  = $src->getAbsolutePath(); +        $destPath = $dest->getAbsolutePath(); +         +        $linkTarget = $src->getLinkTarget(); +        if (false === @symlink($linkTarget, $destPath)) +        { +            $msg = "FileSystem::copy() FAILED. Cannot create symlink from $destPath to $linkTarget."; +            throw new Exception($msg); +        } +    } +          /* -- fs interface --*/      function listRoots() { @@ -263,4 +287,16 @@ class UnixFileSystem extends FileSystem {          return $p;      } +    /** +     * Whether file can be deleted. +     * @param PhingFile $f +     * @return boolean +     */ +    function canDelete(PhingFile $f)  +    {  +        @clearstatcache();  +        $dir = dirname($f->getAbsolutePath());  +        return (bool) @is_writable($dir);  +    } +      } diff --git a/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php b/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php index c32c21ff..58331cde 100644 --- a/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php +++ b/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Win32FileSystem.php,v 1.10 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 0cb3f51d8745f08b64f6f394fc0abb84705f512e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -79,7 +79,7 @@ class Win32FileSystem extends FileSystem {       *    2  absolute UNC (if first char is '\\'), else directory-relative (has form "z:foo")       *    3  absolute local pathname (begins with "z:\\")       */ -    function normalizePrefix($strPath, $len, $sb) { +    function normalizePrefix($strPath, $len, &$sb) {          $src = 0;          while (($src < $len) && $this->isSlash($strPath{$src})) {              $src++; @@ -349,7 +349,7 @@ class Win32FileSystem extends FileSystem {          $pl   = (int) $f->getPrefixLength();          if (($pl === 2) && ($path{0} === $this->slash)) { -            return path;            // UNC +            return $path;            // UNC          }          if ($pl === 3) { @@ -471,7 +471,7 @@ class Win32FileSystem extends FileSystem {          @closedir($dir);          return $vv;      } - +      } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php b/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php index 86f76d80..1eae49c4 100644 --- a/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php +++ b/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: WinNTFileSystem.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $ + *  $Id: de8f1d144dc3d34fa978937632a98625c3e5c15d $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,13 +23,12 @@ include_once 'phing/system/io/Win32FileSystem.php';  /**   * FileSystem for Windows NT/2000. - *  @package   phing.system.io + * @package phing.system.io   */ -  class WinNTFileSystem extends Win32FileSystem {      /* -- class only for convenience and future use everything is inherinted --*/  } -?> + diff --git a/buildscripts/phing/classes/phing/system/io/Writer.php b/buildscripts/phing/classes/phing/system/io/Writer.php index 5e1a69b9..86fa67e9 100644 --- a/buildscripts/phing/classes/phing/system/io/Writer.php +++ b/buildscripts/phing/classes/phing/system/io/Writer.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Writer.php,v 1.6 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 1dbdd04d4483e88c8e409811babeaa83c47f8418 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,29 +20,34 @@   */  /** - * Abstract class for writing character streams.  + * Abstract class for writing character streams. + *    * @package   phing.system.io   */  abstract class Writer { - +     +    /** +     * Writes data to output stream. +     * @param string $buf +     * @param int $off +     * @param int $len +     */      abstract public function write($buf, $off = null, $len = null); - -    abstract public function reset(); +    /** +     * Close the stream. +     * @throws IOException - if there is an error closing stream. +     */      abstract public function close(); -    abstract public function open(); - -    public function mark() {} -     -    public function ready() {} - -    public function markSupported() {} +    /** +     * Flush the stream, if supported by the stream. +     */ +    public function flush() {}      /** -     * Returns the filename, url, etc. that is being written to. +     * Returns a string representation of resource filename, url, etc. that is being written to.       * @return string       */     -    abstract function getResource(); +    abstract public function getResource();  } -?> diff --git a/buildscripts/phing/classes/phing/system/lang/Character.php b/buildscripts/phing/classes/phing/system/lang/Character.php index bb7a5589..60285df6 100644 --- a/buildscripts/phing/classes/phing/system/lang/Character.php +++ b/buildscripts/phing/classes/phing/system/lang/Character.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Character.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $ + *  $Id: afe71e9fbaaa9c49e543c338b5fdca1bc7c9d198 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ class Character {      // in form of an object.      // anyway just a thought -    function isLetter($char) { +    public static function isLetter($char) {          if (strlen($char) !== 1)              $char = 0; @@ -46,4 +46,4 @@ class Character {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/lang/EventObject.php b/buildscripts/phing/classes/phing/system/lang/EventObject.php index 4a2211bc..489a82a8 100644 --- a/buildscripts/phing/classes/phing/system/lang/EventObject.php +++ b/buildscripts/phing/classes/phing/system/lang/EventObject.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: EventObject.php,v 1.5 2005/02/27 20:52:10 mrook Exp $ + *  $Id: b844b1250c5bf730b5eeaccc01bdb24ebbb336e4 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -49,4 +49,4 @@ class EventObject {          }      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php b/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php index ff48c785..5da28838 100644 --- a/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php +++ b/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FileNotFoundException.php,v 1.4 2005/02/27 20:52:10 mrook Exp $ + *  $Id: b5edc38a7438b81c032898ccf3c2be0e83d55203 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,4 +24,3 @@   */  class FileNotFoundException extends Exception {} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/system/lang/NullPointerException.php b/buildscripts/phing/classes/phing/system/lang/NullPointerException.php index 38fa5c10..ccf080f5 100644 --- a/buildscripts/phing/classes/phing/system/lang/NullPointerException.php +++ b/buildscripts/phing/classes/phing/system/lang/NullPointerException.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: NullPointerException.php,v 1.4 2005/02/27 20:52:10 mrook Exp $ + *  $Id: b1e0bb7b6ed5dd7391d7c251e736bba1d14ce4b5 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,4 +24,3 @@   */  class NullPointerException extends Exception {} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/system/lang/SecurityException.php b/buildscripts/phing/classes/phing/system/lang/SecurityException.php index 21e8b1c3..74013bc0 100644 --- a/buildscripts/phing/classes/phing/system/lang/SecurityException.php +++ b/buildscripts/phing/classes/phing/system/lang/SecurityException.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: SecurityException.php,v 1.4 2005/02/27 20:52:10 mrook Exp $ + *  $Id: 2df99e97af67f5f2cbe2ec930e8daddc8a10b406 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,4 +24,3 @@   */  class SecurityException extends Exception {} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/system/util/Message.php b/buildscripts/phing/classes/phing/system/util/Message.php deleted file mode 100644 index bf7bb56b..00000000 --- a/buildscripts/phing/classes/phing/system/util/Message.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php -// -// FIXME. Logger will be renamed to Message, new level is introduces MSG_NOTICE -// Message can handle some more later on -//   - formatted output -//   - sending to dialog or phpgtk whatever -//   - etc -// -?> diff --git a/buildscripts/phing/classes/phing/system/util/Properties.php b/buildscripts/phing/classes/phing/system/util/Properties.php index deff2cdf..4ffd04fc 100644..100755 --- a/buildscripts/phing/classes/phing/system/util/Properties.php +++ b/buildscripts/phing/classes/phing/system/util/Properties.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: Properties.php,v 1.13 2005/05/26 13:10:52 mrook Exp $ + *  $Id: 577374dcb65bb9a2614bc80f605ce49600d64778 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -30,11 +30,30 @@ include_once 'phing/system/io/FileWriter.php';   *        - Add support for arrays (separated by ',')   *   * @package    phing.system.util - * @version $Revision: 1.13 $ + * @version $Id: 577374dcb65bb9a2614bc80f605ce49600d64778 $   */  class Properties {      private $properties = array(); +     +    /** +     * @var PhingFile +     */ +    private $file = null; +     +    /** +     * Constructor +     * +     * @param array $properties +     */ +    function __construct($properties = NULL) +    { +        if (is_array($properties)) { +            foreach ($properties as $key => $value) { +                $this->setProperty($key, $value); +            } +        } +    }      /**       * Load properties from a file. @@ -46,6 +65,8 @@ class Properties {      function load(PhingFile $file) {          if ($file->canRead()) {              $this->parse($file->getPath(), false);                     + +            $this->file = $file;          } else {              throw new IOException("Can not read file ".$file->getPath());          } @@ -75,21 +96,17 @@ class Properties {          $sec_name = "";          foreach($lines as $line) { +            // strip comments and leading/trailing spaces +            $line = trim(preg_replace("/\s+[;#]\s.+$/", "", $line)); -            $line = trim($line); -     -            if($line == "") -                continue; -                     -            if ($line{0} == '#' or $line{0} == ';') { -                // it's a comment, so continue to next line +            if (empty($line) || $line[0] == ';' || $line[0] == '#') {                  continue; -            } else { -                $pos = strpos($line, '='); -                $property = trim(substr($line, 0, $pos)); -                $value = trim(substr($line, $pos + 1));                 -                $this->properties[$property] = $this->inVal($value);              } +                 +            $pos = strpos($line, '='); +            $property = trim(substr($line, 0, $pos)); +            $value = trim(substr($line, $pos + 1));                 +            $this->properties[$property] = $this->inVal($value);          } // for each line              } @@ -135,7 +152,7 @@ class Properties {      public function toString() {          $buf = "";                  foreach($this->properties as $key => $item) { -            $buf .= $key . "=" . $this->outVal($item) . Phing::getProperty('line.separator'); +            $buf .= $key . "=" . $this->outVal($item) . PHP_EOL;          }          return $buf;          } @@ -148,15 +165,22 @@ class Properties {       * @return void       * @throws IOException - on error writing properties file.       */ -    function store(PhingFile $file, $header = null) { +    function store(PhingFile $file = null, $header = null) { +        if ($file == null) { +            $file = $this->file; +        } +         +        if ($file == null) { +            throw new IOException("Unable to write to empty filename"); +        } +                  // stores the properties in this object in the file denoted          // if file is not given and the properties were loaded from a          // file prior, this method stores them in the file used by load()                  try {              $fw = new FileWriter($file); -            $fw->open();              if ($header !== null) { -                $fw->write( "# " . $header . Phing::getProperty("line.separator") ); +                $fw->write( "# " . $header . PHP_EOL );              }              $fw->write($this->toString());              $fw->close(); @@ -215,7 +239,10 @@ class Properties {       * @return mixed Old property value or NULL if none was set.       */      function setProperty($key, $value) { -        $oldValue = @$this->properties[$key];        +        $oldValue = null; +        if (isset($this->properties[$key])) { +            $oldValue = $this->properties[$key]; +        }          $this->properties[$key] = $value;          return $oldValue;      } @@ -233,6 +260,23 @@ class Properties {      }      /** +     * Appends a value to a property if it already exists with a delimiter +     * +     * If the property does not, it just adds it. +     *  +     * @param string $key +     * @param mixed $value +     * @param string $delimiter +     */ +    function append($key, $value, $delimiter = ',') { +        $newValue = $value; +        if (isset($this->properties[$key]) && !empty($this->properties[$key]) ) { +            $newValue = $this->properties[$key] . $delimiter . $value; +        } +        $this->properties[$key] = $newValue; +    } + +    /**       * Same as keys() function, returns an array of property names.       * @return array       */ @@ -267,4 +311,4 @@ class Properties {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/system/util/Register.php b/buildscripts/phing/classes/phing/system/util/Register.php index 5ef2b2fd..56ab0e45 100644..100755 --- a/buildscripts/phing/classes/phing/system/util/Register.php +++ b/buildscripts/phing/classes/phing/system/util/Register.php @@ -35,7 +35,7 @@   * </code>   *   * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.3 $ + * @version $Id$   * @package phing.system.util   */  class Register { @@ -62,6 +62,8 @@ class Register {  /**   * Represents a slot in the register. + * + * @package phing.system.util   */  class RegisterSlot { @@ -111,5 +113,37 @@ class RegisterSlot {          return $this->value;      } +    /** +     * Recursively implodes an array to a comma-separated string +     * @param  array  $arr +     * @return string +     */ +    private function implodeArray(array $arr) { +        $values = array(); +         +        foreach ($arr as $value) { +            if (is_array($value)) { +                $values[] = $this->implodeArray($value); +            } else { +                $values[] = $value; +            } +        } +         +        return "{" . implode(",", $values) . "}"; +    } +     +    /** +     * Returns the value at this slot as a string value. +     * @return string +     */ +    public function __toString() +    { +        if (is_array($this->value)) { +            return $this->implodeArray($this->value); +        } else { +            return (string) $this->value; +        } +    } +      } -?> + diff --git a/buildscripts/phing/classes/phing/system/util/Timer.php b/buildscripts/phing/classes/phing/system/util/Timer.php index a2a665b0..2d2bcc01 100644..100755 --- a/buildscripts/phing/classes/phing/system/util/Timer.php +++ b/buildscripts/phing/classes/phing/system/util/Timer.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Timer.php,v 1.5 2003/12/24 13:02:09 hlellelid Exp $ + *  $Id: 085b1a92f765375e97d2c09c7569ca5747a44634 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -38,7 +38,7 @@   * @author    Charles Killian   * @author    Hans Lellelid <hans@xmpl.org>   * @package    phing.system.util - * @version    $Revision: 1.5 $ $Date: 2003/12/24 13:02:09 $ + * @version    $Id$   */  class Timer { diff --git a/buildscripts/phing/classes/phing/tasks/defaults.properties b/buildscripts/phing/classes/phing/tasks/defaults.properties index d0e62eff..32a03295 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/defaults.properties +++ b/buildscripts/phing/classes/phing/tasks/defaults.properties @@ -3,13 +3,15 @@  ; -------------------------------------  ; Internal system tasks -;  +;  adhoc=phing.tasks.system.AdhocTask  adhoc-task=phing.tasks.system.AdhocTaskdefTask  adhoc-type=phing.tasks.system.AdhocTypedefTask  append=phing.tasks.system.AppendTask  available=phing.tasks.system.AvailableTask  chmod=phing.tasks.system.ChmodTask +chown=phing.tasks.system.ChownTask +concat=phing.tasks.system.AppendTask  condition=phing.tasks.system.ConditionTask  copy=phing.tasks.system.CopyTask  cvs=phing.tasks.system.CvsTask @@ -17,7 +19,7 @@ cvspass=phing.tasks.system.CvsPassTask  delete=phing.tasks.system.DeleteTask  echo=phing.tasks.system.EchoTask  exec=phing.tasks.system.ExecTask -fail=phing.tasks.system.ExitTask +fail=phing.tasks.system.FailTask  foreach=phing.tasks.system.ForeachTask  includepath=phing.tasks.system.IncludePathTask  input=phing.tasks.system.InputTask @@ -38,32 +40,106 @@ uptodate=phing.tasks.system.UpToDateTask  xslt=phing.tasks.system.XsltTask  if=phing.tasks.system.IfTask  warn=phing.tasks.system.WarnTask +import=phing.tasks.system.ImportTask +loadfile=phing.tasks.system.LoadFileTask  ; "Core" contributed tasks  ; -- i.e. no taskdef needed. -sql=phing.tasks.ext.CreoleSQLExecTask +creole=phing.tasks.ext.creole.CreoleSQLExecTask +pdo=phing.tasks.ext.pdo.PDOSQLExecTask +pdosqlexec=phing.tasks.ext.pdo.PDOSQLExecTask  package-as-path=phing.tasks.ext.PackageAsPathTask  smarty=phing.tasks.ext.SmartyTask  capsule=phing.tasks.ext.CapsuleTask  tar=phing.tasks.ext.TarTask +untar=phing.tasks.ext.UntarTask  pearpkg=phing.tasks.ext.PearPackageTask +pearpkg2=phing.tasks.ext.PearPackage2Task  mail=phing.tasks.ext.MailTask  zip=phing.tasks.ext.ZipTask -phplint=phing.tasks.ext.PhpLintTask +unzip=phing.tasks.ext.UnzipTask +waitfor=phing.tasks.system.WaitForTask +trycatch=phing.tasks.system.TryCatchTask  ; "ext" tasks -phpdoc=phing.tasks.ext.phpdoc.PHPDocumentorTask +phpdoc=phing.tasks.ext.phpdoc.PhpDocumentorTask +phpdocext=phing.tasks.ext.phpdoc.PhpDocumentorExternalTask  svnlastrevision=phing.tasks.ext.svn.SvnLastRevisionTask +svncheckout=phing.tasks.ext.svn.SvnCheckoutTask  svnexport=phing.tasks.ext.svn.SvnExportTask -phpunit2=phing.tasks.ext.phpunit2.PHPUnit2Task -phpunit2report=phing.tasks.ext.phpunit2.PHPUnit2ReportTask +svnupdate=phing.tasks.ext.svn.SvnUpdateTask +svnswitch=phing.tasks.ext.svn.SvnSwitchTask +svncopy=phing.tasks.ext.svn.SvnCopyTask +svncommit=phing.tasks.ext.svn.SvnCommitTask +svnlist=phing.tasks.ext.svn.SvnListTask +svnlog=phing.tasks.ext.svn.SvnLogTask +svninfo=phing.tasks.ext.svn.SvnInfoTask +gitinit=phing.tasks.ext.git.GitInitTask +gitclone=phing.tasks.ext.git.GitCloneTask +gitgc=phing.tasks.ext.git.GitGcTask +gitbranch=phing.tasks.ext.git.GitBranchTask +gitfetch=phing.tasks.ext.git.GitFetchTask +gitmerge=phing.tasks.ext.git.GitMergeTask +gitcheckout=phing.tasks.ext.git.GitCheckoutTask +gitpull=phing.tasks.ext.git.GitPullTask +gitpush=phing.tasks.ext.git.GitPushTask +gitlog=phing.tasks.ext.git.GitLogTask +gittag=phing.tasks.ext.git.GitTagTask +phpunit3=phing.tasks.ext.phpunit.PHPUnitTask +phpunit3report=phing.tasks.ext.phpunit.PHPUnitReportTask +phpunit=phing.tasks.ext.phpunit.PHPUnitTask +phpunitreport=phing.tasks.ext.phpunit.PHPUnitReportTask  coverage-setup=phing.tasks.ext.coverage.CoverageSetupTask  coverage-merger=phing.tasks.ext.coverage.CoverageMergerTask  coverage-report=phing.tasks.ext.coverage.CoverageReportTask +coverage-threshold=phing.tasks.ext.coverage.CoverageThresholdTask  ioncubeencoder=phing.tasks.ext.ioncube.IoncubeEncoderTask  ioncubelicense=phing.tasks.ext.ioncube.IoncubeLicenseTask  simpletest=phing.tasks.ext.simpletest.SimpleTestTask  phplint=phing.tasks.ext.PhpLintTask  xmllint=phing.tasks.ext.XmlLintTask -analyze=phing.tasks.ext.ZendCodeAnalyzerTask
\ No newline at end of file +analyze=phing.tasks.ext.ZendCodeAnalyzerTask +zendcodeanalyzer=phing.tasks.ext.ZendCodeAnalyzerTask +jsllint=phing.tasks.ext.JslLintTask +manifest=phing.tasks.ext.ManifestTask +phpcodesniffer=phing.tasks.ext.PhpCodeSnifferTask +phpcpd=phing.tasks.ext.phpcpd.PHPCPDTask +phpmd=phing.tasks.ext.phpmd.PHPMDTask +phpdepend=phing.tasks.ext.pdepend.PhpDependTask +ftpdeploy=phing.tasks.ext.FtpDeployTask +phkpackage=phing.tasks.ext.phk.PhkPackageTask +pharpackage=phing.tasks.ext.phar.PharPackageTask +scp=phing.tasks.ext.ScpTask +; deprecate ScpSendTask +scpsend=phing.tasks.ext.ScpTask +ssh=phing.tasks.ext.SshTask +replaceregexp=phing.tasks.ext.ReplaceRegexpTask +jsmin=phing.tasks.ext.jsmin.JsMinTask +version=phing.tasks.ext.VersionTask +filehash=phing.tasks.ext.FileHashTask +filesize=phing.tasks.ext.FileSizeTask +xmlproperty=phing.tasks.ext.XmlPropertyTask +exportproperties=phing.tasks.ext.ExportPropertiesTask +http-request=phing.tasks.ext.HttpRequestTask +httpget=phing.tasks.ext.HttpGetTask +patch=phing.tasks.ext.PatchTask +dbdeploy=phing.tasks.ext.dbdeploy.DbDeployTask +symlink=phing.tasks.ext.SymlinkTask +s3get=phing.tasks.ext.Service.Amazon.S3.S3GetTask +s3put=phing.tasks.ext.Service.Amazon.S3.S3PutTask +zendguardencode=phing.tasks.ext.zendguard.ZendGuardEncodeTask +zendguardlicense=phing.tasks.ext.zendguard.ZendGuardLicenseTask +docblox=phing.tasks.ext.docblox.DocBloxTask +phpdoc2=phing.tasks.ext.phpdoc.PhpDocumentor2Task +rST=phing.tasks.ext.rSTTask +apigen=phing.tasks.ext.apigen.ApiGenTask +parallel=phing.tasks.ext.ParallelTask +symfonyconsole=phing.tasks.ext.SymfonyConsole.SymfonyConsoleTask +; liquibase +liquibase-changelog=phing.tasks.ext.liquibase.LiquibaseChangeLogTask +liquibase-dbdoc=phing.tasks.ext.liquibase.LiquibaseDbDocTask +liquibase-diff=phing.tasks.ext.liquibase.LiquibaseDiffTask +liquibase-rollback=phing.tasks.ext.liquibase.LiquibaseRollbackTask +liquibase-tag=phing.tasks.ext.liquibase.LiquibaseTagTask +liquibase-update=phing.tasks.ext.liquibase.LiquibaseUpdateTask diff --git a/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php b/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php index aa43a0e4..13ccd73d 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: CapsuleTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 205bc55fd1f7f36783d105ff2d0e27357282bbed $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/util/StringHelper.php';   * This is based on the interface to TexenTask from Apache's Velocity engine.    *   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.17 $ + * @version   $Id: 205bc55fd1f7f36783d105ff2d0e27357282bbed $   * @package   phing.tasks.ext   */  class CapsuleTask extends Task { @@ -185,7 +185,7 @@ class CapsuleTask extends Task {      public function setOutputDirectory(PhingFile $outputDirectory) {          try {              if (!$outputDirectory->exists()) { -                $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE); +                $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),Project::MSG_VERBOSE);                  if (!$outputDirectory->mkdirs()) {                      throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());                  } @@ -393,7 +393,7 @@ class CapsuleTask extends Task {                  // reset value, and then                   // read in teh contents of the file into that var                  $value = ""; -                $f = new PhingFile($project->resolveFile($value)->getCanonicalPath());                         +                $f = new PhingFile($this->project->resolveFile($value)->getCanonicalPath());                  if ($f->exists()) {                      $fr = new FileReader($f);                      $fr->readInto($value); @@ -453,25 +453,27 @@ class CapsuleTask extends Task {  /**   * An "inner" class for holding assigned var values.   * May be need to expand beyond name/value in the future. + * + * @package phing.tasks.ext   */  class AssignedVar {      private $name;      private $value; -    function setName($v) { +    public function setName($v) {          $this->name = $v;      } -    function setValue($v) { +    public function setValue($v) {          $this->value = $v;      } -    function getName() { +    public function getName() {          return $this->name;      } -    function getValue() { +    public function getValue() {          return $this->value;      } diff --git a/buildscripts/phing/classes/phing/tasks/ext/ExportPropertiesTask.php b/buildscripts/phing/classes/phing/tasks/ext/ExportPropertiesTask.php new file mode 100644 index 00000000..8bc64bbb --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ExportPropertiesTask.php @@ -0,0 +1,141 @@ +<?php + +/* + *  $Id: 7d96a453b74edc40fdea85ba8befe6459334016d $ + * + * 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/Task.php"; + +/** + * Saves currently defined properties into a specified file + *  + * @author Andrei Serdeliuc + * @extends Task + * @version   $Id: 7d96a453b74edc40fdea85ba8befe6459334016d $ + * @package   phing.tasks.ext + */ +class ExportPropertiesTask extends Task +{ +    /** +     * Array of project properties +     *  +     * (default value: null) +     *  +     * @var array +     * @access private +     */ +    private $_properties = null; +     +    /** +     * Target file for saved properties +     *  +     * (default value: null) +     *  +     * @var string +     * @access private +     */ +    private $_targetFile = null; +     +    /** +     * Exclude properties starting with these prefixes +     *  +     * @var array +     * @access private +     */ +    private $_disallowedPropertyPrefixes = array( +        'host.', +        'phing.', +        'os.', +        'php.', +        'line.', +        'env.', +        'user.' +    ); + +    /** +     * setter for _targetFile +     *  +     * @access public +     * @param string $file +     * @return bool +     */ +    public function setTargetFile($file) +    { +        if(!is_dir(dirname($file))) { +            throw new BuildException("Parent directory of target file doesn't exist"); +        } +         +        if(!is_writable(dirname($file)) && (file_exists($file) && !is_writable($file))) { +            throw new BuildException("Target file isn't writable"); +        } +         +        $this->_targetFile = $file; +        return true; +    } +     +    /** +     * setter for _disallowedPropertyPrefixes +     *  +     * @access public +     * @param string $file +     * @return bool +     */ +    public function setDisallowedPropertyPrefixes($prefixes) +    { +        $this->_disallowedPropertyPrefixes = explode(",", $prefixes); +        return true; +    }     + +    public function main() +    { +        // Sets the currently declared properties +        $this->_properties = $this->getProject()->getProperties(); +         +        if(is_array($this->_properties) && !empty($this->_properties) && null !== $this->_targetFile) { +            $propertiesString = ''; +            foreach($this->_properties as $propertyName => $propertyValue) { +                if(!$this->isDisallowedPropery($propertyName)) { +                    $propertiesString .= $propertyName . "=" . $propertyValue . PHP_EOL; +                } +            } +             +            if(!file_put_contents($this->_targetFile, $propertiesString)) { +                throw new BuildException('Failed writing to ' . $this->_targetFile); +            } +        } +    } +     +    /** +     * Checks if a property name is disallowed +     *  +     * @access protected +     * @param string $propertyName +     * @return bool +     */ +    protected function isDisallowedPropery($propertyName) +    { +        foreach($this->_disallowedPropertyPrefixes as $property) { +            if(substr($propertyName, 0, strlen($property)) == $property) { +                return true; +            } +        } +         +        return false; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/ExtractBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/ExtractBaseTask.php new file mode 100644 index 00000000..e47acc24 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ExtractBaseTask.php @@ -0,0 +1,199 @@ +<?php +/* + * + * 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'; + +/** + * Base class for extracting tasks such as Unzip and Untar. + * + * @author    Joakim Bodin <joakim.bodin+phing@gmail.com> + * @version   $Id: 8aa7996b72792da30f1ec94174f09b9c612bcc1a $ + * @package   phing.tasks.ext + * @since     2.2.0 + */ +abstract class ExtractBaseTask extends MatchingTask { +    /** +     * @var PhingFile $file +     */ +    protected $file; +    /** +     * @var PhingFile $todir +     */ +    protected $todir; +    protected $removepath; +    protected $filesets = array(); // all fileset objects assigned to this task +     +    /** +     * Set to true to always extract (and possibly overwrite) +     * all files from the archive  +     * @var boolean +     */ +    protected $forceExtract = false; + +    /** +     * Add a new fileset. +     * @return FileSet +     */ +    public function createFileSet() { +        $this->fileset = new FileSet(); +        $this->filesets[] = $this->fileset; +        return $this->fileset; +    } + +    /** +     * Set the name of the zip file to extract. +     * @param PhingFile $file zip file to extract +     */ +    public function setFile(PhingFile $file) { +        $this->file = $file; +    } + +    /** +     * This is the base directory to look in for things to zip. +     * @param PhingFile $baseDir +     */ +    public function setToDir(PhingFile $todir) { +        $this->todir = $todir; +    } +     +    public function setRemovePath($removepath) +    { +        $this->removepath = $removepath; +    } +     +    /** +     * Sets the forceExtract attribute +     * @param boolean $forceExtract +     */ +    public function setForceExtract($forceExtract) +    { +        $this->forceExtract = (bool) $forceExtract; +    } + +    /** +     * do the work +     * @throws BuildException +     */ +    public function main() { +     +        $this->validateAttributes(); +         +        $filesToExtract = array(); +        if ($this->file !== null) { +            if(!$this->isDestinationUpToDate($this->file)) { +                $filesToExtract[] = $this->file; +            } else { +                $this->log('Nothing to do: ' . $this->todir->getAbsolutePath() . ' is up to date for ' .  $this->file->getCanonicalPath(), Project::MSG_INFO); +            } +        } +         +        foreach($this->filesets as $compressedArchiveFileset) { +            $compressedArchiveDirScanner = $compressedArchiveFileset->getDirectoryScanner($this->project); +            $compressedArchiveFiles = $compressedArchiveDirScanner->getIncludedFiles(); +            $compressedArchiveDir = $compressedArchiveFileset->getDir($this->project); +             +            foreach ($compressedArchiveFiles as $compressedArchiveFilePath) { +                $compressedArchiveFile = new PhingFile($compressedArchiveDir, $compressedArchiveFilePath); +                if($compressedArchiveFile->isDirectory()) +                { +                    throw new BuildException($compressedArchiveFile->getAbsolutePath() . ' compressed archive cannot be a directory.'); +                } +                 +                if ($this->forceExtract || !$this->isDestinationUpToDate($compressedArchiveFile)) { +                   $filesToExtract[] = $compressedArchiveFile; +                } else { +                    $this->log('Nothing to do: ' . $this->todir->getAbsolutePath() . ' is up to date for ' .  $compressedArchiveFile->getCanonicalPath(), Project::MSG_INFO); +                } +            } +        } +         +        foreach ($filesToExtract as $compressedArchiveFile) { +            $this->extractArchive($compressedArchiveFile); +        } +    } +     +    abstract protected function extractArchive(PhingFile $compressedArchiveFile); +     +    /** +     * @param array $files array of filenames +     * @param PhingFile $dir +     * @return boolean +     */ +    protected function isDestinationUpToDate(PhingFile $compressedArchiveFile) { +        if (!$compressedArchiveFile->exists()) { +            throw new BuildException("Could not find file " . $compressedArchiveFile->__toString() . " to extract."); +        } +         +        $compressedArchiveContent = $this->listArchiveContent($compressedArchiveFile); +        if(is_array($compressedArchiveContent)) { +             +            $fileSystem = FileSystem::getFileSystem(); +            foreach ($compressedArchiveContent as $compressArchivePathInfo) { +                $compressArchiveFilename = $compressArchivePathInfo['filename']; +                if(!empty($this->removepath) && strlen($compressArchiveFilename) >= strlen($this->removepath)) +                { +                    $compressArchiveFilename = preg_replace('/^' . $this->removepath . '/','', $compressArchiveFilename); +                } +                $compressArchivePath = new PhingFile($this->todir, $compressArchiveFilename); +                 +                if(!$compressArchivePath->exists() || +                    $fileSystem->compareMTimes($compressedArchiveFile->getCanonicalPath(), $compressArchivePath->getCanonicalPath()) == 1) { +                    return false; +                } +            } +             +        } +         +        return true; +    } +     +    abstract protected function listArchiveContent(PhingFile $compressedArchiveFile); +     +    /** +     * Validates attributes coming in from XML +     * +     * @access  private +     * @return  void +     * @throws  BuildException +     */ +    protected function validateAttributes() { +     +        if ($this->file === null && count($this->filesets) === 0) { +            throw new BuildException("Specify at least one source compressed archive - a file or a fileset."); +        } + +        if ($this->todir === null) { +            throw new BuildException("todir must be set."); +        } +         +        if ($this->todir !== null && $this->todir->exists() && !$this->todir->isDirectory()) { +            throw new BuildException("todir must be a directory."); +        } + +        if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) { +            throw new BuildException("Compressed archive file cannot be a directory."); +        } +         +        if ($this->file !== null && !$this->file->exists()) { +            throw new BuildException("Could not find compressed archive file " . $this->file->__toString() . " to extract."); +        } +    } +     +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/FileHashTask.php b/buildscripts/phing/classes/phing/tasks/ext/FileHashTask.php new file mode 100644 index 00000000..5660e793 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/FileHashTask.php @@ -0,0 +1,147 @@ +<?php +/* + * $Id: c59aff266a03f0e2cf22dc33143f2decf2d5e05c $ + * + * 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/Task.php'; + +/** + * fileHash + * + * Calculate either MD5 or SHA hash value of a specified file and retun the + * value in a property + * + * @author      Johan Persson <johan162@gmail.com> + * @version     $Id: c59aff266a03f0e2cf22dc33143f2decf2d5e05c $ + * @package     phing.tasks.ext + */ +class FileHashTask extends Task +{ +    /** +     * Property for File +     * @var PhingFile file +     */ +    private $file; + +    /** +     * Property to be set +     * @var string $property +     */ +    private $propertyName = "filehashvalue"; +     +    /** +     * Specify which hash algorithm to use. +     *   0 = MD5 +     *   1 = SHA1 +     *  +     * @var integer $hashtype +     */ +    private $hashtype=0; + + +    /** +     * Specify if MD5 or SHA1 hash should be used +     * @param integer $type 0=MD5, 1=SHA1 +     */ +    public function setHashtype($type) +    { +        $this->hashtype = $type; +    } + +    /** +     * Which file to calculate the hash value of +     * @param PhingFile $file +     */ +    public function setFile($file) +    { +        $this->file = $file; +    } + +    /** +     * Set the name of the property to store the hash value in +     * @param $property +     * @return void +     */ +    public function setPropertyName($property) +    { +        $this->propertyName = $property; +    } + +    /** +     * Main-Method for the Task +     * +     * @return  void +     * @throws  BuildException +     */ +    public function main() +    { +        $this->checkFile(); +        $this->checkPropertyName(); + +        // read file +        if( (int)$this->hashtype === 0 ) { +            $this->log("Calculating MD5 hash from: ".$this->file); +            $hashValue = md5_file($this->file,false); +        } +        elseif( (int)$this->hashtype === 1 ) { +            $this->log("Calculating SHA1 hash from: ".$this->file); +            $hashValue = sha1_file($this->file,false); +        } +        else { +            throw new BuildException( +                sprintf('[FileHash] Unknown hashtype specified %d. Must be either 0 (=MD5) or 1 (=SHA1).',$this->hashtype)); +             +        } + +        // publish hash value +        $this->project->setProperty($this->propertyName, $hashValue); + +    } + +    /** +     * checks file attribute +     * @return void +     * @throws BuildException +     */ +    private function checkFile() +    { +        // check File +        if ($this->file === null || +            strlen($this->file) == 0) { +            throw new BuildException('[FileHash] You must specify an input file.', $this->file); +        } + +        if( ! is_readable($this->file) ) {  +            throw new BuildException(sprintf('[FileHash] Input file does not exist or is not readable: %s',$this->file)); +        }      + +    } + +    /** +     * checks property attribute +     * @return void +     * @throws BuildException +     */ +    private function checkPropertyName() +    { +        if (is_null($this->propertyName) || +            strlen($this->propertyName) === 0) { +            throw new BuildException('Property name for publishing hashvalue is not set'); +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/FileSizeTask.php b/buildscripts/phing/classes/phing/tasks/ext/FileSizeTask.php new file mode 100644 index 00000000..120197dd --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/FileSizeTask.php @@ -0,0 +1,120 @@ +<?php +/* + * $Id: 2a59c1a9b46f3fd71df0fd3b50908eff268fd630 $ + * + * 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/Task.php'; + +/** + * fileHash + * + * Calculate either MD5 or SHA hash value of a specified file and retun the + * value in a property + * + * @author      Johan Persson <johan162@gmail.com> + * @version     $Id: 2a59c1a9b46f3fd71df0fd3b50908eff268fd630 $ + * @package     phing.tasks.ext + */ +class FileSizeTask extends Task +{ +    /** +     * Property for File +     * @var PhingFile file +     */ +    private $file; + +    /** +     * Property where the file size will be stored +     * @var string $property +     */ +    private $propertyName = "filesize"; +     +    /** +     * Which file to calculate the file size of +     * @param PhingFile $file +     */ +    public function setFile($file) +    { +        $this->file = $file; +    } + +    /** +     * Set the name of the property to store the file size +     * @param $property +     * @return void +     */ +    public function setPropertyName($property) +    { +        $this->propertyName = $property; +    } + +    /** +     * Main-Method for the Task +     * +     * @return  void +     * @throws  BuildException +     */ +    public function main() +    { +        $this->checkFile(); +        $this->checkPropertyName(); + +        $size = filesize($this->file); + +        if( $size === false ) { +            throw new BuildException(sprintf('[FileSize] Cannot determine size of file: %s',$this->file)); +             +        } + +        // publish hash value +        $this->project->setProperty($this->propertyName, $size); + +    } + +    /** +     * checks file attribute +     * @return void +     * @throws BuildException +     */ +    private function checkFile() +    { +        // check File +        if ($this->file === null || +            strlen($this->file) == 0) { +            throw new BuildException('[FileSize] You must specify an input file.', $this->file); +        } + +        if( ! is_readable($this->file) ) {  +            throw new BuildException(sprintf('[FileSize] Input file does not exist or is not readable: %s',$this->file)); +        }      + +    } + +    /** +     * checks property attribute +     * @return void +     * @throws BuildException +     */ +    private function checkPropertyName() +    { +        if (is_null($this->propertyName) || +            strlen($this->propertyName) === 0) { +            throw new BuildException('[FileSize] Property name for publishing file size is not set'); +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/FtpDeployTask.php b/buildscripts/phing/classes/phing/tasks/ext/FtpDeployTask.php new file mode 100644 index 00000000..136c0ac7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/FtpDeployTask.php @@ -0,0 +1,233 @@ +<?php +/** + * $Id: 87063ecf88b18eae74c2bca3918a1b4ac9f52807 $ + * + * 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/Task.php'; + +/** + * FtpDeployTask + *  + * Deploys a set of files to a remote FTP server. + *  + *  + * Example usage: + * <ftpdeploy host="host" port="21" username="user" password="password" dir="public_html" mode="ascii" clearfirst="true"> + *   <fileset dir="."> + *     <include name="**"/> + *     <exclude name="phing"/> + *     <exclude name="build.xml"/> + *     <exclude name="images/**.png"/> + *     <exclude name="images/**.gif"/> + *     <exclude name="images/**.jpg"/> + *   </fileset> + * </ftpdeploy> + * + * @author Jorrit Schippers <jorrit at ncode dot nl> + * @version $Id: 87063ecf88b18eae74c2bca3918a1b4ac9f52807 $ + * @since 2.3.1 + * @package  phing.tasks.ext + */ +class FtpDeployTask extends Task +{ +    private $host = null; +    private $port = 21; +    private $username = null; +    private $password = null; +    private $dir = null; +    private $filesets; +    private $completeDirMap; +    private $mode = FTP_BINARY; +    private $clearFirst = false; +    private $passive = false; + +    protected $logLevel = Project::MSG_VERBOSE; +     +    public function __construct() { +        $this->filesets = array(); +        $this->completeDirMap = array(); +    } +     +    public function setHost($host) { +        $this->host = $host; +    } +     +    public function setPort($port) { +        $this->port = (int) $port; +    } +     +    public function setUsername($username) { +        $this->username = $username; +    } +     +    public function setPassword($password) { +        $this->password = $password; +    } +     +    public function setDir($dir) { +        $this->dir = $dir; +    } +     +    public function setMode($mode) { +        switch(strtolower($mode)) { +            case 'ascii': +                $this->mode = FTP_ASCII; +                break; +            case 'binary': +            case 'bin': +                $this->mode = FTP_BINARY; +                break; +        } +    } +     +    public function setPassive($passive) +    { +        $this->passive = (bool) $passive; +    } +     +    public function setClearFirst($clearFirst) { +        $this->clearFirst = (bool) $clearFirst; +    } +     +    public function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } +     +    /** +     * Set level of log messages generated (default = info) +     * @param string $level +     */ +    public function setLevel($level) +    { +        switch ($level) +        { +            case "error": $this->logLevel = Project::MSG_ERR; break; +            case "warning": $this->logLevel = Project::MSG_WARN; break; +            case "info": $this->logLevel = Project::MSG_INFO; break; +            case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; +            case "debug": $this->logLevel = Project::MSG_DEBUG; break; +        } +    } + +    /** +     * The init method: check if Net_FTP is available +     */ +    public function init() { +        require_once 'PEAR.php'; + +        $paths = explode(PATH_SEPARATOR, get_include_path()); +        foreach($paths as $path) { +            if(file_exists($path.DIRECTORY_SEPARATOR.'Net'.DIRECTORY_SEPARATOR.'FTP.php')) { +                return true; +            } +        } +        throw new BuildException('The FTP Deploy task requires the Net_FTP PEAR package.'); +    } +     +    /** +     * The main entry point method. +     */ +    public function main() { +        $project = $this->getProject(); +         +        require_once 'Net/FTP.php'; +        $ftp = new Net_FTP($this->host, $this->port); +        $ret = $ftp->connect(); +        if(@PEAR::isError($ret)) { +            throw new BuildException('Could not connect to FTP server '.$this->host.' on port '.$this->port.': '.$ret->getMessage()); +        } else { +            $this->log('Connected to FTP server ' . $this->host . ' on port ' . $this->port, $this->logLevel); +        } +         +        $ret = $ftp->login($this->username, $this->password); +        if(@PEAR::isError($ret)) { +            throw new BuildException('Could not login to FTP server '.$this->host.' on port '.$this->port.' with username '.$this->username.': '.$ret->getMessage()); +        } else { +            $this->log('Logged in to FTP server with username ' . $this->username, $this->logLevel); +        } +         +        if ($this->passive) { +            $this->log('Setting passive mode', $this->logLevel); +            $ret = $ftp->setPassive(); +            if(@PEAR::isError($ret)) { +                $ftp->disconnect(); +                throw new BuildException('Could not set PASSIVE mode: '.$ret->getMessage()); +            } +        } + +        // append '/' to the end if necessary +        $dir = substr($this->dir, -1) == '/' ? $this->dir : $this->dir.'/'; +         +        if($this->clearFirst) { +            // TODO change to a loop through all files and directories within current directory +            $this->log('Clearing directory '.$dir, $this->logLevel); +            $ftp->rm($dir, true); +        } +         +        // Create directory just in case +        $ret = $ftp->mkdir($dir, true); +        if(@PEAR::isError($ret)) { +            $ftp->disconnect(); +            throw new BuildException('Could not create directory '.$dir.': '.$ret->getMessage()); +        } +         +        $ret = $ftp->cd($dir); +        if(@PEAR::isError($ret)) { +            $ftp->disconnect(); +            throw new BuildException('Could not change to directory '.$dir.': '.$ret->getMessage()); +        } else { +            $this->log('Changed directory ' . $dir, $this->logLevel); +        } +         +        $fs = FileSystem::getFileSystem(); +        $convert = $fs->getSeparator() == '\\'; +         +        foreach($this->filesets as $fs) { +            $ds = $fs->getDirectoryScanner($project); +            $fromDir  = $fs->getDir($project); +            $srcFiles = $ds->getIncludedFiles(); +            $srcDirs  = $ds->getIncludedDirectories(); +            foreach($srcDirs as $dirname) { +                if($convert) +                    $dirname = str_replace('\\', '/', $dirname); +                $this->log('Will create directory '.$dirname, $this->logLevel); +                $ret = $ftp->mkdir($dirname, true); +                if(@PEAR::isError($ret)) { +                    $ftp->disconnect(); +                    throw new BuildException('Could not create directory '.$dirname.': '.$ret->getMessage()); +                } +            } +            foreach($srcFiles as $filename) { +                $file = new PhingFile($fromDir->getAbsolutePath(), $filename); +                if($convert) +                    $filename = str_replace('\\', '/', $filename); +                $this->log('Will copy '.$file->getCanonicalPath().' to '.$filename, $this->logLevel); +                $ret = $ftp->put($file->getCanonicalPath(), $filename, true, $this->mode); +                if(@PEAR::isError($ret)) { +                    $ftp->disconnect(); +                    throw new BuildException('Could not deploy file '.$filename.': '.$ret->getMessage()); +                } +            } +        } +         +        $ftp->disconnect(); +        $this->log('Disconnected from FTP server', $this->logLevel); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/HttpGetTask.php b/buildscripts/phing/classes/phing/tasks/ext/HttpGetTask.php new file mode 100755 index 00000000..114b80a1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/HttpGetTask.php @@ -0,0 +1,170 @@ +<?php +/* + * $Id: f3fa317b72e2f70f1e483fa49dbf089094e2a476 $ + * + * 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/Task.php'; + +/** + * A HTTP request task. + * Making an HTTP request and try to match the response against an provided + * regular expression. + * + * @package phing.tasks.ext + * @author  Ole Markus With <o.with@sportradar.com> + * @version $Id: f3fa317b72e2f70f1e483fa49dbf089094e2a476 $ + */ +class HttpGetTask extends Task +{ +    /** +     * Holds the request URL +     * +     * @var string +     */ +    protected $url = null; + +    /** +     * Holds the filename to store the output in +     * +     * @var string +     */ +    protected $filename = null;     + +    /** +     * Holds the save location +     * +     * @var string +     */ +    protected $dir = null; +     +    /** +     * Holds the proxy +     * +     * @var string +     */ +    protected $_proxy = null; + +    /** +     * Load the necessary environment for running this task. +     * +     * @throws BuildException +     */ +    public function init() +    { +        @include_once 'HTTP/Request2.php'; + +        if (! class_exists('HTTP_Request2')) { +            throw new BuildException( +                'HttpRequestTask depends on HTTP_Request2 being installed ' +                . 'and on include_path.', +                $this->getLocation() +            ); +        } +    } + + +    /** +     * Make the GET request +     * +     * @throws BuildException +     */ +    public function main() +    { +        if (!isset($this->url)) { +            throw new BuildException("Missing attribute 'url'"); +        } + +        if (!isset($this->dir)) { +            throw new BuildException("Missing attribute 'dir'"); +        } +         +        $config = array(); +        if (isset($this->_proxy) && $url = parse_url($this->_proxy)) { +            $config['proxy_user'] = $url['user']; +            $config['proxy_password'] = $url['pass']; +            $config['proxy_host'] = $url['host']; +            $config['proxy_port'] = $url['port']; +        } + +        $this->log("Fetching " . $this->url); + +        $request = new HTTP_Request2($this->url, '', $config); +        $response =  $request->send(); +        if ($response->getStatus() != 200) { +            throw new BuildException("Request unsuccessful. Response from server: " . $response->getStatus() . " " . $response->getReasonPhrase()); +        } +          +        $content = $response->getBody(); +        $disposition = $response->getHeader('content-disposition'); +         +        if ($this->filename) { +            $filename = $this->filename; +        } elseif ($disposition && 0 == strpos($disposition, 'attachment') +            && preg_match('/filename="([^"]+)"/', $disposition, $m)) { +            $filename = basename($m[1]); +        } else { +            $filename = basename(parse_url($this->url, PHP_URL_PATH)); +        } + +        if (!is_writable($this->dir)) { +            throw new BuildException("Cannot write to directory: " . $this->dir); +        } +          +        $filename = $this->dir . "/" . $filename; +        file_put_contents($filename, $content); +          +        $this->log("Contents from " . $this->url . " saved to $filename"); +    } + +    /** +     * Sets the request URL +     *  +     * @param string $url +     */ +    public function setUrl($url) { +        $this->url = $url; +    } + +    /** +     * Sets the filename to store the output in +     *  +     * @param string $filename +     */ +    public function setFilename($filename) { +        $this->filename = $filename; +    } + +    /** +     * Sets the save location +     *  +     * @param string $dir +     */ +    public function setDir($dir) { +        $this->dir = $dir; +    } + +    /** +     * Sets the proxy +     * +     * @param string $proxy +     */ +    public function setProxy($proxy) { +        $this->_proxy = $proxy; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/HttpRequestTask.php b/buildscripts/phing/classes/phing/tasks/ext/HttpRequestTask.php new file mode 100644 index 00000000..e6f15075 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/HttpRequestTask.php @@ -0,0 +1,286 @@ +<?php +/* + * $Id: 495c02bc3a90d24694d8a4bf2d43ac077e0f9ec6 $ + * + * 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/Task.php'; + +/** + * A HTTP request task. + * Making an HTTP request and try to match the response against an provided + * regular expression. + * + * @package phing.tasks.ext + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 495c02bc3a90d24694d8a4bf2d43ac077e0f9ec6 $ + * @since   2.4.1 + */ +class HttpRequestTask extends Task +{ +    /** +     * Holds the request URL +     * +     * @var string +     */ +    protected $_url = null; + +    /** +     * Holds the regular expression that should match the response +     * +     * @var string +     */ +    protected $_responseRegex = ''; + +    /** +     * Whether to enable detailed logging +     * +     * @var boolean +     */ +    protected $_verbose = false; + +    /** +     * Holds additional header data +     * +     * @var array<Parameter> +     */ +    protected $_headers = array(); + +    /** +     * Holds additional config data for HTTP_Request2 +     * +     * @var array<Parameter> +     */ +    protected $_configData = array(); + +    /** +     * Holds the authentication user name +     * +     * @var string +     */ +    protected $_authUser = null; + +    /** +     * Holds the authentication password +     * +     * @var string +     */ +    protected $_authPassword = ''; + +    /** +     * Holds the authentication scheme +     * +     * @var string +     */ +    protected $_authScheme; + +    /** +     * Holds the events that will be logged +     * +     * @var array<string> +     */ +    protected $_observerEvents = array( +        'connect', +        'sentHeaders', +        'sentBodyPart', +        'receivedHeaders', +        'receivedBody', +        'disconnect', +    ); + +    /** +     * Sets the request URL +     * +     * @param string $url +     */ +    public function setUrl($url) +    { +        $this->_url = $url; +    } + +    /** +     * Sets the response regex +     * +     * @param string $regex +     */ +    public function setResponseRegex($regex) +    { +        $this->_responseRegex = $regex; +    } + +    /** +     * Sets the authentication user name +     * +     * @param string $user +     */ +    public function setAuthUser($user) +    { +        $this->_authUser = $user; +    } + +    /** +     * Sets the authentication password +     * +     * @param string $password +     */ +    public function setAuthPassword($password) +    { +        $this->_authPassword = $password; +    } + +    /** +     * Sets the authentication scheme +     * +     * @param string $scheme +     */ +    public function setAuthScheme($scheme) +    { +        $this->_authScheme = $scheme; +    } + +    /** +     * Sets whether to enable detailed logging +     * +     * @param boolean $verbose +     */ +    public function setVerbose($verbose) +    { +        $this->_verbose = StringHelper::booleanValue($verbose); +    } + +    /** +     * Sets a list of observer events that will be logged +     * if verbose output is enabled. +     * +     * @param string $observerEvents List of observer events +     * +     * @return void +     */ +    public function setObserverEvents($observerEvents) +    { +        $this->_observerEvents = array(); + +        $token = ' ,;'; +        $ext   = strtok($observerEvents, $token); + +        while ($ext !== false) { +            $this->_observerEvents[] = $ext; +            $ext = strtok($token); +        } +    } + +    /** +     * Creates an additional header for this task +     * +     * @return Parameter The created header +     */ +    public function createHeader() +    { +        $num = array_push($this->_headers, new Parameter()); +        return $this->_headers[$num-1]; +    } + +    /** +     * Creates a config parameter for this task +     * +     * @return Parameter The created parameter +     */ +    public function createConfig() +    { +        $num = array_push($this->_configData, new Parameter()); +        return $this->_configData[$num-1]; +    } + +    /** +     * Load the necessary environment for running this task. +     * +     * @throws BuildException +     */ +    public function init() +    { +        @include_once 'HTTP/Request2.php'; + +        if (! class_exists('HTTP_Request2')) { +            throw new BuildException( +                'HttpRequestTask depends on HTTP_Request2 being installed ' +                . 'and on include_path.', +                $this->getLocation() +            ); +        } + +        $this->_authScheme = HTTP_Request2::AUTH_BASIC; + +        // Other dependencies that should only be loaded +        // when class is actually used +        require_once 'HTTP/Request2/Observer/Log.php'; +    } + +    /** +     * Make the http request +     */ +    public function main() +    { +        if (!isset($this->_url)) { +            throw new BuildException("Missing attribute 'url' set"); +        } + +        $request = new HTTP_Request2($this->_url); + +        // set the authentication data +        if (!empty($this->_authUser)) { +            $request->setAuth( +                $this->_authUser, +                $this->_authPassword, +                $this->_authScheme +            ); +        } + +        foreach ($this->_configData as $config) { +            $request->setConfig($config->getName(), $config->getValue()); +        } + +        foreach ($this->_headers as $header) { +            $request->setHeader($header->getName(), $header->getValue()); +        } + +        if ($this->_verbose) { +            $observer = new HTTP_Request2_Observer_Log(); + +            // set the events we want to log +            $observer->events = $this->_observerEvents; + +            $request->attach($observer); +        } + +        $response = $request->send(); + +        if ($this->_responseRegex !== '') { +            $matches = array(); +            preg_match($this->_responseRegex, $response->getBody(), $matches); + +            if (count($matches) === 0) { +                throw new BuildException( +                    'The received response body did not match the ' +                    . 'given regular expression' +                ); +            } else { +                $this->log('The response body matched the provided regex.'); +            } +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/JslLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/JslLintTask.php new file mode 100644 index 00000000..77a4aad5 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/JslLintTask.php @@ -0,0 +1,284 @@ +<?php +/* + *  $Id: 551de2e94aa21f44e19dd0806051f1eabf8b20f9 $ + * + * 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/Task.php'; +require_once 'phing/util/DataStore.php'; + +/** + * A Javascript lint task. Checks syntax of Javascript files. + * Javascript lint (http://www.javascriptlint.com) must be in the system path. + * This class is based on Knut Urdalen's PhpLintTask. + * + * @author Stefan Priebsch <stefan.priebsch@e-novative.de> + * @version $Id: 551de2e94aa21f44e19dd0806051f1eabf8b20f9 $ + * @package phing.tasks.ext + */ +class JslLintTask extends Task +{ +    protected $file;  // the source file (from xml attribute) +    protected $filesets = array(); // all fileset objects assigned to this task + +    protected $showWarnings = true; +    protected $haltOnFailure = false; +    protected $hasErrors = false; +    private $badFiles = array(); + +    private $cache = null; +    private $conf = null; + +    private $executable = "jsl"; +     +    /** +     * @var PhingFile +     */ +    protected $tofile = null; + +    /** +     * Sets the flag if warnings should be shown +     * @param boolean $show +     */ +    public function setShowWarnings($show) { +        $this->showWarnings = StringHelper::booleanValue($show); +    } + +    /** +     * The haltonfailure property +     * @param boolean $aValue +     */ +    public function setHaltOnFailure($aValue) { +        $this->haltOnFailure = $aValue; +    } + +    /** +     * File to be performed syntax check on +     * @param PhingFile $file +     */ +    public function setFile(PhingFile $file) { +        $this->file = $file; +    } + +    /** +     * Whether to store last-modified times in cache +     * +     * @param PhingFile $file +     */ +    public function setCacheFile(PhingFile $file) +    { +        $this->cache = new DataStore($file); +    } + +    /** +     * jsl config file +     * +     * @param PhingFile $file +     */ +    public function setConfFile(PhingFile $file) +    { +        $this->conf = $file; +    } + +    public function setExecutable($path){ +        $this->executable = $path; +         +        if (!@file_exists($path)) { +            throw new BuildException("JavaScript Lint executable '{$path}' not found"); +        } +    } +      +    public function getExecutable(){ +        return $this->executable; +    } + +    /** +     * Nested creator, creates a FileSet for this task +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    /** +     * File to save error messages to +     * +     * @param PhingFile $file +     */ +    public function setToFile(PhingFile $tofile) +    { +        $this->tofile = $tofile; +    } + +    /** +     * Execute lint check against PhingFile or a FileSet +     */ +    public function main() { +        if(!isset($this->file) and count($this->filesets) == 0) { +            throw new BuildException("Missing either a nested fileset or attribute 'file' set"); +        } + +        if (empty($this->executable)) { +            throw new BuildException("Missing the 'executable' attribute"); +        } + +        if($this->file instanceof PhingFile) { +            $this->lint($this->file->getPath()); +        } else { // process filesets +            $project = $this->getProject(); +            foreach($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($project); +                $files = $ds->getIncludedFiles(); +                $dir = $fs->getDir($this->project)->getPath(); +                foreach($files as $file) { +                    $this->lint($dir.DIRECTORY_SEPARATOR.$file); +                } +            } +        } + +        // write list of 'bad files' to file (if specified) +        if ($this->tofile) { +            $writer = new FileWriter($this->tofile); +             +            foreach ($this->badFiles as $file => $messages) { +            	foreach ($messages as $msg) { +                	$writer->write($file . "=" . $msg . PHP_EOL); +            	} +            } +             +            $writer->close(); +        } + +        if ($this->haltOnFailure && $this->hasErrors) throw new BuildException('Syntax error(s) in JS files:' .implode(', ', array_keys($this->badFiles))); +    } + +    /** +     * Performs the actual syntax check +     * +     * @param string $file +     * @return void +     */ +    protected function lint($file) +    { +        $command = $this->executable . ' -output-format ' . escapeshellarg('file:__FILE__;line:__LINE__;message:__ERROR__') . ' '; + +        if (isset($this->conf)) { +            $command .= '-conf ' . escapeshellarg($this->conf->getPath()) . ' '; +        } + +        $command .= '-process '; + +        if(file_exists($file)) +        { +            if(is_readable($file)) +            { +                if ($this->cache) +                { +                    $lastmtime = $this->cache->get($file); + +                    if ($lastmtime >= filemtime($file)) +                    { +                        $this->log("Not linting '" . $file . "' due to cache", Project::MSG_DEBUG); +                        return false; +                    } +                } + +                $messages = array(); +                exec($command.'"'.$file.'"', $messages, $return); +                 +                if ($return > 100) { +                    throw new BuildException("Could not execute Javascript Lint executable '{$this->executable}'"); +                } + +                $summary = $messages[sizeof($messages) - 1]; + +                preg_match('/(\d+)\serror/', $summary, $matches); +                $errorCount = (count($matches) > 1 ? $matches[1] : 0); + +                preg_match('/(\d+)\swarning/', $summary, $matches); +                $warningCount = (count($matches) > 1 ? $matches[1] : 0); +                 +                $errors = array(); +                $warnings = array(); +                if ($errorCount > 0 || $warningCount > 0) { +                    $last = false; +                    foreach ($messages as $message) { +                        $matches = array(); +                        if (preg_match('/^(\.*)\^$/', $message)) { +                            $column = strlen($message); +                            if ($last == 'error') { +                                $errors[count($errors) - 1]['column'] = $column; +                            } else if ($last == 'warning') { +                                $warnings[count($warnings) - 1]['column'] = $column; +                            } +                            $last = false; +                        } +                        if (!preg_match('/^file:(.+);line:(\d+);message:(.+)$/', $message, $matches)) continue; +                        $msg = $matches[3]; +                        $data = array('filename' => $matches[1], 'line' => $matches[2], 'message' => $msg); +                        if (preg_match('/^.*error:.+$/i', $msg)) { +                            $errors[] = $data; +                            $last = 'error'; +                        } else if (preg_match('/^.*warning:.+$/i', $msg)) { +                            $warnings[] = $data; +                            $last = 'warning'; +                        } +                    } +                } + +                if($this->showWarnings && $warningCount > 0) +                { +                    $this->log($file . ': ' . $warningCount . ' warnings detected', Project::MSG_WARN); +                    foreach ($warnings as $warning) { +                        $this->log('- line ' . $warning['line'] . (isset($warning['column']) ? ' column ' . $warning['column'] : '') . ': ' . $warning['message'], Project::MSG_WARN); +                    } +                } + +                if($errorCount > 0) +                { +                    $this->log($file . ': ' . $errorCount . ' errors detected', Project::MSG_ERR); +                    if (!isset($this->badFiles[$file])) { +                        $this->badFiles[$file] = array(); +                    } +                         +                    foreach ($errors as $error) { +                        $message = 'line ' . $error['line'] . (isset($error['column']) ? ' column ' . $error['column'] : '') . ': ' . $error['message']; +                        $this->log('- ' . $message, Project::MSG_ERR); +                        array_push($this->badFiles[$file], $message); +                    } +                    $this->hasErrors = true; +                } else if (!$this->showWarnings || $warningCount == 0) { +                    $this->log($file . ': No syntax errors detected', Project::MSG_VERBOSE); + +                    if ($this->cache) +                    { +                        $this->cache->put($file, filemtime($file)); +                    } +                } +            } else { +                throw new BuildException('Permission denied: '.$file); +            } +        } else { +            throw new BuildException('File not found: '.$file); +        } +    } +} + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/MailTask.php b/buildscripts/phing/classes/phing/tasks/ext/MailTask.php index 16d29fb8..0fff88cc 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/MailTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/MailTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: MailTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 901fb0efa435ae78d249a50ed0e0f6e5d31e0d32 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,56 +22,138 @@  include_once 'phing/Task.php';  /** - *  Send a message by mail()  + * Send an e-mail message   * - *  <mail to="user@example.org" subject="build complete">The build process is a success...</mail>  + * <mail tolist="user@example.org" subject="build complete">The build process is a success...</mail>    *  - *  @author   Francois Harvey at SecuriWeb (http://www.securiweb.net) - *  @version  $Revision: 1.1 $ - *  @package  phing.tasks.ext + * @author   Michiel Rook <mrook@php.net> + * @author   Francois Harvey at SecuriWeb (http://www.securiweb.net) + * @version  $Id: 901fb0efa435ae78d249a50ed0e0f6e5d31e0d32 $ + * @package  phing.tasks.ext   */ -class MailTask extends Task { - -    protected $recipient; -       -    protected $subject; +class MailTask extends Task +{ +    protected $tolist = null; +    protected $subject = null; +    protected $msg = null; +    protected $from = null; +     +    protected $filesets = array(); -    protected $msg; +    public function main() +    { +        if (empty($this->from)) { +            throw new BuildException('Missing "from" attribute'); +        } +         +        $this->log('Sending mail to ' . $this->tolist); +         +        if (!empty($this->filesets)) { +            @require_once 'Mail.php'; +            @require_once 'Mail/mime.php'; +             +            if (!class_exists('Mail_mime')) { +                throw new BuildException('Need the PEAR Mail_mime package to send attachments'); +            } +             +            $mime = new Mail_mime(); +            $hdrs = array( +            	'From'    => $this->from, +            	'Subject' => $this->subject +            ); +            $mime->setTXTBody($this->msg); +             +            foreach ($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($this->project); +                $fromDir  = $fs->getDir($this->project); +                $srcFiles = $ds->getIncludedFiles(); -    function main() { -        $this->log('Sending mail to ' . $this->recipient );     -        mail($this->recipient, $this->subject, $this->msg); +                foreach ($srcFiles as $file) { +                    $mime->addAttachment($fromDir . DIRECTORY_SEPARATOR . $file, 'application/octet-stream'); +                } +            } +             +            $body = $mime->get(); +            $hdrs = $mime->headers($hdrs); +             +            $mail = Mail::factory('mail'); +            $mail->send($this->tolist, $hdrs, $body); +        } else { +            mail($this->tolist, $this->subject, $this->msg, "From: {$this->from}\n"); +        }      } -    /** setter for message */ -    function setMsg($msg) { +    /** +     * Setter for message +     */ +    public function setMsg($msg) +    {          $this->setMessage($msg);      } -    /** alias setter */ -    function setMessage($msg) { +    /** +     * Alias setter +     */ +    public function setMessage($msg) +    {          $this->msg = (string) $msg;      } -    /** setter for subject **/ -    function setSubject($subject) { -        $this->subject = (string) $subject;     +    /** +     * Setter for subject +     */ +    public function setSubject($subject) +    { +        $this->subject = (string) $subject;      } -    /** setter for recipient **/ -    function setRecipient($recipient) { -        $this->recipient = (string) $recipient; +    /** +     * Setter for tolist +     */ +    public function setToList($tolist) +    { +        $this->tolist = $tolist; +    } +     +    /** +     * Alias for (deprecated) recipient +     */ +    public function setRecipient($recipient) +    { +        $this->tolist = (string) $recipient;      } -    /** alias for recipient **/ -    function setTo($recipient) { -        $this->recipient = (string) $recipient; +    /** +     * Alias for to +     */ +    public function setTo($to) +    { +        $this->tolist = (string) $to;      } -    /** Supporting the <mail>Message</mail> syntax. */ -    function addText($msg) +    /** +     * Supports the <mail>Message</mail> syntax. +     */ +    public function addText($msg)      {          $this->msg = (string) $msg;      } +     +    /** +     * Sets email address of sender +     */ +    public function setFrom($from) +    { +        $this->from = $from; +    } +     +    /** +     * Adds a fileset +     */ +    public function createFileSet() +    { +        $fileset = new FileSet(); +        $this->filesets[] = $fileset; +        return $fileset; +    }  } - diff --git a/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php b/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php new file mode 100644 index 00000000..b9cfae64 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php @@ -0,0 +1,343 @@ +<?php +/** + * $Id: 7f8f119fe5dd44ca9f374e24d776a1a764260e33 $ + * + * 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/Task.php"; +require_once 'phing/system/io/PhingFile.php'; + +/** + * ManifestTask + *  + * Generates a simple Manifest file with optional checksums. + *  + *  + * Manifest schema: + * ... + * path/to/file     CHECKSUM    [CHECKSUM2]     [CHECKSUM3] + * path/to/secondfile       CHECKSUM    [CHECKSUM2]     [CHECKSUM3] + * ... + *  + * Example usage: + * <manifest checksum="crc32" file="${dir_build}/Manifest"> + *      <fileset refid="files_build" /> + * </manifest> + *  + * <manifest checksum="md5,adler32,sha256" file="${dir_build}/Manifest"> + *      <fileset refid="files_build" /> + * </manifest> + *  + *  + *  + * @author David Persson <davidpersson at qeweurope dot org> + * @package phing.tasks.ext + * @version $Id: 7f8f119fe5dd44ca9f374e24d776a1a764260e33 $ + * @since 2.3.1 + */ +class ManifestTask extends Task +{ +    var $taskname = 'manifest'; +     +    /** +     * Action +     *  +     * "w" for reading in files from fileSet +     * and writing manifest +     *  +     * or +     *  +     * "r" for reading in files from fileSet +     * and checking against manifest +     *  +     * @var string "r" or "w" +     */ +    private $action = 'w'; +     +    /** +     * The target file passed in the buildfile. +     */ +    private $destFile = null; +     +    /** +     * Holds filesets +     * +     * @var array An Array of objects +     */ +    private $filesets = array(); + +    /** +     * Enable/Disable checksuming or/and select algorithm +     * true defaults to md5 +     * false disables checksuming +     * string "md5,sha256,..." enables generation of multiple checksums +     * string "sha256" generates sha256 checksum only +     *  +     * @var mixed +     */ +    private $checksum = false; +     +    /** +     * A string used in hashing method +     * +     * @var string +     */ +    private $salt = ''; +     +    /** +     * Holds some data collected during runtime +     * +     * @var array +     */ +    private $meta = array('totalFileCount' => 0,'totalFileSize' => 0); +     +     +    /** +     * The setter for the attribute "file" +     * This is where the manifest will be written to/read from +     *  +     * @param string Path to readable file +     * @return void +     */ +    public function setFile(PhingFile $file) +    { +        $this->file = $file; +    } + +    /** +     * The setter for the attribute "checksum" +     *  +     * @param mixed $mixed +     * @return void +     */ +    public function setChecksum($mixed) +    { +        if(is_string($mixed)) { +            $data = array(strtolower($mixed)); + +            if(strpos($data[0],',')) { +                $data = explode(',',$mixed); +            } +             +            $this->checksum = $data; +                                     +        } elseif($mixed === true) { +            $this->checksum = array('md5'); +             +        } +    } +     +    /** +     * The setter for the optional attribute "salt" +     * +     * @param string $string +     * @return void +     */ +    public function setSalt($string)  +    { +        $this->salt = $string; +    }     +     +    /** +     * Nested creator, creates a FileSet for this task +     * +     * @access  public +     * @return  object  The created fileset object +     */ +    public function createFileSet() +    { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    /** +     * The init method: Do init steps. +     */ +    public function init() +    { +      // nothing to do here +    } + +    /** +     * Delegate the work +     */ +    public function main() +    { +        $this->validateAttributes(); +         +        if($this->action == 'w') { +            $this->write(); +             +        } elseif($this->action == 'r') { +            $this->read(); +             +        } +    } + +    /** +     * Creates Manifest file +     * Writes to $this->file +     *  +     * @throws BuildException +     */ +    private function write() +    { +        $project = $this->getProject(); +         +        if(!touch($this->file->getPath())) { +            throw new BuildException("Unable to write to ".$this->file->getPath()."."); +        }         + +        $this->log("Writing to " . $this->file->__toString(), Project::MSG_INFO); + +        if(is_array($this->checksum)) { +            $this->log("Using " . implode(', ',$this->checksum)." for checksuming.", Project::MSG_INFO); +        } +         +        foreach($this->filesets as $fs) { +             +            $dir = $fs->getDir($this->project)->getPath(); + +            $ds = $fs->getDirectoryScanner($project); +            $fromDir  = $fs->getDir($project); +            $srcFiles = $ds->getIncludedFiles(); +            $srcDirs  = $ds->getIncludedDirectories();           + +            foreach($ds->getIncludedFiles() as $file_path) { +                $line = $file_path; +                if($this->checksum) { +                    foreach($this->checksum as $algo) { +                        if(!$hash = $this->hashFile($dir.'/'.$file_path,$algo)) { +                            throw new BuildException("Hashing $dir/$file_path with $algo failed!"); +                        } + +                        $line .= "\t".$hash; +                    } +                } +                $line .= "\n"; +                $manifest[] = $line; +                $this->log("Adding file ".$file_path,Project::MSG_VERBOSE); +                $this->meta['totalFileCount'] ++; +                $this->meta['totalFileSize'] += filesize($dir.'/'.$file_path); +            } +             +        } +         +        file_put_contents($this->file,$manifest); +         +        $this->log("Done. Total files: ".$this->meta['totalFileCount'].". Total file size: ".$this->meta['totalFileSize']." bytes.", Project::MSG_INFO);         +    } +     +    /** +     * @todo implement +     */ +    private function read() +    { +        throw new BuildException("Checking against manifest not yet supported."); +    } +     +    /** +     * Wrapper method for hash generation +     * Automatically selects extension +     * Falls back to built-in functions +     *  +     * @link  http://www.php.net/mhash +     * @link  http://www.php.net/hash +     *  +     * @param string $msg The string that should be hashed +     * @param string $algo Algorithm +     * @return mixed String on success, false if $algo is not available  +     */ +    private function hash($msg,$algo)  +    { +        if(extension_loaded('hash')) { +            $algo = strtolower($algo); +             +            if(in_array($algo,hash_algos())) { +                return hash($algo,$this->salt.$msg); +            } +             +        } +         +        if(extension_loaded('mhash')) { +            $algo = strtoupper($algo); +             +            if(defined('MHASH_'.$algo)) { +                return mhash('MHASH_'.$algo,$this->salt.$msg); +             +            } +        } +         +        switch(strtolower($algo)) { +            case 'md5': +                return md5($this->salt.$msg); +            case 'crc32': +                return abs(crc32($this->salt.$msg)); +        } +         +        return false; +    } +     +    /** +     * Hash a files contents  +     * plus it's size an modification time +     * +     * @param string $file +     * @param string $algo +     * @return mixed String on success, false if $algo is not available  +     */ +    private function hashFile($file,$algo) +    { +        if(!file_exists($file)) { +            return false; +        } +         +        $msg = file_get_contents($file).filesize($file).filemtime($file); +         +        return $this->hash($msg,$algo); +    } +     +    /** +     * Validates attributes coming in from XML +     * +     * @access  private +     * @return  void +     * @throws  BuildException +     */ +    protected function validateAttributes() +    { +        if($this->action != 'r' && $this->action != 'w') { +            throw new BuildException("'action' attribute has non valid value. Use 'r' or 'w'"); +        } +                 +        if(empty($this->salt)) { +            $this->log("No salt provided. Specify one with the 'salt' attribute.", Project::MSG_WARN); +        } +         +        if (is_null($this->file) && count($this->filesets) === 0) { +            throw new BuildException("Specify at least sources and destination - a file or a fileset."); +        } + +        if (!is_null($this->file) && $this->file->exists() && $this->file->isDirectory()) { +            throw new BuildException("Destination file cannot be a directory."); +        } +         +    }      +} + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php b/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php index b8664aac..2db5ad69 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: PackageAsPathTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 976dafaf4cafd9ff8f47907a09943ae3963aea79 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ require_once 'phing/Task.php';   * Convert dot-notation packages to relative paths.   *   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.5 $ + * @version   $Id: 976dafaf4cafd9ff8f47907a09943ae3963aea79 $   * @package   phing.tasks.ext   */  class PackageAsPathTask extends Task { diff --git a/buildscripts/phing/classes/phing/tasks/ext/ParallelTask.php b/buildscripts/phing/classes/phing/tasks/ext/ParallelTask.php new file mode 100755 index 00000000..b8da5cb4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ParallelTask.php @@ -0,0 +1,83 @@ +<?php + +/** + * $Id: 860b2b6cdbd797754660fe2c1554e22ab2db4967 $ + * + * 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>. + *  + * @package phing.tasks.ext + */ + +/** + * Uses the DocBlox_Parallel library to run nested Phing tasks concurrently. + *  + * WARNING: this task is highly experimental! + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 860b2b6cdbd797754660fe2c1554e22ab2db4967 $ + * @package phing.tasks.ext + * @see https://github.com/phpdocumentor/Parallel + * @since 2.4.10 + */ +class ParallelTask extends SequentialTask +{ +    /** +     * Maximum number of threads / processes +     * @var int +     */ +    private $threadCount = 2; +     +    /** +     * Sets the maximum number of threads / processes to use +     * @param int $threadCount +     */ +    public function setThreadCount($threadCount) +    { +        $this->threadCount = $threadCount; +    } +     +    public function init() +    { +    } +     +    public function main() +    { +        @include_once 'phing/contrib/DocBlox/Parallel/Manager.php'; +        @include_once 'phing/contrib/DocBlox/Parallel/Worker.php'; +        @include_once 'phing/contrib/DocBlox/Parallel/WorkerPipe.php'; +        if (!class_exists('DocBlox_Parallel_Worker')) { +            throw new BuildException( +                'ParallelTask depends on DocBlox being installed and on include_path.', +                $this->getLocation() +            ); +        } + +        $mgr = new DocBlox_Parallel_Manager(); +        $mgr->setProcessLimit($this->threadCount); +         +        foreach ($this->nestedTasks as $task) { +            $worker = new DocBlox_Parallel_Worker( +                array($task, 'perform'), +                array($task) +            ); +             +            $mgr->addWorker($worker); +        } +         +        $mgr->execute(); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/PatchTask.php b/buildscripts/phing/classes/phing/tasks/ext/PatchTask.php new file mode 100755 index 00000000..162f5fe5 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/PatchTask.php @@ -0,0 +1,301 @@ +<?php +/** + *  Patches a file by applying a 'diff' file to it + * + *  Requires "patch" to be on the execution path. + * + *  Based on Apache Ant PatchTask: + * + *  Licensed to the Apache Software Foundation (ASF) under one or more + *  contributor license agreements.  See the NOTICE file distributed with + *  this work for additional information regarding copyright ownership. + *  The ASF licenses this file to You under the Apache License, Version 2.0 + *  (the "License"); you may not use this file except in compliance with + *  the License.  You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + *  Unless required by applicable law or agreed to in writing, software + *  distributed under the License is distributed on an "AS IS" BASIS, + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *  See the License for the specific language governing permissions and + *  limitations under the License. + */ +  +require_once 'phing/Task.php'; + +/** + * Patches a file by applying a 'diff' file to it + * + * Requires "patch" to be on the execution path. + * + * @package phing.tasks.ext + */ +class PatchTask extends Task +{ +	/** +	 * Base command to be executed (must end with a space character!) +	 * @var string +	 */ +	const CMD = 'patch --batch --silent '; + +	/** +	 * File to be patched +	 * @var string +	 */ +	private $originalFile; + +	/** +	 * Patch file +	 * +	 * @var string +	 */ +	private $patchFile; + +	/** +	 * Value for a "-p" option +	 * @var int +	 */ +	private $strip; + +	/** +	 * Command line arguments for patch binary +	 * @var array +	 */ +	private $cmdArgs = array(); + +	/** +	 * Halt on error return value from patch invocation. +	 * @var bool +	 */ +	private $haltOnFailure = false; + +	/** +	 * The file containing the diff output +	 * +	 * Required. +	 * +	 * @param string $file  File containing the diff output +	 * @return void +	 * @throws BuildException if $file not exists +	 */ +	public function setPatchFile($file) +	{ +		if (!is_file($file)) +		{ +			throw new BuildException(sprintf('Patchfile %s doesn\'t exist', $file)); +		} +		$this->patchFile = $file; +	} + +	/** +	 * The file to patch +	 * +	 * Optional if it can be inferred from the diff file. +	 * +	 * @param string $file  File to patch +	 * @return void +	 */ +	public function setOriginalFile($file) +	{ +		$this->originalFile = $file; +	} + +	/** +	 * The name of a file to send the output to, instead of patching +	 * the file(s) in place +	 * +	 * Optional. +	 * +	 * @param string $file   File to send the output to +	 * @return void +	 */ +	public function setDestFile($file) +	{ +		if ($file !== null) +		{ +			$this->cmdArgs []= "--output=$file"; +		} +	} + +	/** +	 * Flag to create backups +	 * +	 * Optional, default - false +	 * +	 * @param bool $backups  If true create backups +	 * @return void +	 */ +	public function setBackups($backups) +	{ +		if ($backups) +		{ +			$this->cmdArgs []= '--backup'; +		} +	} + +	/** +	 * Flag to ignore whitespace differences; +	 * +	 * Default - false +	 * +	 * @param bool $ignore  If true ignore whitespace differences +	 * @return void +	 */ +	public function setIgnoreWhiteSpace($ignore) +	{ +		if ($ignore) +		{ +			$this->cmdArgs []= '--ignore-whitespace'; +		} +	} + +	/** +	 * Strip the smallest prefix containing <i>num</i> leading slashes +	 * from filenames. +	 * +	 * patch's <i>--strip</i> option. +	 * +	 * @param int $num number of lines to strip +	 * @return void +	 * @throws BuildException if num is < 0, or other errors +	 */ +	public function setStrip($num) +	{ +		if ($num < 0) +		{ +			throw new BuildException('strip has to be >= 0'); +		} + +		$this->strip = $num; +	} + +	/** +	 * Work silently unless an error occurs +	 * +	 * Optional, default - false +	 * @param bool $flag  If true suppress set the -s option on the patch command +	 * @return void +	 */ +	public function setQuiet($flag) +	{ +		if ($flag) +		{ +			$this->cmdArgs []= '--silent'; +		} +	} + +	/** +	 * Assume patch was created with old and new files swapped +	 * +	 * Optional, default - false +	 * +	 * @param bool $flag  If true set the -R option on the patch command +	 * @return void +	 */ +	public function setReverse($flag) +	{ +		if ($flag) +		{ +			$this->cmdArgs []= '--reverse'; +		} +	} + +	/** +	 * The directory to run the patch command in +	 * +	 * Defaults to the project's base directory. +	 * +	 * @param string $directory  Directory to run the patch command in +	 * @return void +	 */ +	public function setDir($directory) +	{ +		$this->cmdArgs []= "--directory=$directory"; +	} + +	/** +	 * Ignore patches that seem to be reversed or already applied +	 * +	 * @param bool $flag  If true set the -N (--forward) option +	 * @return void +	 */ +	public function setForward($flag) +	{ +		if ($flag) +		{ +			$this->cmdArgs []= "--forward"; +		} +	} + +	/** +	 * Set the maximum fuzz factor +	 * +	 * Defaults to 0 +	 * +	 * @param string $value  Value of a fuzz factor +	 * @return void +	 */ +	public function setFuzz($value) +	{ +		$this->cmdArgs []= "--fuzz=$value"; +	} + +	/** +	 * If true, stop the build process if the patch command +	 * exits with an error status. +	 * +	 * The default is "false" +	 * +	 * @param bool $value  "true" if it should halt, otherwise "false" +	 * @return void +	 */ +	public function setHaltOnFailure($value) +	{ +		$this->haltOnFailure = $value; +	} + +	/** +	 * Main task method +	 * +	 * @return void +	 * @throws BuildException when it all goes a bit pear shaped +	 */ +	public function main() +	{ +		if ($this->patchFile == null) +		{ +			throw new BuildException('patchfile argument is required'); +		} + +		// Define patch file +		$this->cmdArgs []= '-i ' . $this->patchFile; +		// Define strip factor +		if ($this->strip != null) +		{ +			$this->cmdArgs []= '--strip=' . $this->strip; +		} +		// Define original file if specified +		if ($this->originalFile != null) +		{ +			$this->cmdArgs []= $this->originalFile; +		} + +		$cmd = self::CMD . implode(' ', $this->cmdArgs); + +		$this->log('Applying patch: ' . $this->patchFile); + +		exec($cmd, $output, $exitCode); + +		foreach ($output as $line) +		{ +			$this->log($line, Project::MSG_VERBOSE); +		} + +		if ($exitCode != 0 && $this->haltOnFailure) +		{ +			throw new BuildException( "Task exited with code $exitCode" ); +		} + +	} +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/PearPackage2Task.php b/buildscripts/phing/classes/phing/tasks/ext/PearPackage2Task.php new file mode 100644 index 00000000..f42231f7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/PearPackage2Task.php @@ -0,0 +1,279 @@ +<?php +/* + *  $Id: 1b20dbb6595bd4c41d1e5f1430900e3bf95de411 $ + * + * 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/ext/PearPackageTask.php'; + +/** + * A task to create a PEAR package.xml version 2.0 file. + * + * This class uses the PEAR_PackageFileManager2 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_PackageFileManager2::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_PackageFileManager2::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> + * <pearpkg2 name="phing" dir="${build.src.dir}"> + *  <fileset dir="src"> + *      <include name="**"/> + *  </fileset> + *  <option name="outputdirectory" value="./build"/> + *  <option name="packagefile" value="package2.xml"/> + *  <option name="packagedirectory" value="./${build.dist.dir}"/> + *  <option name="baseinstalldir" value="${pkg.prefix}"/> + *  <option name="channel" value="my.pear-channel.com"/> + *  <option name="summary" value="${pkg.summary}"/> + *  <option name="description" value="${pkg.description}"/> + *  <option name="apiversion" value="${pkg.version}"/> + *  <option name="apistability" value="beta"/> + *  <option name="releaseversion" value="${pkg.version}"/> + *  <option name="releasestability" value="beta"/> + *  <option name="license" value="none"/> + *  <option name="phpdep" value="5.0.0"/> + *  <option name="pearinstallerdep" value="1.4.6"/> + *  <option name="packagetype" value="php"/> + *  <option name="notes" value="${pkg.relnotes}"/> + *  <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 key="active" value="yes"/> + *   </element> + *  </mapping> + * </pearpkg2> + * </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   Stuart Binge <stuart.binge@complinet.com> + * @author   Hans Lellelid <hans@xmpl.org> + * @package  phing.tasks.ext + * @version  $Id: 1b20dbb6595bd4c41d1e5f1430900e3bf95de411 $ + */ +class PearPackage2Task extends PearPackageTask { + +    public function init() { +        include_once 'PEAR/PackageFileManager2.php'; +        if (!class_exists('PEAR_PackageFileManager2')) { +            throw new BuildException("You must have installed PEAR_PackageFileManager in order to create a PEAR package.xml version 2.0 file."); +        } +    } + +    protected function setVersion2Options() +    { +        $this->pkg->setPackage($this->package); +        $this->pkg->setDate(strftime('%Y-%m-%d')); +        $this->pkg->setTime(strftime('%H:%M:%S'));  + +        $newopts = array(); +        foreach ($this->options as $opt) { +            switch ($opt->getName()) { +                case 'summary': +                    $this->pkg->setSummary($opt->getValue()); +                    break; + +                case 'description': +                    $this->pkg->setDescription($opt->getValue()); +                    break; + +                case 'uri': +                    $this->pkg->setUri($opt->getValue()); +                    break; + +                case 'license': +                    $this->pkg->setLicense($opt->getValue()); +                    break; + +                case 'channel': +                    $this->pkg->setChannel($opt->getValue()); +                    break; + +                case 'apiversion': +                    $this->pkg->setAPIVersion($opt->getValue()); +                    break; + +                case 'releaseversion': +                    $this->pkg->setReleaseVersion($opt->getValue()); +                    break; + +                case 'releasestability': +                    $this->pkg->setReleaseStability($opt->getValue()); +                    break; + +                case 'apistability': +                    $this->pkg->setAPIStability($opt->getValue()); +                    break; + +                case 'notes': +                    $this->pkg->setNotes($opt->getValue()); +                    break; + +                case 'packagetype': +                    $this->pkg->setPackageType($opt->getValue()); +                    break; + +                case 'phpdep': +                    $this->pkg->setPhpDep($opt->getValue()); +                    break; + +                case 'pearinstallerdep': +                    $this->pkg->setPearinstallerDep($opt->getValue()); +                    break; + +                default: +                    $newopts[] = $opt; +                    break; +            } +        } +        $this->options = $newopts; + +        $newmaps = array(); +        foreach ($this->mappings as $map) { +            switch ($map->getName()) { +                case 'deps': +                    $deps = $map->getValue(); +                    foreach ($deps as $dep) { +                        $type = isset($dep['optional']) ? 'optional' : 'required'; +                        $min = isset($dep['min']) ? $dep['min'] : $dep['version']; +                        $max = isset($dep['max']) ? $dep['max'] : null; +                        $rec = isset($dep['recommended']) ? $dep['recommended'] : null; +                        $channel = isset($dep['channel']) ? $dep['channel'] : false; +                        $uri = isset($dep['uri']) ? $dep['uri'] : false; + +                        if (!empty($channel)) { +                            $this->pkg->addPackageDepWithChannel( +                                $type, $dep['name'], $channel, $min, $max, $rec +                            ); +                        } elseif (!empty($uri)) { +                            $this->pkg->addPackageDepWithUri( +                                $type, $dep['name'], $uri +                            ); +                        } +                    }; +                    break; + +                case 'extdeps': +                    $deps = $map->getValue(); +                    foreach ($deps as $dep) { +                        $type = isset($dep['optional']) ? 'optional' : 'required'; +                        $min = isset($dep['min']) ? $dep['min'] : $dep['version']; +                        $max = isset($dep['max']) ? $dep['max'] : $dep['version']; +                        $rec = isset($dep['recommended']) ? $dep['recommended'] : $dep['version']; + +                        $this->pkg->addExtensionDep( +                            $type, $dep['name'], $min, $max, $rec +                        ); +                    }; +                    break; + +                case 'maintainers': +                    $maintainers = $map->getValue(); + +                    foreach ($maintainers as $maintainer) { +                        if (!isset($maintainer['active'])) { +                            $maintainer['active'] = 'yes'; +                        } else { +                            $maintainer['active'] = $maintainer['active'] === false ? 'no' : 'yes'; +                        } +                        $this->pkg->addMaintainer( +                            $maintainer['role'], +                            $maintainer['handle'], +                            $maintainer['name'], +                            $maintainer['email'], +                            $maintainer['active'] +                        ); +                    } +                    break; + +                case 'replacements': +                    $replacements = $map->getValue(); + +                    foreach($replacements as $replacement) {  +                        $this->pkg->addReplacement( +                            $replacement['path'],  +                            $replacement['type'],  +                            $replacement['from'],  +                            $replacement['to'] +                        ); +                    } +                    break; + +				case 'role': +					foreach ($map->getValue() as $role) { +						$this->pkg->addRole($role['extension'], $role['role']); +					} +					break; + +                default: +                    $newmaps[] = $map; +            } +        } +        $this->mappings = $newmaps; +    } + +    /** +     * Main entry point. +     * @return void +     */ +    public function main() +    { +        if ($this->dir === null) { +            throw new BuildException("You must specify the \"dir\" attribute for PEAR package 2 task."); +        } + +        if ($this->package === null) { +            throw new BuildException("You must specify the \"name\" attribute for PEAR package 2 task."); +        } + +        $this->pkg = new PEAR_PackageFileManager2(); + +        $this->setVersion2Options(); +        $this->setOptions(); + +        $this->pkg->addRelease(); +        $this->pkg->generateContents(); +        $e = $this->pkg->writePackageFile(); +        if (PEAR::isError($e)) { +            throw new BuildException("Unable to write package file.", new Exception($e->getMessage())); +        } +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php index 4f8ee3ab..47945998 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PearPackageTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 2078fd5bab3dd6dcea0345a12fce86a24586c765 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -74,15 +74,15 @@ include_once 'phing/types/FileSet.php';   *    * @author   Hans Lellelid <hans@xmpl.org>   * @package  phing.tasks.ext - * @version  $Revision: 1.9 $ + * @version  $Id: 2078fd5bab3dd6dcea0345a12fce86a24586c765 $   */  class PearPackageTask extends MatchingTask {      /** */         -    private $package; +    protected $package;      /** Base directory for reading files. */ -    private $dir; +    protected $dir;      /** Package file */      private $packageFile; @@ -91,15 +91,21 @@ class PearPackageTask extends MatchingTask {      private $filesets = array();      /** @var PEAR_PackageFileManager */ -    private $pkg; +    protected $pkg;      private $preparedOptions = array();      /** @var array PearPkgOption[] */ -    private $options = array(); +    protected $options = array();      /** Nested <mapping> (complex options) types. */ -    private $mappings = array(); +    protected $mappings = array(); +     +    /** +     * Nested <role> elements +     * @var PearPkgRole[] +     */ +    protected $roles = array();      public function init() {          include_once 'PEAR/PackageFileManager.php'; @@ -112,7 +118,7 @@ class PearPackageTask extends MatchingTask {       * Sets PEAR package.xml options, based on class properties.       * @return void       */ -    private function setOptions() { +    protected function setOptions() {          // 1) first prepare/populate options                  $this->populateOptions(); @@ -147,6 +153,11 @@ class PearPackageTask extends MatchingTask {          if (PEAR::isError($e)) {              throw new BuildException("Unable to set options.", new Exception($e->getMessage()));          } +         +        // convert roles +        foreach ($this->roles as $role) { +            $this->pkg->addRole($role->getExtension(), $role->getRole()); +        }      }      /** @@ -180,9 +191,9 @@ class PearPackageTask extends MatchingTask {              $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); +            $this->log("Creating package file: " . $f->__toString(), Project::MSG_INFO);          } else { -            $this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO); +            $this->log("Creating [default] package.xml file in base directory.", Project::MSG_INFO);          }          // converts option objects and mapping objects into  @@ -244,11 +255,12 @@ class PearPackageTask extends MatchingTask {      /**       * Nested creator, creates a FileSet for this task       * -     * @return FileSet The created fileset object +     * @param FileSet $fileset Set of files to add to the package +     * +     * @return void       */ -    function createFileSet() { -        $num = array_push($this->filesets, new FileSet()); -        return $this->filesets[$num-1]; +    public function addFileSet(FileSet $fs) { +        $this->filesets[] = $fs;      }      /** @@ -289,7 +301,7 @@ class PearPackageTask extends MatchingTask {      /**       * Handles nested generic <option> elements.       */ -    function createOption() { +    public function createOption() {          $o = new PearPkgOption();          $this->options[] = $o;          return $o; @@ -298,17 +310,30 @@ class PearPackageTask extends MatchingTask {      /**       * Handles nested generic <option> elements.       */ -    function createMapping() { +    public function createMapping() {          $o = new PearPkgMapping();          $this->mappings[] = $o;          return $o;      } +     +    /** +     * Handles nested <role> elements +     * @return PearPkgRole +     */ +    public function createRole() +    { +        $role = new PearPkgRole(); +        $this->roles[] = $role; +        return $role; +    }  }  /**   * Generic option class is used for non-complex options. + * + * @package  phing.tasks.ext   */  class PearPkgOption { @@ -326,6 +351,8 @@ class PearPkgOption {  /**   * Handles complex options <mapping> elements which are hashes (assoc arrays). + * + * @package  phing.tasks.ext   */  class PearPkgMapping { @@ -369,6 +396,8 @@ class PearPkgMapping {  /**   * Sub-element of <mapping>. + * + * @package  phing.tasks.ext   */  class PearPkgMappingElement { @@ -419,3 +448,57 @@ class PearPkgMappingElement {      }  } + +/** + * Encapsulates file roles + * + * @package phing.tasks.ext + */ +class PearPkgRole +{ +    /** +     * @var string +     */ +    private $extension; +     +    /** +     * @var string +     */ +    private $role; +     +    /** +     * Sets the file extension +     * @param string $extension +     */ +    public function setExtension($extension) +    { +        $this->extension = $extension; +    } +     +    /** +     * Retrieves the file extension +     * @return string +     */ +    public function getExtension() +    { +        return $this->extension; +    } +     +    /** +     * Sets the role +     * @param string $role +     */ +    public function setRole($role) +    { +        $this->role = $role; +    } +     +    /** +     * Retrieves the role +     * @return string +     */ +    public function getRole() +    { +        return $this->role; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/PhpCodeSnifferTask.php b/buildscripts/phing/classes/phing/tasks/ext/PhpCodeSnifferTask.php new file mode 100644 index 00000000..de40ae36 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/PhpCodeSnifferTask.php @@ -0,0 +1,648 @@ +<?php +/* + *  $Id: 8c8f9369e06a3467e34fc8d89f6355df048ece90 $ + * + * 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/Task.php'; + +/** + * A PHP code sniffer task. Checking the style of one or more PHP source files. + * + * @author  Dirk Thomas <dirk.thomas@4wdmedia.de> + * @version $Id: 8c8f9369e06a3467e34fc8d89f6355df048ece90 $ + * @package phing.tasks.ext + */ +class PhpCodeSnifferTask extends Task { + +    protected $file;    // the source file (from xml attribute) +    protected $filesets = array(); // all fileset objects assigned to this task + +    // parameters for php code sniffer +    protected $standard = 'Generic'; +    protected $sniffs = array(); +    protected $showWarnings = true; +    protected $showSources = false; +    protected $reportWidth = 80; +    protected $verbosity = 0; +    protected $tabWidth = 0; +    protected $allowedFileExtensions = array('php'); +    protected $ignorePatterns = false; +    protected $noSubdirectories = false; +    protected $configData = array(); +    protected $encoding = 'iso-8859-1'; + +    // parameters to customize output +    protected $showSniffs = false; +    protected $format = 'default'; +    protected $formatters = array(); + +    /** +     * Holds the type of the doc generator +     * +     * @var string +     */ +    protected $docGenerator = ''; + +    /** +     * Holds the outfile for the documentation +     * +     * @var PhingFile +     */ +    protected $docFile = null; + +    private $haltonerror = false; +    private $haltonwarning = false; +    private $skipversioncheck = false; + +    /** +     * Load the necessary environment for running PHP_CodeSniffer. +     * +     * @return void +     */ +    public function init() +    { +    } + +    /** +     * File to be performed syntax check on +     * @param PhingFile $file +     */ +    public function setFile(PhingFile $file) { +        $this->file = $file; +    } + +    /** +     * Nested creator, creates a FileSet for this task +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    /** +     * Sets the coding standard to test for +     * +     * @param string $standard The coding standard +     * +     * @return void +     */ +    public function setStandard($standard) +    { +        $this->standard = $standard; +    } + +    /** +     * Sets the sniffs which the standard should be restricted to +     * @param string $sniffs +     */ +    public function setSniffs($sniffs) +    { +        $token = ' ,;'; +        $sniff = strtok($sniffs, $token); +        while ($sniff !== false) { +            $this->sniffs[] = $sniff; +            $sniff = strtok($token); +        } +    } + +    /** +     * Sets the type of the doc generator +     * +     * @param string $generator HTML or Text +     * +     * @return void +     */ +    public function setDocGenerator($generator) +    { +        $this->docGenerator = $generator; +    } + +    /** +     * Sets the outfile for the documentation +     * +     * @param PhingFile $file The outfile for the doc +     * +     * @return void +     */ +    public function setDocFile(PhingFile $file) +    { +        $this->docFile = $file; +    } + +    /** +     * Sets the flag if warnings should be shown +     * @param boolean $show +     */ +    public function setShowWarnings($show) +    { +        $this->showWarnings = StringHelper::booleanValue($show); +    } + +    /** +     * Sets the flag if sources should be shown +     * +     * @param boolean $show Whether to show sources or not +     * +     * @return void +     */ +    public function setShowSources($show) +    { +        $this->showSources = StringHelper::booleanValue($show); +    } + +    /** +     * Sets the width of the report +     * +     * @param int $width How wide the screen reports should be. +     * +     * @return void +     */ +    public function setReportWidth($width) +    { +        $this->reportWidth = (int) $width; +    } + +    /** +     * Sets the verbosity level +     * @param int $level +     */ +    public function setVerbosity($level) +    { +        $this->verbosity = (int)$level; +    } + +    /** +     * Sets the tab width to replace tabs with spaces +     * @param int $width +     */ +    public function setTabWidth($width) +    { +        $this->tabWidth = (int)$width; +    } +     +    /** +     * Sets file encoding +     * @param string $encoding +     */ +    public function setEncoding($encoding) +    { +        $this->encoding = $encoding; +    } + +    /** +     * Sets the allowed file extensions when using directories instead of specific files +     * @param array $extensions +     */ +    public function setAllowedFileExtensions($extensions) +    { +        $this->allowedFileExtensions = array(); +        $token = ' ,;'; +        $ext = strtok($extensions, $token); +        while ($ext !== false) { +            $this->allowedFileExtensions[] = $ext; +            $ext = strtok($token); +        } +    } + +    /** +     * Sets the ignore patterns to skip files when using directories instead of specific files +     * @param array $extensions +     */ +    public function setIgnorePatterns($patterns) +    { +        $this->ignorePatterns = array(); +        $token = ' ,;'; +        $pattern = strtok($patterns, $token); +        while ($pattern !== false) { +            $this->ignorePatterns[] = $pattern; +            $pattern = strtok($token); +        } +    } + +    /** +     * Sets the flag if subdirectories should be skipped +     * @param boolean $subdirectories +     */ +    public function setNoSubdirectories($subdirectories) +    { +        $this->noSubdirectories = StringHelper::booleanValue($subdirectories); +    } + +    /** +     * Creates a config parameter for this task +     * +     * @return Parameter The created parameter +     */ +    public function createConfig() { +        $num = array_push($this->configData, new Parameter()); +        return $this->configData[$num-1]; +    } + +    /** +     * Sets the flag if the used sniffs should be listed +     * @param boolean $show +     */ +    public function setShowSniffs($show) +    { +        $this->showSniffs = StringHelper::booleanValue($show); +    } + +    /** +     * Sets the output format +     * @param string $format +     */ +    public function setFormat($format) +    { +        $this->format = $format; +    } + +    /** +     * Create object for nested formatter element. +     * @return CodeSniffer_FormatterElement +     */ +    public function createFormatter () { +        $num = array_push($this->formatters, +        new PhpCodeSnifferTask_FormatterElement()); +        return $this->formatters[$num-1]; +    } + +    /** +     * Sets the haltonerror flag +     * @param boolean $value +     */ +    public function setHaltonerror($value) +    { +        $this->haltonerror = $value; +    } + +    /** +     * Sets the haltonwarning flag +     * @param boolean $value +     */ +    public function setHaltonwarning($value) +    { +        $this->haltonwarning = $value; +    } +     +    /** +     * Sets the skipversioncheck flag +     * @param boolean $value +     */ +    public function setSkipVersionCheck($value) +    { +        $this->skipversioncheck = $value; +    } + +    /** +     * Executes PHP code sniffer against PhingFile or a FileSet +     */ +    public function main() { +        if (!class_exists('PHP_CodeSniffer')) { +            @include_once 'PHP/CodeSniffer.php'; +             +            if (!class_exists('PHP_CodeSniffer')) { +                throw new BuildException("This task requires the PHP_CodeSniffer package installed and available on the include path", $this->getLocation()); +            } +        } + +        /** +         * Determine PHP_CodeSniffer version number +         */ +        if (!$this->skipversioncheck) { +            preg_match('/\d\.\d\.\d/', shell_exec('phpcs --version'), $version); + +            if (version_compare($version[0], '1.2.2') < 0) { +                throw new BuildException( +                    'PhpCodeSnifferTask requires PHP_CodeSniffer version >= 1.2.2', +                    $this->getLocation() +                ); +            } +        } + +        if(!isset($this->file) and count($this->filesets) == 0) { +            throw new BuildException("Missing either a nested fileset or attribute 'file' set"); +        } + +        if (PHP_CodeSniffer::isInstalledStandard($this->standard) === false) { +            // They didn't select a valid coding standard, so help them +            // out by letting them know which standards are installed. +            $installedStandards = PHP_CodeSniffer::getInstalledStandards(); +            $numStandards       = count($installedStandards); +            $errMsg             = ''; + +            if ($numStandards === 0) { +                $errMsg = 'No coding standards are installed.'; +            } else { +                $lastStandard = array_pop($installedStandards); + +                if ($numStandards === 1) { +                    $errMsg = 'The only coding standard installed is ' . $lastStandard; +                } else { +                    $standardList  = implode(', ', $installedStandards); +                    $standardList .= ' and ' . $lastStandard; +                    $errMsg = 'The installed coding standards are ' . $standardList; +                } +            } + +            throw new BuildException( +                'ERROR: the "' . $this->standard . '" coding standard is not installed. ' . $errMsg, +                $this->getLocation() +            ); +        } + +        if (count($this->formatters) == 0) { +          // turn legacy format attribute into formatter +          $fmt = new PhpCodeSnifferTask_FormatterElement(); +          $fmt->setType($this->format); +          $fmt->setUseFile(false); +          $this->formatters[] = $fmt; +        } + +        if (!isset($this->file)) +        { +            $fileList = array(); +            $project = $this->getProject(); +            foreach ($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($project); +                $files = $ds->getIncludedFiles(); +                $dir = $fs->getDir($this->project)->getAbsolutePath(); +                foreach ($files as $file) { +                    $fileList[] = $dir.DIRECTORY_SEPARATOR.$file; +                } +            } +        } + +        $cwd = getcwd(); +        // Save command line arguments because it confuses PHPCS (version 1.3.0) +        $oldArgs = $_SERVER['argv']; +        $_SERVER['argv'] = array(); +        $_SERVER['argc'] = 0; +        $codeSniffer = new PHP_CodeSniffer($this->verbosity, $this->tabWidth, $this->encoding); +        $codeSniffer->setAllowedFileExtensions($this->allowedFileExtensions); +        if (is_array($this->ignorePatterns)) $codeSniffer->setIgnorePatterns($this->ignorePatterns); +        foreach ($this->configData as $configData) { +            $codeSniffer->setConfigData($configData->getName(), $configData->getValue(), true); +        } + +        if ($this->file instanceof PhingFile) { +            $codeSniffer->process($this->file->getPath(), $this->standard, $this->sniffs, $this->noSubdirectories); + +        } else { +            $codeSniffer->process($fileList, $this->standard, $this->sniffs, $this->noSubdirectories); +        } +        // Restore command line arguments +        $_SERVER['argv'] = $oldArgs; +        $_SERVER['argc'] = count($oldArgs); +        chdir($cwd); + +        $report = $this->printErrorReport($codeSniffer); + +        // generate the documentation +        if ($this->docGenerator !== '' && $this->docFile !== null) { +            ob_start(); + +            $codeSniffer->generateDocs($this->standard, $this->sniffs, $this->docGenerator); + +            $output = ob_get_contents(); +            ob_end_clean(); + +            // write to file +            $outputFile = $this->docFile->getPath(); +            $check      = file_put_contents($outputFile, $output); + +            if (is_bool($check) && !$check) { +                throw new BuildException('Error writing doc to ' . $outputFile); +            } +        } elseif ($this->docGenerator !== '' && $this->docFile === null) { +            $codeSniffer->generateDocs($this->standard, $this->sniffs, $this->docGenerator); +        } + +        if ($this->haltonerror && $report['totals']['errors'] > 0) +        { +            throw new BuildException('phpcodesniffer detected ' . $report['totals']['errors']. ' error' . ($report['totals']['errors'] > 1 ? 's' : '')); +        } + +        if ($this->haltonwarning && $report['totals']['warnings'] > 0) +        { +            throw new BuildException('phpcodesniffer detected ' . $report['totals']['warnings'] . ' warning' . ($report['totals']['warnings'] > 1 ? 's' : '')); +        } +    } + +    /** +     * Prints the error report. +     * +     * @param PHP_CodeSniffer $phpcs The PHP_CodeSniffer object containing +     *                               the errors. +     * +     * @return int The number of error and warning messages shown. +     */ +    protected function printErrorReport($phpcs) +    { +        if ($this->showSniffs) { +            $sniffs = $phpcs->getSniffs(); +            $sniffStr = ''; +            foreach ($sniffs as $sniff) { +                $sniffStr .= '- ' . $sniff.PHP_EOL; +            } +            $this->log('The list of used sniffs (#' . count($sniffs) . '): ' . PHP_EOL . $sniffStr, Project::MSG_INFO); +        } + +        $filesViolations = $phpcs->getFilesErrors(); +        $reporting       = new PHP_CodeSniffer_Reporting(); +        $report          = $reporting->prepare($filesViolations, $this->showWarnings); + +        // process output +        foreach ($this->formatters as $fe) { +            switch ($fe->getType()) { +                case 'default': +                    // default format goes to logs, no buffering +                    $this->outputCustomFormat($report); +                    $fe->setUseFile(false); +                    break; + +                default: +                    $reportFile = null; + +                    if ($fe->getUseFile()) { +                        $reportFile = $fe->getOutfile(); +                        ob_start(); +                    } + +                    // Determine number of parameters required to +                    // ensure backwards compatibility +                    $rm = new ReflectionMethod('PHP_CodeSniffer_Reporting', 'printReport'); + +                    if ($rm->getNumberOfParameters() == 5) { +                        $reporting->printReport( +                            $fe->getType(), +                            $filesViolations, +                            $this->showSources, +                            $reportFile, +                            $this->reportWidth +                        ); +                    } else { +                        $reporting->printReport( +                            $fe->getType(), +                            $filesViolations, +                            $this->showWarnings, +                            $this->showSources, +                            $reportFile, +                            $this->reportWidth +                        ); +                    } + +                    // reporting class uses ob_end_flush(), but we don't want +                    // an output if we use a file +                    if ($fe->getUseFile()) { +                        ob_end_clean(); +                    } +                    break; +            } +        } + +        return $report; +    } + +    /** +     * Outputs the results with a custom format +     * +     * @param array $report Packaged list of all errors in each file +     */ +    protected function outputCustomFormat($report) { +        $files = $report['files']; +        foreach ($files as $file => $attributes) { +            $errors = $attributes['errors']; +            $warnings = $attributes['warnings']; +            $messages = $attributes['messages']; +            if ($errors > 0) { +                $this->log($file . ': ' . $errors . ' error' . ($errors > 1 ? 's' : '') . ' detected', Project::MSG_ERR); +                $this->outputCustomFormatMessages($messages, 'ERROR'); +            } else { +                $this->log($file . ': No syntax errors detected', Project::MSG_VERBOSE); +            } +            if ($warnings > 0) { +                $this->log($file . ': ' . $warnings . ' warning' . ($warnings > 1 ? 's' : '') . ' detected', Project::MSG_WARN); +                $this->outputCustomFormatMessages($messages, 'WARNING'); +            } +        } + +        $totalErrors = $report['totals']['errors']; +        $totalWarnings = $report['totals']['warnings']; +        $this->log(count($files) . ' files where checked', Project::MSG_INFO); +        if ($totalErrors > 0) { +            $this->log($totalErrors . ' error' . ($totalErrors > 1 ? 's' : '') . ' detected', Project::MSG_ERR); +        } else { +            $this->log('No syntax errors detected', Project::MSG_INFO); +        } +        if ($totalWarnings > 0) { +            $this->log($totalWarnings . ' warning' . ($totalWarnings > 1 ? 's' : '') . ' detected', Project::MSG_INFO); +        } +    } + +    /** +     * Outputs the messages of a specific type for one file +     * @param array $messages +     * @param string $type +     */ +    protected function outputCustomFormatMessages($messages, $type) { +        foreach ($messages as $line => $messagesPerLine) { +            foreach ($messagesPerLine as $column => $messagesPerColumn) { +                foreach ($messagesPerColumn as $message) { +                    $msgType = $message['type']; +                    if ($type == $msgType) { +                        $logLevel = Project::MSG_INFO; +                        if ($msgType == 'ERROR') { +                            $logLevel = Project::MSG_ERR; +                        } else if ($msgType == 'WARNING') { +                            $logLevel = Project::MSG_WARN; +                        } +                        $text = $message['message']; +                        $string = $msgType . ' in line ' . $line . ' column ' . $column . ': ' . $text; +                        $this->log($string, $logLevel); +                    } +                } +            } +        } +    } + +} //end phpCodeSnifferTask + +/** + * @package phing.tasks.ext + */ +class PhpCodeSnifferTask_FormatterElement extends DataType { + +  /** +   * Type of output to generate +   * @var string +   */ +  protected $type      = ""; + +  /** +   * Output to file? +   * @var bool +   */ +  protected $useFile   = true; + +  /** +   * Output file. +   * @var string +   */ +  protected $outfile   = ""; + +  /** +   * Validate config. +   */ +  public function parsingComplete () { +        if(empty($this->type)) { +            throw new BuildException("Format missing required 'type' attribute."); +    } +    if ($useFile && empty($this->outfile)) { +      throw new BuildException("Format requires 'outfile' attribute when 'useFile' is true."); +    } + +  } + +  public function setType ($type)  { +    $this->type = $type; +  } + +  public function getType () { +    return $this->type; +  } + +  public function setUseFile ($useFile) { +    $this->useFile = $useFile; +  } + +  public function getUseFile () { +    return $this->useFile; +  } + +  public function setOutfile ($outfile) { +    $this->outfile = $outfile; +  } + +  public function getOutfile () { +    return $this->outfile; +  } + +} //end FormatterElement diff --git a/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php index 2fd89fc3..63ec1812 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php @@ -1,82 +1,278 @@  <?php +/* + *  $Id: 524bae55e1007bc9778c232dd7b437964a66c5a4 $ + * + * 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/Task.php'; +require_once 'phing/util/DataStore.php'; +require_once 'phing/system/io/FileWriter.php';  /**   * A PHP lint task. Checking syntax of one or more PHP source file.   *   * @author   Knut Urdalen <knut.urdalen@telio.no> + * @author   Stefan Priebsch <stefan.priebsch@e-novative.de> + * @version  $Id: 524bae55e1007bc9778c232dd7b437964a66c5a4 $   * @package  phing.tasks.ext   */  class PhpLintTask extends Task { -  protected $file;  // the source file (from xml attribute) -  protected $filesets = array(); // all fileset objects assigned to this task +    protected $file;    // the source file (from xml attribute) +    protected $filesets = array(); // all fileset objects assigned to this task -  /** -   * File to be performed syntax check on -   * @param PhingFile $file -   */ -  public function setFile(PhingFile $file) { -    $this->file = $file; -  } -   -  /** -   * 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]; -  } +    protected $errorProperty; +    protected $haltOnFailure = false; +    protected $hasErrors = false; +    protected $badFiles = array(); +    protected $interpreter = ''; // php interpreter to use for linting +     +    protected $logLevel = Project::MSG_VERBOSE; +     +    protected $cache = null; +     +    protected $tofile = null; +     +    protected $deprecatedAsError = false; -  /** -   * Execute lint check against PhingFile or a FileSet -   */ -  public function main() { -    if(!isset($this->file) and count($this->filesets) == 0) { -      throw new BuildException("Missing either a nested fileset or attribute 'file' set"); +    /** +     * Initialize the interpreter with the Phing property +     */ +    public function __construct() { +        $this->setInterpreter(Phing::getProperty('php.interpreter')); +    } + +    /** +     * Override default php interpreter +     * @todo    Do some sort of checking if the path is correct but would  +     *          require traversing the systems executeable path too +     * @param   string  $sPhp +     */ +    public function setInterpreter($sPhp) { +        $this->Interpreter = $sPhp; +    } + +    /** +     * The haltonfailure property +     * @param boolean $aValue +     */ +    public function setHaltOnFailure($aValue) { +        $this->haltOnFailure = $aValue; +    } + +    /** +     * File to be performed syntax check on +     * @param PhingFile $file +     */ +    public function setFile(PhingFile $file) { +        $this->file = $file; +    } + +    /** +     * Set an property name in which to put any errors. +     * @param string $propname  +     */ +    public function setErrorproperty($propname) +    { +        $this->errorProperty = $propname; +    } +     +    /** +     * Whether to store last-modified times in cache +     * +     * @param PhingFile $file +     */ +    public function setCacheFile(PhingFile $file) +    { +        $this->cache = new DataStore($file);      } -    if($this->file instanceof PhingFile) { -      $this->lint($this->file->getPath()); -    } else { // process filesets -      $project = $this->getProject(); -      foreach($this->filesets as $fs) { -	$ds = $fs->getDirectoryScanner($project); -	$files = $ds->getIncludedFiles(); -	$dir = $fs->getDir($this->project)->getPath(); -	foreach($files as $file) { -	  $this->lint($dir.DIRECTORY_SEPARATOR.$file); -	} -      } +    /** +     * File to save error messages to +     * +     * @param PhingFile $file +     */ +    public function setToFile(PhingFile $tofile) +    { +        $this->tofile = $tofile;      } -  } -  /** -   * Performs the actual syntax check -   * -   * @param string $file -   * @return void -   */ -  protected function lint($file) { -    $command = 'php -l '; -    if(file_exists($file)) { -      if(is_readable($file)) { -	$message = array(); -	exec($command.$file, $message); -	if(!preg_match('/^No syntax errors detected/', $message[0])) { -	  $this->log($message[1], PROJECT_MSG_ERR); -	} else { -	  $this->log($file.': No syntax errors detected', PROJECT_MSG_INFO); -	} -      } else { -	throw new BuildException('Permission denied: '.$file); -      } -    } else { -      throw new BuildException('File not found: '.$file); +    /** +     * Nested creator, creates a FileSet for this task +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } +     +    /** +     * Set level of log messages generated (default = info) +     * @param string $level +     */ +    public function setLevel($level) +    { +        switch ($level) +        { +            case "error": $this->logLevel = Project::MSG_ERR; break; +            case "warning": $this->logLevel = Project::MSG_WARN; break; +            case "info": $this->logLevel = Project::MSG_INFO; break; +            case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; +            case "debug": $this->logLevel = Project::MSG_DEBUG; break; +        } +    } +     +    /** +     * Sets whether to treat deprecated warnings (introduced in PHP 5.3) as errors +     * @param boolean $deprecatedAsError +     */ +    public function setDeprecatedAsError($deprecatedAsError) +    { +        $this->deprecatedAsError = $deprecatedAsError; +    } + +    /** +     * Execute lint check against PhingFile or a FileSet +     */ +    public function main() { +        if(!isset($this->file) and count($this->filesets) == 0) { +            throw new BuildException("Missing either a nested fileset or attribute 'file' set"); +        } + +        if($this->file instanceof PhingFile) { +            $this->lint($this->file->getPath()); +        } else { // process filesets +            $project = $this->getProject(); +            foreach($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($project); +                $files = $ds->getIncludedFiles(); +                $dir = $fs->getDir($this->project)->getPath(); +                foreach($files as $file) { +                    $this->lint($dir.DIRECTORY_SEPARATOR.$file); +                } +            } +        } +                 +        // write list of 'bad files' to file (if specified) +        if ($this->tofile) { +            $writer = new FileWriter($this->tofile); +             +            foreach ($this->badFiles as $file => $messages) { +            	foreach ($messages as $msg) { +                	$writer->write($file . "=" . $msg . PHP_EOL); +            	} +            } +             +            $writer->close(); +        } + +        $message = ''; +        foreach ($this->badFiles as $file => $messages) { +            foreach ($messages as $msg) { +                $message .= $file . "=" . $msg . PHP_EOL; +            } +        } +         +        // save list of 'bad files' with errors to property errorproperty (if specified) +        if ($this->errorProperty) { +            $this->project->setProperty($this->errorProperty, $message); +        } +         +        if (!empty($this->cache)) { +            $this->cache->commit(); +        } +         +        if ($this->haltOnFailure && $this->hasErrors) { +            throw new BuildException('Syntax error(s) in PHP files: ' . $message); +        } +    } + +    /** +     * Performs the actual syntax check +     * +     * @param string $file +     * @return void +     */ +    protected function lint($file) { +        $command = $this->Interpreter == '' +            ? 'php' +            : $this->Interpreter; +        $command .= ' -n -l '; +         +        if ($this->deprecatedAsError) { +            $command .= '-d error_reporting=32767 '; +        } +         +        if(file_exists($file)) { +            if(is_readable($file)) { +                if ($this->cache) +                { +                    $lastmtime = $this->cache->get($file); +                     +                    if ($lastmtime >= filemtime($file)) +                    { +                        $this->log("Not linting '" . $file . "' due to cache", Project::MSG_DEBUG); +                        return false; +                    } +                } +                 +                $messages = array(); +                $errorCount = 0; + +                exec($command.'"'.$file.'" 2>&1', $messages); +                 +                for ($i = 0; $i < count($messages) - 1; $i++) { +                    $message = $messages[$i]; +                    if (trim($message) == '') { +                        continue; +                    } +                     +                    if ((!preg_match('/^(.*)Deprecated:/', $message) || $this->deprecatedAsError) && !preg_match('/^No syntax errors detected/', $message)) { +                        $this->log($message, Project::MSG_ERR); +                         +                        if (!isset($this->badFiles[$file])) { +                            $this->badFiles[$file] = array(); +                        } +                         +                        array_push($this->badFiles[$file], $message); +                         +                        $this->hasErrors = true; +                        $errorCount++; +                    } +                } + +                if (!$errorCount) { +                    $this->log($file.': No syntax errors detected', $this->logLevel); +                     +                    if ($this->cache) +                    { +                        $this->cache->put($file, filemtime($file)); +                    } +                } +            } else { +                throw new BuildException('Permission denied: '.$file); +            } +        } else { +            throw new BuildException('File not found: '.$file); +        }      } -  }  } -?>
\ No newline at end of file + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/ReplaceRegexpTask.php b/buildscripts/phing/classes/phing/tasks/ext/ReplaceRegexpTask.php new file mode 100644 index 00000000..dc4ccbf7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ReplaceRegexpTask.php @@ -0,0 +1,204 @@ +<?php +/* + *  $Id: f81043cad2c0ffe0a2571a0a8dc16a98651eac51 $   + *  + * 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/Task.php'; + +/** + * ReplaceRegExp is a directory based task for replacing the occurrence of a given regular expression with a substitution  + * pattern in a selected file or set of files. + *  + * <code> + * <replaceregexp file="${src}/build.properties" + *                        match="OldProperty=(.*)" + *                        replace="NewProperty=\1" + *                        byline="true"/> + * </code> + *  + * @author    Jonathan Bond-Caron <jbondc@openmv.com> + * @version   $Id: f81043cad2c0ffe0a2571a0a8dc16a98651eac51 $ + * @package   phing.tasks.system + * @link      http://ant.apache.org/manual/OptionalTasks/replaceregexp.html + */ +class ReplaceRegexpTask extends Task { +     +    /** Single file to process. */ +    private $file; +     +    /** Any filesets that should be processed. */ +    private $filesets = array(); +     +    /** +     * Regular expression +     *  +     * @var RegularExpression +     */ +    private $_regexp; +         +    /** +     * File to apply regexp on +     *  +     * @param string $path +     */ +    public function setFile(PhingFile $path) +    { +        $this->file = $path; +    } +     +    /** +     * Sets the regexp match pattern +     *  +     * @param string $regexp  +     */ +    public function setMatch( $regexp ) +    { +        $this->_regexp->setPattern( $regexp ); +    } + +    /** +     * @see setMatch() +     */ +    public function setPattern( $regexp ) +    { +        $this->setMatch( $regexp ); +    } + +    /** +     * Sets the replacement string +     *  +     * @param string $string +     */ +    public function setReplace( $string ) +    { +        $this->_regexp->setReplace( $string ); +    } + +    /** +     * Sets the regexp flags +     *  +     * @param string $flags +     */ +    public function setFlags( $flags ) +    { +        // TODO... $this->_regexp->setFlags( $flags );  +    } + +    /** +     * Match only per line +     *  +     * @param bool $yesNo +     */ +    public function setByline( $yesNo ) +    { +        // TODO... $this->_regexp->  +    } +     +    /** Nested creator, adds a set of files (nested fileset attribute). */ +    public function createFileSet() +    { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    public function init() +    { +        $this->_regexp = new RegularExpression; +    } + +    public function main() +    { +        if ($this->file === null && empty($this->filesets)) { +            throw new BuildException("You must specify a file or fileset(s) for the <ReplaceRegexp> task."); +        } +         +        // compile a list of all files to modify, both file attrib and fileset elements +        // can be used. +        $files = array(); +         +        if ($this->file !== null) { +            $files[] = $this->file; +        } +         +        if (!empty($this->filesets)) { +            $filenames = array(); +            foreach($this->filesets as $fs) { +                try { +                    $ds = $fs->getDirectoryScanner($this->project); +                    $filenames = $ds->getIncludedFiles(); // get included filenames +                    $dir = $fs->getDir($this->project); +                    foreach ($filenames as $fname) { +                        $files[] = new PhingFile($dir, $fname); +                    } +                } catch (BuildException $be) { +                    $this->log($be->getMessage(), Project::MSG_WARN); +                } +            }                         +        } +         +        $this->log("Applying Regexp processing to " . count($files) . " files."); + +        // These "slots" allow filters to retrieve information about the currently-being-process files       +        $slot = $this->getRegisterSlot("currentFile"); +        $basenameSlot = $this->getRegisterSlot("currentFile.basename");  + +        $filter = new FilterChain($this->project); + +        $r = new ReplaceRegexp; +        $r->setRegexps(array($this->_regexp)); + +        $filter->addReplaceRegexp($r); +        $filters = array($filter); + +        foreach($files as $file) { +            // set the register slots +             +            $slot->setValue($file->getPath()); +            $basenameSlot->setValue($file->getName()); +             +            // 1) read contents of file, pulling through any filters +            $in = null; +            try {                 +                $contents = ""; +                $in = FileUtils::getChainedReader(new FileReader($file), $filters, $this->project); +                while(-1 !== ($buffer = $in->read())) { +                    $contents .= $buffer; +                } +                $in->close(); +            } catch (Exception $e) { +                if ($in) $in->close(); +                $this->log("Error reading file: " . $e->getMessage(), Project::MSG_WARN); +            } +             +            try { +                // now create a FileWriter w/ the same file, and write to the file +                $out = new FileWriter($file); +                $out->write($contents); +                $out->close(); +                $this->log("Applying regexp processing to " . $file->getPath(), Project::MSG_VERBOSE); +            } catch (Exception $e) { +                if ($out) $out->close(); +                $this->log("Error writing file back: " . $e->getMessage(), Project::MSG_WARN); +            } +             +        } +                                 +    }    + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/ScpTask.php b/buildscripts/phing/classes/phing/tasks/ext/ScpTask.php new file mode 100644 index 00000000..f6ceadd1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ScpTask.php @@ -0,0 +1,380 @@ +<?php +/* + *  $Id: 300efdab5b721c6312491450bc2ba93ffc8124b4 $ + * + * 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/Task.php'; + +/** + * Copy files to and from a remote host using scp. + * + * @author    Michiel Rook <mrook@php.net> + * @author    Johan Van den Brande <johan@vandenbrande.com> + * @version   $Id: 300efdab5b721c6312491450bc2ba93ffc8124b4 $ + * @package   phing.tasks.ext + */ + +class ScpTask extends Task +{ +    protected $file = ""; +    protected $filesets = array(); // all fileset objects assigned to this task +    protected $todir = ""; +    protected $mode = null; + +    protected $host = ""; +    protected $port = 22; +    protected $username = ""; +    protected $password = ""; +    protected $autocreate = true; +    protected $fetch = false; +    protected $localEndpoint = ""; +    protected $remoteEndpoint = ""; + +    protected $pubkeyfile = ''; +    protected $privkeyfile = ''; +    protected $privkeyfilepassphrase = ''; +        +    protected $connection = null; +    protected $sftp = null; +     +    protected $count = 0; +     +    protected $logLevel = Project::MSG_VERBOSE; + +    /** +     * Sets the remote host +     */ +    public function setHost($h) +    { +        $this->host = $h; +    } + +    /** +     * Returns the remote host +     */ +    public function getHost() +    { +        return $this->host; +    } + +    /** +     * Sets the remote host port +     */ +    public function setPort($p) +    { +        $this->port = $p; +    } + +    /** +     * Returns the remote host port +     */ +    public function getPort() +    { +        return $this->port; +    } + +    /** +     * Sets the mode value +     */ +    public function setMode($value) +    { +        $this->mode = $value; +    } + +    /** +     * Returns the mode value +     */ +    public function getMode() +    { +        return $this->mode; +    } + +    /** +     * Sets the username of the user to scp +     */ +    public function setUsername($username) +    { +        $this->username = $username; +    } + +    /** +     * Returns the username +     */ +    public function getUsername() +    { +        return $this->username; +    } + +    /** +     * Sets the password of the user to scp +     */ +    public function setPassword($password) +    { +        $this->password = $password; +    } + +    /** +     * Returns the password +     */ +    public function getPassword() +    { +        return $this->password; +    } +     +    /** +     * Sets the public key file of the user to scp +     */ +    public function setPubkeyfile($pubkeyfile) +    { +        $this->pubkeyfile = $pubkeyfile; +    } + +    /** +     * Returns the pubkeyfile +     */ +    public function getPubkeyfile() +    { +        return $this->pubkeyfile; +    } +     +    /** +     * Sets the private key file of the user to scp +     */ +    public function setPrivkeyfile($privkeyfile) +    { +        $this->privkeyfile = $privkeyfile; +    } + +    /** +     * Returns the private keyfile +     */ +    public function getPrivkeyfile() +    { +        return $this->privkeyfile; +    } +     +    /** +     * Sets the private key file passphrase of the user to scp +     */ +    public function setPrivkeyfilepassphrase($privkeyfilepassphrase) +    { +        $this->privkeyfilepassphrase = $privkeyfilepassphrase; +    } + +    /** +     * Returns the private keyfile passphrase +     */ +    public function getPrivkeyfilepassphrase($privkeyfilepassphrase) +    { +        return $this->privkeyfilepassphrase; +    } +     +    /** +     * Sets whether to autocreate remote directories +     */ +    public function setAutocreate($autocreate) +    { +        $this->autocreate = (bool) $autocreate; +    } +     +    /** +     * Returns whether to autocreate remote directories +     */ +    public function getAutocreate() +    { +        return $this->autocreate; +    } +     +    /** +     * Set destination directory +     */ +    public function setTodir($todir) +    { +        $this->todir = $todir; +    } + +    /** +     * Returns the destination directory +     */ +    public function getTodir() +    { +        return $this->todir; +    } + +    /** +     * Sets local filename +     */ +    public function setFile($file) +    { +        $this->file = $file; +    } + +    /** +     * Returns local filename +     */ +    public function getFile() +    { +        return $this->file; +    } +     +    /** +     * Sets whether to send (default) or fetch files +     */ +    public function setFetch($fetch) +    { +        $this->fetch = (bool) $fetch; +    } +     +    /** +     * Returns whether to send (default) or fetch files +     */ +    public function getFetch() +    { +        return $this->fetch; +    } +     +    /** +     * Nested creator, creates a FileSet for this task +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } +     +    /** +     * Set level of log messages generated (default = verbose) +     * @param string $level +     */ +    public function setLevel($level) +    { +        switch ($level) +        { +            case "error": $this->logLevel = Project::MSG_ERR; break; +            case "warning": $this->logLevel = Project::MSG_WARN; break; +            case "info": $this->logLevel = Project::MSG_INFO; break; +            case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; +            case "debug": $this->logLevel = Project::MSG_DEBUG; break; +        } +    } + +    public function init() +    { +    } + +    public function main() +    { +        if (!function_exists('ssh2_connect')) {  +            throw new BuildException("To use ScpTask, you need to install the PHP SSH2 extension."); +        } +         +        if ($this->file == "" && empty($this->filesets)) { +            throw new BuildException("Missing either a nested fileset or attribute 'file'"); +        } +         +        if ($this->host == "" || $this->username == "") { +            throw new BuildException("Attribute 'host' and 'username' must be set"); +        } + +        $this->connection = ssh2_connect($this->host, $this->port); +        if (is_null($this->connection)) { +            throw new BuildException("Could not establish connection to " . $this->host . ":" . $this->port . "!"); +        } + +        $could_auth = null; +        if ( $this->pubkeyfile ) { +            $could_auth = ssh2_auth_pubkey_file($this->connection, $this->username, $this->pubkeyfile, $this->privkeyfile, $this->privkeyfilepassphrase); +        } else { +            $could_auth = ssh2_auth_password($this->connection, $this->username, $this->password); +        } +        if (!$could_auth) { +            throw new BuildException("Could not authenticate connection!"); +        } +         +        // prepare sftp resource +        if ($this->autocreate) { +            $this->sftp = ssh2_sftp($this->connection); +        } +         +        if ($this->file != "") { +            $this->copyFile($this->file, basename($this->file)); +        } else { +            if ($this->fetch) { +                throw new BuildException("Unable to use filesets to retrieve files from remote server"); +            } +             +            foreach($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($this->project); +                $files = $ds->getIncludedFiles(); +                $dir = $fs->getDir($this->project)->getPath(); +                foreach($files as $file) { +                    $path = $dir.DIRECTORY_SEPARATOR.$file; +                     +                    // Translate any Windows paths +                    $this->copyFile($path, strtr($file, '\\', '/')); +                } +            } +        } +         +        $this->log("Copied " . $this->counter . " file(s) " . ($this->fetch ? "from" : "to") . " '" . $this->host . "'"); +         +        // explicitly close ssh connection +        @ssh2_exec($this->connection, 'exit'); +    } +     +    protected function copyFile($local, $remote) +    { +        $path = rtrim($this->todir, "/") . "/"; +         +        if ($this->fetch) { +            $localEndpoint = $path . $remote; +            $remoteEndpoint = $local; + +            $this->log('Will fetch ' . $remoteEndpoint . ' to ' . $localEndpoint, $this->logLevel); + +            $ret = @ssh2_scp_recv($this->connection, $remoteEndpoint, $localEndpoint); +             +            if ($ret === false) { +                throw new BuildException("Could not fetch remote file '" . $remoteEndpoint . "'"); +            } +        } else { +            $localEndpoint = $local; +            $remoteEndpoint = $path . $remote; + +            if ($this->autocreate) { +                ssh2_sftp_mkdir($this->sftp, dirname($remoteEndpoint), (is_null($this->mode) ? 0777 : $this->mode), true); +            } +             +            $this->log('Will copy ' . $localEndpoint . ' to ' . $remoteEndpoint, $this->logLevel); +             +            if (!is_null($this->mode)) { +                $ret = @ssh2_scp_send($this->connection, $localEndpoint, $remoteEndpoint, $this->mode); +            } else { +                $ret = @ssh2_scp_send($this->connection, $localEndpoint, $remoteEndpoint); +            } + +            if ($ret === false) { +                throw new BuildException("Could not create remote file '" . $remoteEndpoint . "'"); +            } +        } + +        $this->counter++; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon.php new file mode 100644 index 00000000..6e8fa8e0 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon.php @@ -0,0 +1,120 @@ +<?php + +/* + *  $Id: 81e9d8cbc94bac15a6a32ed0bb23c04d2b0ff439 $ + * + * 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/Task.php"; + +/** + * Abstract Service_Amazon class. + * + * Implements common methods & properties used by all Amazon services + *  + * @extends Task + * @version $ID$ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @abstract + */ +abstract class Service_Amazon extends Task +{ +    /** +	 * Collection of set options +	 * +	 * We set these magically so we can also load then from the environment +	 *  +	 * (default value: array()) +	 *  +	 * @var array +	 * @access protected +	 */ +	protected $_options = array(); +	 +	public function __set($var, $val) +	{ +		$this->_options[$var] = $val; +	} +	 +	/** +	 * Property getter +	 * +	 * If the property hasn't been previously set (through the task call normally), +	 * it will try to load it from the project +	 * +	 * This way, we can define global properties for the "Amazon" service, like key and secret +	 *  +	 * @access public +	 * @param mixed $var +	 * @return void +	 */ +	public function __get($var) +	{ +		if(!isset($this->$var)) { +			if(!($val = $this->getProject()->getProperty('amazon.' . strtolower($var)))) { +				return false; +			} else { +				return $val; +			} +		} +		 +		return $this->_options[$var]; +	} +	 +	public function __isset($var) +	{ +		return array_key_exists($var, $this->_options); +	} + +	public function setKey($key) +	{ +		if(empty($key) || !is_string($key)) { +			throw new BuildException('Key must be a non empty string'); +		} +		 +		$this->key = $key; +	} +	 +	public function getKey() +	{ +		if(!($key = $this->key)) { +			throw new BuildException('Key is not set'); +		} + +		return $key; +	} +	 +	public function setSecret($secret) +	{ +		if(empty($secret) || !is_string($secret)) { +			throw new BuildException('Secret must be a non empty string'); +		} +		 +		$this->secret = $secret; +	} +	 +	public function getSecret() +	{ +		if(!($secret = $this->secret)) { +            throw new BuildException('Secret is not set'); +        } +         +        return $this->secret; +	} +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3.php new file mode 100644 index 00000000..7bed642e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3.php @@ -0,0 +1,188 @@ +<?php + +/* + *  $Id: a205dcffd1f42b70a8101808242d66620e3dabbd $ + * + * 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 dirname(dirname(__FILE__)) . "/Amazon.php"; + +/** + * Abstract Service_Amazon_S3 class. + *  + * Provides common methods and properties to all of the S3 tasks + * + * @extends Service_Amazon + * @version $ID$ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @abstract + */ +abstract class Service_Amazon_S3 extends Service_Amazon +{ +    /** +     * Services_Amazon_S3 client +     *  +     * (default value: null) +     *  +     * @var Services_Amazon_S3 +     * @see Services_Amazon_S3 +     * @access protected +     */ +    protected $_client = null; +     +    /** +     * We only instantiate the client once per task call +     *  +     * @access public +     * @return Services_Amazon_S3 +     */ +    public function getClient() +    { +        require_once "Services/Amazon/S3.php"; + +        if($this->_client === null) { +            $this->_client = Services_Amazon_S3::getAccount($this->getKey(), $this->getSecret()); +        } +         +        return $this->_client; +    } +     +    public function setBucket($bucket) +    { +		if(empty($bucket) || !is_string($bucket)) { +			throw new BuildException('Bucket must be a non-empty string'); +		} + +        $this->bucket = (string) $bucket; +    } + +    public function getBucket() +    { +        if(!($bucket = $this->bucket)) { +            throw new BuildException('Bucket is not set'); +        } +         +        return $this->bucket; +    } + +    /** +	 * Returns an instance of Services_Amazon_S3_Resource_Object +	 *  +	 * @access public +	 * @param mixed $object +	 * @return Services_Amazon_S3_Resource_Object +	 */ +	public function getObjectInstance($object) +	{ +		return $this->getBucketInstance()->getObject($object); +	} +     +    /** +     * Check if the object already exists in the current bucket +     *  +     * @access public +     * @param mixed $object +     * @return bool +     */ +    public function isObjectAvailable($object) +    { +		return (bool) $this->getObjectInstance($object)->load(Services_Amazon_S3_Resource_Object::LOAD_METADATA_ONLY); +    } + +    /** +	 * Returns an instance of Services_Amazon_S3_Resource_Bucket +	 *  +	 * @access public +	 * @return Services_Amazon_S3_Resource_Bucket +	 */ +	public function getBucketInstance() +	{ +		return $this->getClient()->getBucket($this->getBucket()); +	} + +    /** +	 * Check if the current bucket is available +	 *  +	 * @access public +	 * @return bool +	 */ +	public function isBucketAvailable() +	{ +		return (bool) $this->getBucketInstance($this->getBucket())->load(); +	} +     +    /** +     * Get the contents of an object (by it's name) +     *  +     * @access public +     * @param string $object +     * @return mixed +     */ +    public function getObjectContents($object) +    { +		if(!$this->isBucketAvailable($this->getBucket())) { +			throw new BuildException('Bucket doesn\'t exist or wrong permissions'); +		} +		 +		$bucket = $this->getClient()->getBucket($this->getBucket()); +        if(!$this->isObjectAvailable($object)) { +            throw new BuildException('Object not available: ' . $object); +        } +         +        $object = $this->getObjectInstance($object); +		$object->load(); +		return $object->data; +    } + +    /** +	 * Create a bucket +	 *  +	 * @access public +	 * @return void +	 */ +	public function createBucket() +	{ +		$bucket = $this->getBucketInstance(); +		$bucket->name = $this->getBucket(); +		$bucket->save(); +		 +		return $this->isBucketAvailable(); +	} +     +    /** +     * Main entry point, doesn't do anything +     *  +     * @access public +     * @final +     * @return void +     */ +    final public function main() +    {        +        $this->execute(); +    } +     +    /** +     * Entry point to children tasks +     *  +     * @access public +     * @abstract +     * @return void +     */ +    abstract public function execute(); +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php new file mode 100644 index 00000000..37b4e817 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php @@ -0,0 +1,108 @@ +<?php + +/* + *  $Id: 214ed107be71d8dbc0f68ffc90bfd8b11a76b36d $ + * + * 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 dirname(dirname(__FILE__)) . '/S3.php'; + +/** + * Downloads an object off S3 + *  + * @version $Id: 214ed107be71d8dbc0f68ffc90bfd8b11a76b36d $ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @extends Service_Amazon_S3 + */ +class S3GetTask extends Service_Amazon_S3 +{ +    /** +     * This is where we'll store the object +     *  +     * (default value: null) +     *  +     * @var mixed +     * @access protected +     */ +    protected $_target = null; +     +    /** +     * The S3 object we're working with +     *  +     * (default value: null) +     *  +     * @var mixed +     * @access protected +     */ +    protected $_object = null; +     +	public function setObject($object) +	{ +		if(empty($object) || !is_string($object)) { +			throw new BuildException('Object must be a non-empty string'); +		} +		 +		$this->_object = $object; +	} +	 +	public function getObject() +	{ +		if($this->_object === null) { +			throw new BuildException('Object is not set'); +		} +		 +		return $this->_object; +	} + +    public function setTarget($target) +    { +        if(!is_file($target) && !is_dir($target) && !is_link($target)) { +            if(!is_writable(dirname($target))) { +                throw new BuildException('Target is not writable: ' . $target); +            } +        } else { +            if(!is_writable($target)) { +                throw new BuildException('Target is not writable: ' . $target); +            } +        } + +        $this->_target = $target; +    } +     +    public function getTarget() +    { +        if($this->_target === null) { +            throw new BuildException('Target is not set'); +        } +         +        return $this->_target; +    } +     +    public function execute() +    { +		$target = $this->getTarget(); +		 +        // Use the object name as the target if the current target is a directory +        if(is_dir($target)) { +            $target = rtrim($target, '/') . '/' . $this->getObject(); +        } + +		file_put_contents($target, $this->getObjectContents($this->getObject())); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php new file mode 100644 index 00000000..dbb18b56 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php @@ -0,0 +1,243 @@ +<?php +/* + *  $Id: 84b1d6039427591cbf43dbe1a82691063ae4238a $ + * + * 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 dirname(dirname(__FILE__)) . '/S3.php'; + +/** + * Stores an object on S3 + *  + * @version $Id: 84b1d6039427591cbf43dbe1a82691063ae4238a $ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @extends Service_Amazon_S3 + */ +class S3PutTask extends Service_Amazon_S3 +{ +    /** +     * File we're trying to upload +     * +     * (default value: null) +     *  +     * @var string +     * @access protected +     */ +    protected $_source = null; + +    /** +	 * Content we're trying to upload +	 * +	 * The user can specify either a file to upload or just a bit of content +	 * +	 * (default value: null) +	 *  +	 * @var mixed +	 * @access protected +	 */ +	protected $_content = null; +	 +	/** +     * Collection of filesets +     * Used for uploading multiple files +     *  +     * (default value: array()) +     *  +     * @var array +     * @access protected +     */ +    protected $_filesets = array(); +	 +	/** +	 * Whether to try to create buckets or not +	 *  +	 * (default value: false) +	 *  +	 * @var bool +	 * @access protected +	 */ +	protected $_createBuckets = false; +     +    public function setSource($source) +    { +        if(!is_readable($source)) { +            throw new BuildException('Source is not readable: ' . $source); +        } + +        $this->_source = $source; +    } +     +    public function getSource() +    { +        if($this->_source === null) { +            throw new BuildException('Source is not set'); +        } +         +        return $this->_source; +    } + +	public function setContent($content) +	{ +		if(empty($content) || !is_string($content)) { +			throw new BuildException('Content must be a non-empty string'); +		} +		 +		$this->_content = $content; +	} +	 +	public function getContent() +	{ +		if($this->_content === null) { +			throw new BuildException('Content is not set'); +		} +		 +		return $this->_content; +	} + +	public function setObject($object) +	{ +		if(empty($object) || !is_string($object)) { +			throw new BuildException('Object must be a non-empty string'); +		} +		 +		$this->_object = $object; +	} +	 +	public function getObject() +	{ +		if($this->_object === null) { +			throw new BuildException('Object is not set'); +		} +		 +		return $this->_object; +	} + +	public function setCreateBuckets($createBuckets) +    { +        $this->_createBuckets = (bool) $createBuckets; +    } + +	public function getCreateBuckets() +    { +        return (bool) $this->_createBuckets; +    } + +	/** +     * creator for _filesets +     *  +     * @access public +     * @return FileSet +     */ +    public function createFileset() +    { +        $num = array_push($this->_filesets, new FileSet()); +        return $this->_filesets[$num-1]; +    } + +	/** +     * getter for _filesets +     *  +     * @access public +     * @return array +     */ +    public function getFilesets() +    { +        return $this->_filesets; +    } + +    /** +	 * Determines what we're going to store in the object +	 *  +	 * If _content has been set, this will get stored, +	 * otherwise, we read from _source +	 * +	 * @access public +	 * @return string +	 */ +	public function getObjectData() +	{ +		try { +			$content = $this->getContent(); +		} catch(BuildException $e) { +			$source = $this->getSource(); +			 +			if(!is_file($source)) { +                throw new BuildException('Currently only files can be used as source'); +			} +			 +			$content = file_get_contents($source); +		} +		 +		return $content; +	} +     +    /** +     * Store the object on S3 +     *  +     * @access public +     * @return void +     */ +    public function execute() +    { +		if(!$this->isBucketAvailable()) { +			if(!$this->getCreateBuckets()) { +				throw new BuildException('Bucket doesn\'t exist and createBuckets not specified'); +			} else{ +				if(!$this->createBucket()) { +					throw new BuildException('Bucket cannot be created'); +				} +			} +		} +		 +		// Filesets take precedence +		if(!empty($this->_filesets)) { +			$objects = array(); +			 +			foreach($this->_filesets as $fs) { +	            if(!($fs instanceof FileSet)) { +	                continue; +	            } + +				$ds = $fs->getDirectoryScanner($this->getProject()); +				$objects = array_merge($objects, $ds->getIncludedFiles()); +			} +			 +			$fromDir = $fs->getDir($this->getProject())->getAbsolutePath(); +			 +			foreach($objects as $object) { +				$this->saveObject($object, file_get_contents($fromDir . DIRECTORY_SEPARATOR . $object)); +			} +			 +			return true; +		} +		 +		$this->saveObject($this->getObject(), $this->getObjectData()); +    } + +	protected function saveObject($object, $data) +	{ +		$object = $this->getObjectInstance($object); +		$object->data = $data; +		$object->save(); +		 +		if(!$this->isObjectAvailable($object->key)) { +			throw new BuildException('Upload failed'); +		} +	} +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php b/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php index 97eada3d..69c7b8f8 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: SmartyTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 1fe8b2aa2668db628554e59b3099520c0e1c03e4 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -37,7 +37,7 @@ include_once 'phing/util/StringHelper.php';   * @author    Hans Lellelid <hans@xmpl.org> (SmartyTask)   * @author    Jason van Zyl <jvanzyl@apache.org> (TexenTask)   * @author    Robert Burrell Donkin <robertdonkin@mac.com> - * @version   $Id: SmartyTask.php 59 2006-04-28 14:49:47Z mrook $ + * @version   $Id: 1fe8b2aa2668db628554e59b3099520c0e1c03e4 $   * @package   phing.tasks.ext   */  class SmartyTask extends Task { @@ -233,7 +233,7 @@ class SmartyTask extends Task {      public function setOutputDirectory(PhingFile $outputDirectory) {          try {                          if (!$outputDirectory->exists()) { -                $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE); +                $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),Project::MSG_VERBOSE);                  if (!$outputDirectory->mkdirs()) {                      throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());                  } @@ -494,7 +494,7 @@ class SmartyTask extends Task {          $smartyCompilePath = new PhingFile($this->context->compile_dir);          if (!$smartyCompilePath->exists()) { -            $this->log("Compile directory does not exist, creating: " . $smartyCompilePath->getPath(), PROJECT_MSG_VERBOSE); +            $this->log("Compile directory does not exist, creating: " . $smartyCompilePath->getPath(), Project::MSG_VERBOSE);              if (!$smartyCompilePath->mkdirs()) {                  throw new BuildException("Smarty needs a place to compile templates; specify a 'compilePath' or create ".$this->context->compile_dir);              } @@ -543,7 +543,7 @@ class SmartyTask extends Task {                      // reset value, and then                       // read in teh contents of the file into that var                      $value = ""; -                    $f = new PhingFile($project->resolveFile($value)->getCanonicalPath());                         +                    $f = new PhingFile($this->project->resolveFile($value)->getCanonicalPath());                      if ($f->exists()) {                          try {                              $fr = new FileReader($f); diff --git a/buildscripts/phing/classes/phing/tasks/ext/SshTask.php b/buildscripts/phing/classes/phing/tasks/ext/SshTask.php new file mode 100644 index 00000000..9c2349a8 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SshTask.php @@ -0,0 +1,224 @@ +<?php +/* + *  $Id: e0fe77ed287d359bd7449d459769370e6192417f $ + * + * 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/Task.php'; + +/** + * Execute commands on a remote host using ssh. + * + * @author    Johan Van den Brande <johan@vandenbrande.com> + * @version   $Id: e0fe77ed287d359bd7449d459769370e6192417f $ + * @package   phing.tasks.ext + */ +class SshTask extends Task { + +    private $host = ""; +    private $port = 22; +    private $username = ""; +    private $password = ""; +    private $command = ""; +    private $pubkeyfile = ''; +    private $privkeyfile = ''; +    private $privkeyfilepassphrase = ''; +     +    /** +     * The name of the property to capture (any) output of the command +     * @var string +     */ +    private $property = ""; +     +    /** +     * Whether to display the output of the command +     * @var boolean +     */ +    private $display = true; + +    public function setHost($host)  +    { +        $this->host = $host; +    } + +    public function getHost()  +    { +        return $this->host; +    } + +    public function setPort($port)  +    { +        $this->port = $port; +    } + +    public function getPort()  +    { +        return $this->port; +    } + +    public function setUsername($username)  +    { +        $this->username = $username; +    } + +    public function getUsername()  +    { +        return $this->username; +    } + +    public function setPassword($password)  +    { +        $this->password = $password; +    } + +    public function getPassword()  +    { +        return $this->password; +    } + +    /** +     * Sets the public key file of the user to scp +     */ +    public function setPubkeyfile($pubkeyfile) +    { +        $this->pubkeyfile = $pubkeyfile; +    } + +    /** +     * Returns the pubkeyfile +     */ +    public function getPubkeyfile() +    { +        return $this->pubkeyfile; +    } +     +    /** +     * Sets the private key file of the user to scp +     */ +    public function setPrivkeyfile($privkeyfile) +    { +        $this->privkeyfile = $privkeyfile; +    } + +    /** +     * Returns the private keyfile +     */ +    public function getPrivkeyfile() +    { +        return $this->privkeyfile; +    } +     +    /** +     * Sets the private key file passphrase of the user to scp +     */ +    public function setPrivkeyfilepassphrase($privkeyfilepassphrase) +    { +        $this->privkeyfilepassphrase = $privkeyfilepassphrase; +    } + +    /** +     * Returns the private keyfile passphrase +     */ +    public function getPrivkeyfilepassphrase($privkeyfilepassphrase) +    { +        return $this->privkeyfilepassphrase; +    } +     +    public function setCommand($command)  +    { +        $this->command = $command; +    } + +    public function getCommand()  +    { +        return $this->command; +    } +     +    /** +     * Sets the name of the property to capture (any) output of the command +     * @param string $property +     */ +    public function setProperty($property) +    { +        $this->property = $property; +    } +     +    /** +     * Sets whether to display the output of the command +     * @param boolean $display +     */ +    public function setDisplay($display) +    { +        $this->display = (boolean) $display; +    } + +    public function init()  +    { +    } + +    public function main()  +    { +        if (!function_exists('ssh2_connect')) {  +            throw new BuildException("To use SshTask, you need to install the PHP SSH2 extension."); +        } +         +        $this->connection = ssh2_connect($this->host, $this->port); +        if (is_null($this->connection)) { +            throw new BuildException("Could not establish connection to " . $this->host . ":" . $this->port . "!"); +        } + +        $could_auth = null; +        if ( $this->pubkeyfile ) { +            $could_auth = ssh2_auth_pubkey_file($this->connection, $this->username, $this->pubkeyfile, $this->privkeyfile, $this->privkeyfilepassphrase); +        } else { +            $could_auth = ssh2_auth_password($this->connection, $this->username, $this->password); +        } +        if (!$could_auth) { +            throw new BuildException("Could not authenticate connection!"); +        } + +        $stream = ssh2_exec($this->connection, $this->command); +        if (!$stream) { +            throw new BuildException("Could not execute command!"); +        } +         +        $this->log("Executing command {$this->command}", Project::MSG_VERBOSE); +         +        stream_set_blocking($stream, true); +        $result = stream_get_contents($stream); +         +        if (!strlen($result)) { +            $stderr_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR); +            stream_set_blocking($stderr_stream, true); +            $result = stream_get_contents($stderr_stream); +        } +         +        if ($this->display) { +            print($result); +        } +         +        if (!empty($this->property)) { +            $this->project->setProperty($this->property, $result); +        } +         +        fclose($stream); +        if (isset($stderr_stream)) { +            fclose($stderr_stream); +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/Arg.php b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/Arg.php new file mode 100644 index 00000000..564fdef4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/Arg.php @@ -0,0 +1,96 @@ +<?php +require_once "phing/types/DataType.php"; + + +/** + * Implementation of console argument + * + * @author nuno costa <nuno@francodacosta.com> + * @license GPL + */ +class Arg extends DataType +{ +    private $name = null; +    private $value = null; +    private $quotes = false; + +    /** +     * Gets the argment name +     * @return String +     */ +    public function getName() +    { +        return $this->name; +    } + +    /** +     * Sets the argument name +     * @param String $name +     */ +    public function setName($name) +    { +        $this->name = $name; +    } + +    /** +     * Gets the argument value +     * @return String +     */ +    public function getValue() +    { +        return $this->value; +    } + +    /** +     * Sets the argument value +     * @param String $value +     */ +    public function setValue($value) +    { +        $this->value = $value; +    } + +    /** +     * Should the argument value be enclosed in double quotes +     * @return boolean +     */ +    public function getQuotes() +    { +        return $this->quotes; +    } + +    /** +     * Should the argument value be enclosed in double quotes +     * @param boolean $quotes +     */ +    public function setQuotes( $quotes) +    { +        $this->quotes = $quotes; +    } + +    /** +     * Transforms the argument object into a string, takes into consideration +     * the quotes and the argument value +     * @return String +     */ +    public function __toString() +    { +        $name = ""; +        $value = ""; +        $quote = $this->getQuotes() ? '"' : ''; + +        if (!is_null($this->getValue())) { +            $value = $quote . $this->getValue() . $quote ; +        } + +        if (!is_null($this->getName())) { +            $name = '--' . $this->getName(); +        } + +        if (strlen($name) > 0 && strlen($value) > 0) { +            $value = '=' . $value; +        } +        return $name . ' ' . $value; +    } + +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php new file mode 100644 index 00000000..64c1f02b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php @@ -0,0 +1,113 @@ +<?php +require_once "phing/Task.php"; +require_once dirname(__FILE__) . "/Arg.php"; +/** + * Symfony Console Task + * @author nuno costa <nuno@francodacosta.com> + * @license GPL + * + */ +class SymfonyConsoleTask extends Task +{ + +    /** +     * +     * @var Array of Arg a collection of Arg objects +     */ +    private $args = array(); + +    /** +     * +     * @var string the Symfony console command to execute +     */ +    private $command = null; + +    /** +     * +     * @var string path to symfony console application +     */ +    private $console = 'app/console'; + + +    /** +     * sets the symfony console command to execute +     * @param string $command +     */ +    public function setCommand($command) +    { +        $this->command = $command; +    } + +    /** +     * return the symfony console command to execute +     * @return String +     */ +    public function getCommand() +    { +        return $this->command; +    } + +    /** +     * sets the path to symfony console application +     * @param string $console +     */ +    public function setConsole($console) +    { +        $this->console = $console; +    } + +    /** +     * returns the path to symfony console application +     * @return string +     */ +    public function getConsole() +    { +        return $this->console; +    } + +    /** +     * appends an arg tag to the arguments stack +     * +     * @return Arg Argument object +     */ + +    public function createArg() +    { +        $num = array_push($this->args, new Arg());
 +        return $this->args[$num-1]; +    } + +    /** +     * return the argumments passed to this task +     * @return array of Arg() +     */ +    public function getArgs() +    { +        return $this->args; +    } + + +    /** +     * Gets the command string to be executed +     * @return string +     */ +    public function getCmdString() { +        $cmd = array(
 +                $this->console,
 +                $this->command,
 +                implode(' ', $this->args)
 +        );
 +        $cmd = implode(' ', $cmd); +        return $cmd; +    } +    /** +     * executes the synfony consile application +     */ +    public function main() +    { +        $cmd = $this->getCmdString(); + +        $this->log("executing $cmd"); +        passthru ($cmd); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/SymlinkTask.php b/buildscripts/phing/classes/phing/tasks/ext/SymlinkTask.php new file mode 100644 index 00000000..57738398 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SymlinkTask.php @@ -0,0 +1,309 @@ +<?php + +/* + *  $Id: 6efb50d5b7cb94f2f22db6e876010e718aa25b22 $ + * + * 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/Task.php"; + +/** + * Generates symlinks based on a target / link combination. + * Can also symlink contents of a directory, individually + * + * Single target symlink example: + * <code> + *     <symlink target="/some/shared/file" link="${project.basedir}/htdocs/my_file" /> + * </code> + * + * Symlink entire contents of directory + * + * This will go through the contents of "/my/shared/library/*" + * and create a symlink for each entry into ${project.basedir}/library/ + * <code> + *     <symlink link="${project.basedir}/library"> + *         <fileset dir="/my/shared/library"> + *             <include name="*" /> + *         </fileset> + *     </symlink> + * </code> + *  + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @extends Task + * @version $ID$ + * @package phing.tasks.ext + */ +class SymlinkTask extends Task +{ +    /** +     * What we're symlinking from +     *  +     * (default value: null) +     *  +     * @var string +     * @access private +     */ +    private $_target = null; +     +    /** +     * Symlink location +     *  +     * (default value: null) +     *  +     * @var string +     * @access private +     */ +    private $_link = null; +     +    /** +     * Collection of filesets +     * Used when linking contents of a directory +     *  +     * (default value: array()) +     *  +     * @var array +     * @access private +     */ +    private $_filesets = array(); +     +    /** +     * Whether to override the symlink if it exists but points +     * to a different location +     * +     * (default value: false) +     * +     * @var boolean +     * @access private +     */ +    private $_overwrite = false; + +    /** +     * setter for _target +     *  +     * @access public +     * @param string $target +     * @return void +     */ +    public function setTarget($target) +    { +        $this->_target = $target; +    } +     +    /** +     * setter for _link +     *  +     * @access public +     * @param string $link +     * @return void +     */ +    public function setLink($link) +    {         +        $this->_link = $link; +    } +     +    /** +     * creator for _filesets +     *  +     * @access public +     * @return FileSet +     */ +    public function createFileset() +    { +        $num = array_push($this->_filesets, new FileSet()); +        return $this->_filesets[$num-1]; +    } + +    /** +     * setter for _overwrite +     * +     * @access public +     * @param boolean $overwrite +     * @return void +     */ +    public function setOverwrite($overwrite) +    { +        $this->_overwrite = $overwrite; +    } + +    /** +     * getter for _target +     *  +     * @access public +     * @return string +     */ +    public function getTarget() +    { +        if($this->_target === null) { +            throw new BuildException('Target not set'); +        } +         +        return $this->_target; +    } +     +    /** +     * getter for _link +     *  +     * @access public +     * @return string +     */ +    public function getLink() +    { +        if($this->_link === null) { +            throw new BuildException('Link not set'); +        } +         +        return $this->_link; +    } +     +    /** +     * getter for _filesets +     *  +     * @access public +     * @return array +     */ +    public function getFilesets() +    { +        return $this->_filesets; +    } + +    /** +     * getter for _overwrite +     * +     * @access public +     * @return boolean +     */ +    public function getOverwrite() +    { +        return $this->_overwrite; +    } + +    /** +     * Generates an array of directories / files to be linked +     * If _filesets is empty, returns getTarget() +     *  +     * @access protected +     * @return array|string +     */ +    protected function getMap() +    { +        $fileSets = $this->getFilesets(); +         +        // No filesets set +        // We're assuming single file / directory +        if(empty($fileSets)) { +            return $this->getTarget(); +        } +     +        $targets = array(); +         +        foreach($fileSets as $fs) { +            if(!($fs instanceof FileSet)) { +                continue; +            } +             +            // We need a directory to store the links +            if(!is_dir($this->getLink())) { +                throw new BuildException('Link must be an existing directory when using fileset'); +            } +             +            $fromDir = $fs->getDir($this->getProject())->getAbsolutePath(); + +            if(!is_dir($fromDir)) { +                $this->log('Directory doesn\'t exist: ' . $fromDir, Project::MSG_WARN); +                continue; +            } +             +            $fsTargets = array(); +             +            $ds = $fs->getDirectoryScanner($this->getProject()); +             +            $fsTargets = array_merge( +                $fsTargets, +                $ds->getIncludedDirectories(), +                $ds->getIncludedFiles() +            ); +             +            // Add each target to the map +            foreach($fsTargets as $target) { +                if(!empty($target)) { +                    $targets[$target] = $fromDir . DIRECTORY_SEPARATOR . $target; +                } +            } +        } +         +        return $targets; +    } +     +    /** +     * Main entry point for task +     *  +     * @access public +     * @return bool +     */ +    public function main() +    { +        $map = $this->getMap(); +         +        // Single file symlink +        if(is_string($map)) { +            return $this->symlink($map, $this->getLink()); +        } +         +        // Multiple symlinks +        foreach($map as $name => $targetPath) { +            $this->symlink($targetPath, $this->getLink() . DIRECTORY_SEPARATOR . $name); +        } +         +        return true; +    } +     +    /** +     * Create the actual link +     *  +     * @access protected +     * @param string $target +     * @param string $link +     * @return bool +     */ +    protected function symlink($target, $link) +    { +        $fs = FileSystem::getFileSystem(); +         +        if (is_link($link) && readlink($link) == $target) { +            $this->log('Link exists: ' . $link, Project::MSG_INFO); +            return true; +        } elseif (file_exists($link)) { +            if (!$this->getOverwrite()) { +                $this->log('Not overwriting existing link ' . $link, Project::MSG_ERR); +                return false; +            } +             +            if (is_link($link) || is_file($link)) { +                $fs->unlink($link); +                $this->log('Link removed: ' . $link, Project::MSG_INFO); +            } else { +                $fs->rmdir($link, true); +                $this->log('Directory removed: ' . $link, Project::MSG_INFO); +            } +        } +     +        $this->log('Linking: ' . $target . ' to ' . $link, Project::MSG_INFO); +         +        return $fs->symlink($target, $link); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/TarTask.php b/buildscripts/phing/classes/phing/tasks/ext/TarTask.php index 8d6bb47f..95d915d7 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/TarTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/TarTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TarTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: c3ac5fcdf4d7cdb199d57b021e3f015c9c7fd3f8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/util/StringHelper.php';   * @author    Stefano Mazzocchi <stefano@apache.org> (Ant)   * @author    Stefan Bodewig <stefan.bodewig@epost.de> (Ant)   * @author    Magesh Umasankar - * @version   $Revision: 1.10 $ + * @version   $Id: c3ac5fcdf4d7cdb199d57b021e3f015c9c7fd3f8 $   * @package   phing.tasks.ext   */  class TarTask extends MatchingTask { @@ -44,7 +44,8 @@ class TarTask extends MatchingTask {      private $tarFile;      private $baseDir; - +    private $includeEmpty = true; // Whether to include empty dirs in the TAR +          private $longFileMode = "warn";      private $filesets = array(); @@ -59,6 +60,13 @@ class TarTask extends MatchingTask {       * Compression mode.  Available options "gzip", "bzip2", "none" (null).       */      private $compression = null; + +    /** +     * File path prefix in the tar archive +     * +     * @var string +     */ +    private $prefix = null;      /**       * Ensures that PEAR lib exists. @@ -108,6 +116,16 @@ class TarTask extends MatchingTask {      }      /** +     * Set the include empty dirs flag. +     * @param  boolean  Flag if empty dirs should be tarred too +     * @return void +     * @access public +     */ +    public function setIncludeEmptyDirs($bool) { +        $this->includeEmpty = (boolean) $bool; +    } + +    /**       * Set how to handle long files, those with a path>100 chars.       * Optional, default=warn.       * <p> @@ -145,10 +163,21 @@ class TarTask extends MatchingTask {                  $this->compression = null;                  break;              default: -                $this->log("Ignoring unknown compression mode: ".$mode, PROJECT_MSG_WARN); +                $this->log("Ignoring unknown compression mode: ".$mode, Project::MSG_WARN);                  $this->compression = null;          }      } + +    /** +     * Sets the file path prefix for file in the tar file. +     * +     * @param string $prefix Prefix +     * +     * @return void +     */ +    public function setPrefix($prefix) { +        $this->prefix = $prefix; +    }      /**       * do the work @@ -175,13 +204,14 @@ class TarTask extends MatchingTask {          try {              if ($this->baseDir !== null) {                  if (!$this->baseDir->exists()) { -                    throw new BuildException("basedir does not exist!", $this->getLocation()); +                    throw new BuildException("basedir '" . (string) $this->baseDir . "' does not exist!", $this->getLocation()); +                } +                if (empty($this->filesets)) { // if there weren't any explicit filesets specivied, then +                                              // create a default, all-inclusive fileset using the specified basedir. +                    $mainFileSet = new TarFileSet($this->fileset); +                    $mainFileSet->setDir($this->baseDir); +                    $this->filesets[] = $mainFileSet;                  } - -                // add the main fileset to the list of filesets to process. -                $mainFileSet = new TarFileSet($this->fileset); -                $mainFileSet->setDir($this->baseDir); -                $this->filesets[] = $mainFileSet;              }              if (empty($this->filesets)) { @@ -190,27 +220,27 @@ class TarTask extends MatchingTask {                                           $this->getLocation());              }                         -            // check if tar is out of date with respect to each -            // fileset -            $upToDate = true; -            foreach($this->filesets as $fs) { -                $files = $fs->getFiles($this->project); -                if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) { -                    $upToDate = false; -                } -                for ($i=0, $fcount=count($files); $i < $fcount; $i++) { -                    if ($this->tarFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) { -                        throw new BuildException("A tar file cannot include itself", $this->getLocation()); +            // check if tar is out of date with respect to each fileset +            if($this->tarFile->exists()) { +                $upToDate = true; +                foreach($this->filesets as $fs) { +                    $files = $fs->getFiles($this->project, $this->includeEmpty); +                    if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) { +                        $upToDate = false; +                    } +                    for ($i=0, $fcount=count($files); $i < $fcount; $i++) { +                        if ($this->tarFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) { +                            throw new BuildException("A tar file cannot include itself", $this->getLocation()); +                        }                      }                  } +                if ($upToDate) { +                    $this->log("Nothing to do: " . $this->tarFile->__toString() . " is up to date.", Project::MSG_INFO); +                    return; +                }              } -            if ($upToDate) { -                $this->log("Nothing to do: " . $this->tarFile->__toString() . " is up to date.", PROJECT_MSG_INFO); -                return; -            } - -            $this->log("Building tar: " . $this->tarFile->__toString(), PROJECT_MSG_INFO); +            $this->log("Building tar: " . $this->tarFile->__toString(), Project::MSG_INFO);              $tar = new Archive_Tar($this->tarFile->getAbsolutePath(), $this->compression); @@ -218,25 +248,21 @@ class TarTask extends MatchingTask {              $tar->setErrorHandling(PEAR_ERROR_PRINT);              foreach($this->filesets as $fs) {                                 -                    $files = $fs->getFiles($this->project); +                    $files = $fs->getFiles($this->project, $this->includeEmpty);                      if (count($files) > 1 && strlen($fs->getFullpath()) > 0) {                          throw new BuildException("fullpath attribute may only "                                                   . "be specified for "                                                   . "filesets that specify a "                                                   . "single file.");                      } -                    // FIXME  -                    // Current model is only adding directories implicitly.  This -                    // won't add any empty directories.  Perhaps modify TarFileSet::getFiles() -                    // to also include empty directories.  Not high priority, since non-inclusion -                    // of empty dirs is probably not unexpected behavior for TarTask.                      $fsBasedir = $fs->getDir($this->project);                      $filesToTar = array();                      for ($i=0, $fcount=count($files); $i < $fcount; $i++) {                          $f = new PhingFile($fsBasedir, $files[$i]); -                        $filesToTar[] = $f->getAbsolutePath();                         +                        $filesToTar[] = $f->getAbsolutePath(); +                        $this->log("Adding file " . $f->getPath() . " to archive.", Project::MSG_VERBOSE);                                      }                     -                    $tar->addModify($filesToTar, '', $fsBasedir->getAbsolutePath());             +                    $tar->addModify($filesToTar, $this->prefix, $fsBasedir->getAbsolutePath());                          } @@ -270,6 +296,7 @@ class TarTask extends MatchingTask {   * Permissions are currently not implemented by PEAR Archive_Tar,   * but hopefully they will be in the future.   *  + * @package   phing.tasks.ext   */  class TarFileSet extends FileSet { @@ -288,11 +315,49 @@ class TarFileSet extends FileSet {       *  @return array a list of file and directory names, relative to       *    the baseDir for the project.       */ -    public function getFiles(Project $p) { +    public function getFiles(Project $p, $includeEmpty = true) { +              if ($this->files === null) { +                      $ds = $this->getDirectoryScanner($p);              $this->files = $ds->getIncludedFiles(); -        } +             +            if ($includeEmpty) { +             +                // first any empty directories that will not be implicitly added by any of the files +                $implicitDirs = array(); +                foreach($this->files as $file) { +                    $implicitDirs[] = dirname($file); +                }  +                 +                $incDirs = $ds->getIncludedDirectories(); +                 +                // we'll need to add to that list of implicit dirs any directories +                // that contain other *directories* (and not files), since otherwise +                // we get duplicate directories in the resulting tar +                foreach($incDirs as $dir) { +                    foreach($incDirs as $dircheck) { +                        if (!empty($dir) && $dir == dirname($dircheck)) { +                            $implicitDirs[] = $dir; +                        } +                    } +                } +                 +                $implicitDirs = array_unique($implicitDirs); +                 +                // Now add any empty dirs (dirs not covered by the implicit dirs) +                // to the files array.  +                 +                foreach($incDirs as $dir) { // we cannot simply use array_diff() since we want to disregard empty/. dirs +                    if ($dir != "" && $dir != "." && !in_array($dir, $implicitDirs)) { +                        // it's an empty dir, so we'll add it. +                        $this->files[] = $dir; +                    } +                } +            } // if $includeEmpty +             +        } // if ($this->files===null) +                  return $this->files;      } diff --git a/buildscripts/phing/classes/phing/tasks/ext/UntarTask.php b/buildscripts/phing/classes/phing/tasks/ext/UntarTask.php new file mode 100644 index 00000000..74777322 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/UntarTask.php @@ -0,0 +1,89 @@ +<?php
 +/*
 + *
 + * 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/ext/ExtractBaseTask.php';
 +
 +/**
 + * Extracts one or several tar archives using PEAR Archive_Tar
 + *
 + * @author    Joakim Bodin <joakim.bodin+phing@gmail.com>
 + * @version   $Id: f77612833e0415725e7b816a0515db4a4f0f4c93 $
 + * @package   phing.tasks.ext
 + * @since     2.2.0
 + */
 +class UntarTask extends ExtractBaseTask {
 +
 +    /**
 +     * Ensures that PEAR lib exists.
 +     */
 +    public function init() {
 +        include_once 'Archive/Tar.php';
 +        if (!class_exists('Archive_Tar')) {
 +            throw new BuildException("You must have installed the PEAR Archive_Tar class in order to use UntarTask.");
 +        }
 +    }
 +
 +    protected function extractArchive(PhingFile $tarfile)
 +    {
 +        $this->log("Extracting tar file: " . $tarfile->__toString() . ' to ' . $this->todir->__toString(), Project::MSG_INFO);
 +
 +        try {
 +            $tar = $this->initTar($tarfile);
 +            if(!$tar->extractModify($this->todir->getAbsolutePath(), $this->removepath)) {
 +                throw new BuildException('Failed to extract tar file: ' . $tarfile->getAbsolutePath());
 +            }
 +        } catch (IOException $ioe) {
 +            $msg = "Could not extract tar file: " . $ioe->getMessage();
 +            throw new BuildException($msg, $ioe, $this->getLocation());
 +        }
 +    }
 +
 +    protected function listArchiveContent(PhingFile $tarfile)
 +    {
 +        $tar = $this->initTar($tarfile);
 +        return $tar->listContent();
 +    }
 +
 +    /**
 +     * Init a Archive_Tar class with correct compression for the given file.
 +     *
 +     * @param PhingFile $tarfile
 +     * @return Archive_Tar the tar class instance
 +     */
 +    private function initTar(PhingFile $tarfile)
 +    {
 +        $compression = null;
 +        $tarfileName = $tarfile->getName();
 +        $mode = strtolower(substr($tarfileName, strrpos($tarfileName, '.')));
 +
 +        $compressions = array(
 +                'gz' => array('.gz', '.tgz',),
 +                'bz2' => array('.bz2',),
 +            );
 +        foreach ($compressions as $algo => $ext) {
 +            if (array_search($mode, $ext) !== false) {
 +                $compression = $algo;
 +                break;
 +            }
 +        }
 +
 +        return new Archive_Tar($tarfile->getAbsolutePath(), $compression);
 +    }
 +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/UnzipTask.php b/buildscripts/phing/classes/phing/tasks/ext/UnzipTask.php new file mode 100644 index 00000000..ef7c3e7d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/UnzipTask.php @@ -0,0 +1,77 @@ +<?php +/* + * + * 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/ext/ExtractBaseTask.php'; +require_once 'phing/system/io/FileSystem.php'; + +/** + * Extracts one or several zip archives using ZipArchive class. + * + * @author  Joakim Bodin <joakim.bodin+phing@gmail.com> + * @author  George Miroshnikov <laggy.luke@gmail.com> + * @version $Id: 9c4afd9af5e81250ca6c7afbc6e646c2a0f0148c $ + * @package phing.tasks.ext + */ +class UnzipTask extends ExtractBaseTask +{ +    /** +     * Extract archive content into $this->todir directory +     * @param PhingFile Zip file to extract +     * @return boolean +     */ +    protected function extractArchive(PhingFile $zipfile) +    { +        $this->log("Extracting zip: " . $zipfile->__toString() . ' to ' . $this->todir->__toString(), Project::MSG_INFO); +         +        $zip = new ZipArchive(); +         +        $result = $zip->open($zipfile->getAbsolutePath()); +        if (!$result) { +            $this->log("Unable to open zipfile " . $zipfile->__toString(), Project::MSG_ERR); +            return false; +        } +         +        $result = $zip->extractTo($this->todir->getAbsolutePath()); +        if (!$result) { +            $this->log("Unable to extract zipfile " . $zipfile->__toString(), Project::MSG_ERR); +            return false; +        } +         +        return true; +    } +     +    /** +     * List archive content +     * @param PhingFile Zip file to list content +     * @return array List of files inside $zipfile +     */ +    protected function listArchiveContent(PhingFile $zipfile) +    { +        $zip = new ZipArchive(); +        $zip->open($zipfile->getAbsolutePath()); +         +        $content = array(); +        for ($i = 0; $i < $zip->numFiles; $i++) { +            $content[] = $zip->getNameIndex($i); +        } +        return $content; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/VersionTask.php b/buildscripts/phing/classes/phing/tasks/ext/VersionTask.php new file mode 100755 index 00000000..b8268870 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/VersionTask.php @@ -0,0 +1,217 @@ +<?php +/* + * $Id: 7fb6793b55e9c1c8c7b3cd8a87b694d720b32749 $ + * + * 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/Task.php'; + +/** + * VersionTask + * + * Increments a three-part version number from a given file + * and writes it back to the file. + * Incrementing is based on given releasetype, which can be one + * of Major, Minor and Bugfix. + * Resulting version number is also published under supplied property. + * + * @author      Mike Wittje <mw@mike.wittje.de> + * @version     $Id: 7fb6793b55e9c1c8c7b3cd8a87b694d720b32749 $ $Rev $Id$ $Author$ + * @package     phing.tasks.ext + */ +class VersionTask extends Task +{ +    /** +     * Property for Releasetype +     * @var string $releasetype +     */ +    private $releasetype; + +    /** +     * Property for File +     * @var PhingFile file +     */ +    private $file; + +    /** +     * Property to be set +     * @var string $property +     */ +    private $property; + +    /* Allowed Releastypes */ +    const RELEASETYPE_MAJOR = 'MAJOR'; +    const RELEASETYPE_MINOR = 'MINOR'; +    const RELEASETYPE_BUGFIX = 'BUGFIX'; + +    /** +     * Set Property for Releasetype (Minor, Major, Bugfix) +     * @param string  $releasetype +     */ +    public function setReleasetype($releasetype) +    { +        $this->releasetype = strtoupper($releasetype); +    } + +    /** +     * Set Property for File containing versioninformation +     * @param PhingFile $file +     */ +    public function setFile($file) +    { +        $this->file = $file; +    } + +    /** +     * Set name of property to be set +     * @param $property +     * @return void +     */ +    public function setProperty($property) +    { +        $this->property = $property; +    } + +    /** +     * Main-Method for the Task +     * +     * @return  void +     * @throws  BuildException +     */ +    public function main() +    { +        // check supplied attributes +        $this->checkReleasetype(); +        $this->checkFile(); +        $this->checkProperty(); + +        // read file +        $filecontent = trim(file_get_contents($this->file)); + +        // get new version +        $newVersion = $this->getVersion($filecontent); + +        // write new Version to file +        file_put_contents($this->file, $newVersion . "\n"); + +        // publish new version number as property +        $this->project->setProperty($this->property, $newVersion); + +    } + +    /** +     * Returns new version number corresponding to Release type +     * +     * @param string $filecontent +     * @return string +     */ +    private function getVersion($filecontent) +    { +        // init +        $newVersion = ''; + +        // Extract version +        list($major, $minor, $bugfix) = explode(".", $filecontent); + +        // Return new version number +        switch ($this->releasetype) { +            case self::RELEASETYPE_MAJOR: +                $newVersion = sprintf("%d.%d.%d", ++$major, +                                                  0, +                                                  0); +                break; + +            case self::RELEASETYPE_MINOR: +                $newVersion = sprintf("%d.%d.%d", $major, +                                                  ++$minor, +                                                  0); +                break; + +            case self::RELEASETYPE_BUGFIX: +                $newVersion = sprintf("%d.%d.%d", $major, +                                                  $minor, +                                                  ++$bugfix); +                break; +        } + +        return $newVersion; +    } + + +    /** +     * checks releasetype attribute +     * @return void +     * @throws BuildException +     */ +    private function checkReleasetype() +    { +        // check Releasetype +        if (is_null($this->releasetype)) { +            throw new BuildException('releasetype attribute is required', $this->location); +        } +        // known releasetypes +        $releaseTypes = array( +            self::RELEASETYPE_MAJOR, +            self::RELEASETYPE_MINOR, +            self::RELEASETYPE_BUGFIX +        ); + +        if (!in_array($this->releasetype, $releaseTypes)) { +            throw new BuildException(sprintf('Unknown Releasetype %s..Must be one of Major, Minor or Bugfix', +                                        $this->releasetype), $this->location); +        } +    } + +    /** +     * checks file attribute +     * @return void +     * @throws BuildException +     */ +    private function checkFile() +    { +        // check File +        if ($this->file === null || +        strlen($this->file) == 0) { +            throw new BuildException('You must specify a file containing the version number', $this->location); +        } + +        $content = file_get_contents($this->file); +        if (strlen($content) == 0) { +            throw new BuildException(sprintf('Supplied file %s is empty', $this->file), $this->location); +        } + +        // check for three-part number +        $split = explode('.', $content); +        if (count($split) !== 3) { +            throw new BuildException('Unknown version number format', $this->location); +        } + +    } + +    /** +     * checks property attribute +     * @return void +     * @throws BuildException +     */ +    private function checkProperty() +    { +        if (is_null($this->property) || +            strlen($this->property) === 0) { +            throw new BuildException('Property for publishing version number is not set', $this->location); +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php index 866e954d..15200d37 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php @@ -1,10 +1,31 @@  <?php +/* + *  $Id: 6261b2f19844b353c379c46daf3ffb13b7a2ddb8 $ + * + * 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/Task.php';  /**   * A XML lint task. Checking syntax of one or more XML files against an XML Schema using the DOM extension.   *   * @author   Knut Urdalen <knut.urdalen@telio.no> + * @version  $Id: 6261b2f19844b353c379c46daf3ffb13b7a2ddb8 $   * @package  phing.tasks.ext   */  class XmlLintTask extends Task { @@ -12,6 +33,9 @@ class XmlLintTask extends Task {    protected $file;  // the source file (from xml attribute)    protected $schema; // the schema file (from xml attribute)    protected $filesets = array(); // all fileset objects assigned to this task +  protected $useRNG = false; +   +  protected $haltonfailure = true;    /**     * File to be performed syntax check on @@ -31,26 +55,42 @@ class XmlLintTask extends Task {      $this->schema = $schema;    } +   +  /** +   * Use RNG instead of DTD schema validation +   * +   * @param bool $bool +   */ +  public function setUseRNG($bool) { +    $this->useRNG = (boolean)$bool; +  } +   +      /**     * Nested creator, creates a FileSet for this task     *     * @return FileSet The created fileset object     */ -  function createFileSet() { +  public function createFileSet() {      $num = array_push($this->filesets, new FileSet());      return $this->filesets[$num-1];    } +   +  /** +   * Sets the haltonfailure attribute +   * +   * @param bool $haltonfailure +   */ +  public function setHaltonfailure($haltonfailure) { +    $this->haltonfailure = (bool) $haltonfailure; +  }    /**     * Execute lint check against PhingFile or a FileSet     */    public function main() { -    if(!isset($this->schema)) { -      throw new BuildException("Missing attribute 'schema'"); -    } -    $schema = $this->schema->getPath(); -    if(!file_exists($schema)) { -      throw new BuildException("File not found: ".$schema); +    if(isset($this->schema) && !file_exists($this->schema->getPath())) { +      throw new BuildException("Schema file not found: ".$this->schema->getPath());      }      if(!isset($this->file) and count($this->filesets) == 0) {        throw new BuildException("Missing either a nested fileset or attribute 'file' set"); @@ -62,16 +102,24 @@ class XmlLintTask extends Task {      } else { // process filesets        $project = $this->getProject();        foreach($this->filesets as $fs) { -	$ds = $fs->getDirectoryScanner($project); -	$files = $ds->getIncludedFiles(); -	$dir = $fs->getDir($this->project)->getPath(); -	foreach($files as $file) { -	  $this->lint($dir.DIRECTORY_SEPARATOR.$file); -	} +    $ds = $fs->getDirectoryScanner($project); +    $files = $ds->getIncludedFiles(); +    $dir = $fs->getDir($this->project)->getPath(); +    foreach($files as $file) { +      $this->lint($dir.DIRECTORY_SEPARATOR.$file); +    }        }      }      restore_error_handler();    } +   +  protected function logError($message) { +    if ($this->haltonfailure) { +      throw new BuildException($message); +    } else { +      $this->log($message, Project::MSG_ERR); +    } +  }    /**     * Performs validation @@ -81,19 +129,35 @@ class XmlLintTask extends Task {     */    protected function lint($file) {      if(file_exists($file)) { -      if(is_readable($file)) { -	$dom = new DOMDocument(); -	$dom->load($file); -	if($dom->schemaValidate($this->schema->getPath())) { -	  $this->log($file.' validated', PROJECT_MSG_INFO); -	} else { -	  $this->log($file.' fails to validate (See messages above)', PROJECT_MSG_ERR); -	} +      if(is_readable($file)) {       +        $dom = new DOMDocument(); +        if ($dom->load($file) === false) { +          $error = libxml_get_last_error(); +          $this->logError($file.' is not well-formed (See messages above)'); +        } else { +              if(isset($this->schema)) { +                  if( $this->useRNG ) { +                    if($dom->relaxNGValidate($this->schema->getPath())) { +                      $this->log($file.' validated with RNG grammar', Project::MSG_INFO); +                    } else { +                      $this->logError($file.' fails to validate (See messages above)'); +                    }                   +                  } else {               +                    if($dom->schemaValidate($this->schema->getPath())) { +                      $this->log($file.' validated with schema', Project::MSG_INFO); +                    } else { +                      $this->logError($file.' fails to validate (See messages above)'); +                    } +                } +              } else { +                $this->log($file.' is well-formed (not validated due to missing schema specification)', Project::MSG_INFO); +              } +        }        } else { -	throw new BuildException('Permission denied: '.$file); +        $this->logError('Permission denied to read file: '.$file);        }      } else { -      throw new BuildException('File not found: '.$file); +      $this->logError('File not found: '.$file);      }    } @@ -108,9 +172,8 @@ class XmlLintTask extends Task {    public function errorHandler($level, $message, $file, $line, $context) {      $matches = array();      preg_match('/^.*\(\): (.*)$/', $message, $matches); -    $this->log($matches[1], PROJECT_MSG_ERR); +    $this->log($matches[1], Project::MSG_ERR);    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/XmlPropertyTask.php b/buildscripts/phing/classes/phing/tasks/ext/XmlPropertyTask.php new file mode 100755 index 00000000..d32cd78e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/XmlPropertyTask.php @@ -0,0 +1,273 @@ +<?php + +/* + *  $Id: c7a3e7eff0b94828f9ec634c3612d89f2740fead $ + * + * 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>. + */ + +include_once 'phing/tasks/system/PropertyTask.php'; + +/** + * Task for setting properties from an XML file in buildfiles. + *  + * @author    Jonathan Bond-Caron <jbondc@openmv.com> + * @version   $Id: c7a3e7eff0b94828f9ec634c3612d89f2740fead $ + * @package   phing.tasks.ext + * @since     2.4.0 + * @link      http://ant.apache.org/manual/CoreTasks/xmlproperty.html + */ +class XmlPropertyTask extends PropertyTask { + +    private $_keepRoot = true; +    private $_collapseAttr = false; +    private $_delimiter = ','; +    private $_required = false; + +    /** Set a file to use as the source for properties. */ +    public function setFile($file) { +        if (is_string($file)) { +            $file = new PhingFile($file); +        } +        $this->file = $file; +    } +     +    /** Get the PhingFile that is being used as property source. */ +    public function getFile() { +        return $this->file; +    } + +    /** +     * Prefix to apply to properties loaded using <code>file</code>. +     * A "." is appended to the prefix if not specified. +     * @param string $prefix prefix string +     * @return void +     * @since 2.0 +     */ +    public function setPrefix($prefix) { +        $this->prefix = $prefix; +        if (!StringHelper::endsWith(".", $prefix)) { +            $this->prefix .= "."; +        } +    } + +    /** +     * @return string +     * @since 2.0 +     */ +    public function getPrefix() { +        return $this->prefix; +    } + +    /** +     * Keep the xml root tag as the first value in the property name +     * +     * @param bool $yesNo +     */ +    public function setKeepRoot($yesNo) { +        $this->_keepRoot = (bool)$yesNo; +    } + +    /** +     * @return bool +     */ +    public function getKeepRoot() { +        return $this->_keepRoot; +    } + +    /** +     * Treat attributes as nested elements. +     * +     * @param bool $yesNo +     */ +    public function setCollapseAttributes($yesNo) { +        $this->_collapseAttr = (bool)$yesNo; +    } + +    /** +     * @return bool +     */ +    public function getCollapseAttributes() { +        return $this->_collapseAttr; +    } + +    /** +     * Delimiter for splitting multiple values. +     * +     * @param string $d +     */ +    public function setDelimiter($d) { +        $this->_delimiter = $d; +    } + +    /** +     * @return string +     */ +    public function getDelimiter() { +        return $this->_delimiter; +    } + +    /** +     * File required or not. +     * +     * @param string $d +     */ +    public function setRequired($d) { +        $this->_required = $d; +    } + +    /** +     * @return string +     */ +    public function getRequired() { +        return $this->_required; +    } + +    /** +     * set the property in the project to the value. +     * if the task was give a file or env attribute +     * here is where it is loaded +     */ +    public function main() { + +        if ($this->file === null ) { +            throw new BuildException("You must specify file to load properties from", $this->getLocation()); +        } + +        $this->loadFile($this->file); +    } + +    /** +     * load properties from an XML file. +     * @param PhingFile $file +     */ +    protected function loadFile(PhingFile $file) { +        $props = new Properties(); +        $this->log("Loading ". $file->getAbsolutePath(), Project::MSG_INFO); +        try { // try to load file +            if ($file->exists()) { + +                $this->addProperties($this->_getProperties($file)); + +            } else { +                if ($this->getRequired()){ +                    throw new BuildException("Could not load required properties file.", $ioe); +                } else { +                    $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", Project::MSG_WARN); +                } +            } +        } catch (IOException $ioe) { +            throw new BuildException("Could not load properties from file.", $ioe); +        } +    } + +    /** +     * Parses an XML file and returns properties  +     *  +     * @param string $filePath +     * +     * @return Properties +     */ +    protected function _getProperties($filePath) { + +        // load() already made sure that file is readable                 +        // but we'll double check that when reading the file into  +        // an array +         +        if (($lines = @file($filePath)) === false) { +            throw new IOException("Unable to parse contents of $filePath"); +        } +         +        $prop = new Properties; + +        $xml = simplexml_load_file($filePath); + +        if($xml === false) +            throw new IOException("Unable to parse XML file $filePath"); + +        $path = array(); + +        if($this->_keepRoot) { +            $path[] = dom_import_simplexml($xml)->tagName; +             +            $prefix = implode('.', $path); +             +            if (!empty($prefix)) +                $prefix .= '.'; +             +            // Check for attributes +            foreach($xml->attributes() as $attribute => $val) { +                if($this->_collapseAttr) +                    $prop->setProperty($prefix . "$attribute", (string)$val); +                else +                    $prop->setProperty($prefix . "($attribute)", (string)$val); +            } +        } + +        $this->_addNode($xml, $path, $prop); + +        return $prop; +    } + +    /** +     * Adds an XML node +     *  +     * @param SimpleXMLElement $node +     * @param array $path Path to this node +     * @param Properties $prop Properties will be added as they are found (by reference here) +     * +     * @return void +     */ +    protected function _addNode($node, $path, $prop) { +        foreach($node as $tag => $value) { +             +            $prefix = implode('.', $path); +             +            if (!empty($prefix) > 0) +                $prefix .= '.'; +             +            // Check for attributes +            foreach($value->attributes() as $attribute => $val) { +                if($this->_collapseAttr) +                    $prop->setProperty($prefix . "$tag.$attribute", (string)$val); +                else +                    $prop->setProperty($prefix . "$tag($attribute)", (string)$val); +            } +             +            // Add tag +            if(count($value->children())) { +                $this->_addNode($value, array_merge($path, array($tag)), $prop); +            } else { +                $val = (string)$value; +                 +                /* Check for * and ** on 'exclude' and 'include' tag / ant seems to do this? could use FileSet here +                if($tag == 'exclude') { +                }*/ +                 +                // When property already exists, i.e. multiple xml tag +                // <project> +                //    <exclude>file/a.php</exclude> +                //    <exclude>file/a.php</exclude> +                // </project> +                // +                // Would be come project.exclude = file/a.php,file/a.php +                $p = empty($prefix) ? $tag : $prefix . $tag; +                $prop->append($p, (string)$val, $this->_delimiter); +            } +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php b/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php index 490ee797..5093fabe 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php @@ -1,4 +1,24 @@  <?php +/* + *  $Id: 5b7e3fb304bb5f406c919407d6881449a70b8a28 $ + * + * 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/Task.php';  /** @@ -6,7 +26,7 @@ require_once 'phing/Task.php';   *    * Available warnings:   * <b>zend-error</b> - %s(line %d): %s - * <b>oneline-comment</b> - One-line comment ends with ?> tag. + * <b>oneline-comment</b> - One-line comment ends with  tag.   * <b>bool-assign</b> - Assignment seen where boolean expression is expected. Did you mean '==' instead of '='?   * <b>bool-print</b> - Print statement used when boolean expression is expected.   * <b>bool-array</b> - Array used when boolean expression is expected. @@ -38,126 +58,150 @@ require_once 'phing/Task.php';   * <b>empty-cond</b> - Condition without a body   * <b>expr-unused</b> - Expression result is never used   * - * @author   Knut Urdalen <knut.urdalen@telio.no> + * @author   Knut Urdalen <knut.urdalen@gmail.com> + * @version  $Id: 5b7e3fb304bb5f406c919407d6881449a70b8a28 $   * @package  phing.tasks.ext   */ -class ZendCodeAnalyzerTask extends Task { -   -  protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary -  protected $file = "";  // the source file (from xml attribute) -  protected $filesets = array(); // all fileset objects assigned to this task -  protected $warnings = array(); -  protected $counter = 0; -  protected $disable = array(); -  protected $enable = array(); -   -  /** -   * File to be analyzed -   *  -   * @param PhingFile $file -   */ -  public function setFile(PhingFile $file) { -    $this->file = $file; -  } -   -  /** -   * Path to ZendCodeAnalyzer binary -   * -   * @param string $analyzerPath -   */ -  public function setAnalyzerPath($analyzerPath) { -    $this->analyzerPath = $analyzerPath; -  } -   -  /** -   * Disable warning levels. Seperate warning levels with ',' -   * -   * @param string $disable -   */ -  public function setDisable($disable) { -    $this->disable = explode(",", $disable); -  } -   -  /** -   * Enable warning levels. Seperate warning levels with ',' -   * -   * @param string $enable -   */ -  public function setEnable($enable) { -    $this->enable = explode(",", $enable); -  } -   -  /** -   * 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]; -  } +class ZendCodeAnalyzerTask extends Task +{ +    protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary +    protected $file = "";  // the source file (from xml attribute) +    protected $filesets = array(); // all fileset objects assigned to this task +    protected $counter = 0; +    protected $disable = array(); +    protected $enable = array(); + +    private $haltonwarning = false;  -  /** -   * Analyze against PhingFile or a FileSet -   */ -  public function main() { -    if(!isset($this->analyzerPath)) { -      throw new BuildException("Missing attribute 'analyzerPath'"); +    /** +     * File to be analyzed +     *  +     * @param PhingFile $file +     */ +    public function setFile(PhingFile $file) { +        $this->file = $file;      } -    if(!isset($this->file) and count($this->filesets) == 0) { -      throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + +    /** +     * Path to ZendCodeAnalyzer binary +     * +     * @param string $analyzerPath +     */ +    public function setAnalyzerPath($analyzerPath) { +        $this->analyzerPath = $analyzerPath; +    } + +    /** +    * Disable warning levels. Seperate warning levels with ',' +    * +    * @param string $disable +    */ +    public function setDisable($disable) { +        $this->disable = explode(",", $disable); +    } + +    /** +     * Enable warning levels. Seperate warning levels with ',' +     * +     * @param string $enable +     */ +    public function setEnable($enable) { +        $this->enable = explode(",", $enable); +    } + +    /** +     * Sets the haltonwarning flag +     * @param boolean $value +     */ +    public function setHaltonwarning($value) +    { +        $this->haltonwarning = $value;      } -    if($this->file instanceof PhingFile) { -      $this->analyze($this->file->getPath()); -    } else { // process filesets -      $project = $this->getProject(); -      foreach($this->filesets as $fs) { -      	$ds = $fs->getDirectoryScanner($project); -      	$files = $ds->getIncludedFiles(); -      	$dir = $fs->getDir($this->project)->getPath(); -      	foreach($files as $file) { -	  $this->analyze($dir.DIRECTORY_SEPARATOR.$file); -      	} -      } +    /** +     * Nested creator, creates a FileSet for this task +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    /** +     * Analyze against PhingFile or a FileSet +     */ +    public function main() { +        if(!isset($this->analyzerPath)) { +            throw new BuildException("Missing attribute 'analyzerPath'"); +        } +         +        if(!isset($this->file) and count($this->filesets) == 0) { +            throw new BuildException("Missing either a nested fileset or attribute 'file' set"); +        } + +        if($this->file instanceof PhingFile) { +            $this->analyze($this->file->getPath()); +        } else { // process filesets +            $project = $this->getProject(); +         +            foreach($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($project); +                $files = $ds->getIncludedFiles(); +                $dir = $fs->getDir($this->project)->getPath(); +                 +                foreach($files as $file) { +                    $this->analyze($dir.DIRECTORY_SEPARATOR.$file); +                } +            } +        } +         +        $this->log("Number of findings: ".$this->counter, Project::MSG_INFO);      } -    $this->log("Number of findings: ".$this->counter, PROJECT_MSG_INFO); -  } -  /** -   * Analyze file -   * -   * @param string $file -   * @return void -   */ -  protected function analyze($file) { -    if(file_exists($file)) { -      if(is_readable($file)) { -      	 -      	// Construct shell command -      	$cmd = $this->analyzerPath." "; -      	foreach($this->enable as $enable) { // Enable warning levels -      		$cmd .= " --enable $enable "; -      	} -      	foreach($this->disable as $disable) { // Disable warning levels -      		$cmd .= " --disable $disable "; -      	} -      	$cmd .= "$file 2>&1"; -      	 -      	// Execute command -      	$result = shell_exec($cmd); -      	$result = explode("\n", $result); -      	for($i=2, $size=count($result); $i<($size-1); $i++) { -	  $this->counter++; -	  $this->log($result[$i], PROJECT_MSG_WARN); -      	} -      } else { -      	throw new BuildException('Permission denied: '.$file); -      } -    } else { -      throw new BuildException('File not found: '.$file); +    /** +     * Analyze file +     * +     * @param string $file +     * @return void +     */ +    protected function analyze($file) { +        if(file_exists($file)) { +            if(is_readable($file)) { +                // Construct shell command +                $cmd = $this->analyzerPath." "; +                 +                foreach($this->enable as $enable) { // Enable warning levels +                    $cmd .= " --enable $enable "; +                } +                 +                foreach($this->disable as $disable) { // Disable warning levels +                    $cmd .= " --disable $disable "; +                } +                 +                $cmd .= "$file 2>&1"; + +                // Execute command +                $result = shell_exec($cmd); +                $result = explode("\n", $result); +                 +                for($i=2, $size=count($result); $i<($size-1); $i++) { +                    $this->counter++; +                    $this->log($result[$i], Project::MSG_WARN); +                } +                 +                $total = count($result) - 3; +                 +                if ($total > 0 && $this->haltonwarning) { +                    throw new BuildException('zendcodeanalyzer detected ' . $total . ' warning' . ($total > 1 ? 's' : '') . ' in ' . $file); +                } +            }  +            else +            { +                throw new BuildException('Permission denied: '.$file); +            } +        } else { +            throw new BuildException('File not found: '.$file); +        }      } -  }  } - -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php b/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php index 33ef16ae..72bf42fd 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ZipTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 6997b3f3abffedf1b2efabc40c3b2d012b2379cb $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,31 +23,48 @@ require_once 'phing/tasks/system/MatchingTask.php';  include_once 'phing/util/SourceFileScanner.php';  include_once 'phing/mappers/MergeMapper.php';  include_once 'phing/util/StringHelper.php'; -include_once 'phing/lib/Zip.php';  /** - * Creates a zip archive using PEAR Archive_Zip (which is presently unreleased - * and included with Phing). + * Creates a zip archive using PHP ZipArchive extension/   * - * @author    Michiel Rook <michiel@trendserver.nl> - * @version   $Revision: 1.2 $ + * @author    Michiel Rook <mrook@php.net> + * @version   $Id: 6997b3f3abffedf1b2efabc40c3b2d012b2379cb $   * @package   phing.tasks.ext   * @since     2.1.0   */  class ZipTask extends MatchingTask { +    /** +     * @var PhingFile +     */      private $zipFile; +     +    /** +     * @var PhingFile +     */      private $baseDir; - +     +    /** +     * Whether to include empty dirs in the archive. +     */ +    private $includeEmpty = true; +          private $filesets = array();      private $fileSetFiles = array();      /** +     * File path prefix in zip archive +     * +     * @var string +     */ +    private $prefix = null; + +    /**       * Add a new fileset.       * @return FileSet       */      public function createFileSet() { -        $this->fileset = new FileSet(); +        $this->fileset = new ZipFileSet();          $this->filesets[] = $this->fileset;          return $this->fileset;      } @@ -69,6 +86,27 @@ class ZipTask extends MatchingTask {      }      /** +     * Sets the file path prefix for file in the zip file. +     * +     * @param string $prefix Prefix +     * +     * @return void +     */ +    public function setPrefix($prefix) { +        $this->prefix = $prefix; +    } + +    /** +     * Set the include empty dirs flag. +     * @param  boolean  Flag if empty dirs should be tarred too +     * @return void +     * @access public +     */ +    public function setIncludeEmptyDirs($bool) { +        $this->includeEmpty = (boolean) $bool; +    } +     +    /**       * do the work       * @throws BuildException       */ @@ -93,13 +131,16 @@ class ZipTask extends MatchingTask {          try {              if ($this->baseDir !== null) {                  if (!$this->baseDir->exists()) { -                    throw new BuildException("basedir does not exist!", $this->getLocation()); +                    throw new BuildException("basedir '" . (string) $this->baseDir . "' does not exist!", $this->getLocation()); +                } +                 +                if (empty($this->filesets)) +                { +                    // add the main fileset to the list of filesets to process. +                    $mainFileSet = new ZipFileSet($this->fileset); +                    $mainFileSet->setDir($this->baseDir); +                    $this->filesets[] = $mainFileSet;                  } - -                // add the main fileset to the list of filesets to process. -                $mainFileSet = new FileSet($this->fileset); -                $mainFileSet->setDir($this->baseDir); -                $this->filesets[] = $mainFileSet;              }              if (empty($this->filesets)) { @@ -112,8 +153,7 @@ class ZipTask extends MatchingTask {              // fileset              $upToDate = true;              foreach($this->filesets as $fs) { -            	$ds = $fs->getDirectoryScanner($this->project); -            	$files = $ds->getIncludedFiles(); +                $files = $fs->getFiles($this->project, $this->includeEmpty);                  if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) {                      $upToDate = false;                  } @@ -125,33 +165,47 @@ class ZipTask extends MatchingTask {              }              if ($upToDate) { -                $this->log("Nothing to do: " . $this->zipFile->__toString() . " is up to date.", PROJECT_MSG_INFO); +                $this->log("Nothing to do: " . $this->zipFile->__toString() . " is up to date.", Project::MSG_INFO);                  return;              } -            $this->log("Building zip: " . $this->zipFile->__toString(), PROJECT_MSG_INFO); +            $this->log("Building zip: " . $this->zipFile->__toString(), Project::MSG_INFO); -            $zip = new Archive_Zip($this->zipFile->getAbsolutePath()); +            $zip = new ZipArchive(); +            $res = $zip->open($this->zipFile->getAbsolutePath(), ZIPARCHIVE::CREATE); -            foreach($this->filesets as $fs) {                                 -            	$ds = $fs->getDirectoryScanner($this->project); -            	$files = $ds->getIncludedFiles(); - -                // FIXME  -                // Current model is only adding directories implicitly.  This -                // won't add any empty directories.  Perhaps modify FileSet::getFiles() -                // to also include empty directories.  Not high priority, since non-inclusion -                // of empty dirs is probably not unexpected behavior for ZipTask. -                $fsBasedir = $fs->getDir($this->project); +            if ($res !== true) +            { +                throw new Exception("ZipArchive::open() failed with code " . $res); +            } +             +            foreach($this->filesets as $fs) { +                $fsBasedir = (null != $this->baseDir) ? $this->baseDir : +                                    $fs->getDir($this->project); +                 +                $files = $fs->getFiles($this->project, $this->includeEmpty); +                                  $filesToZip = array();                  for ($i=0, $fcount=count($files); $i < $fcount; $i++) {                      $f = new PhingFile($fsBasedir, $files[$i]); -                    $filesToZip[] = $f->getAbsolutePath();                         -                }                     -                $zip->add($filesToZip, array('remove_path' => $fsBasedir->getPath())); + +                    $pathInZip = $this->prefix +                        . $f->getPathWithoutBase($fsBasedir); +                         +                    $pathInZip = str_replace('\\', '/', $pathInZip); +                     +                    if ($f->isDirectory()) { +                        if ($pathInZip != '.') { +                            $zip->addEmptyDir($pathInZip); +                        } +                    } else { +                        $zip->addFile($f->getPath(), $pathInZip); +                    } +                    $this->log("Adding " . $f->getPath() . " as " . $pathInZip . " to archive.", Project::MSG_VERBOSE); +                }              } -                          -                 +             +            $zip->close();          } catch (IOException $ioe) {                  $msg = "Problem creating ZIP: " . $ioe->getMessage();                  $this->filesets = $savedFileSets; @@ -174,3 +228,74 @@ class ZipTask extends MatchingTask {      }  } + + + + +/** + * This is a FileSet with the to specify permissions. + *  + * Permissions are currently not implemented by PEAR Archive_Tar, + * but hopefully they will be in the future. + *  + * @package phing.tasks.ext + */ +class ZipFileSet extends FileSet { + +    private $files = null; + +    /** +     *  Get a list of files and directories specified in the fileset. +     *  @return array a list of file and directory names, relative to +     *    the baseDir for the project. +     */ +    public function getFiles(Project $p, $includeEmpty = true) { +     +        if ($this->files === null) { +         +            $ds = $this->getDirectoryScanner($p); +            $this->files = $ds->getIncludedFiles(); +             +            // build a list of directories implicitly added by any of the files +            $implicitDirs = array(); +            foreach($this->files as $file) { +                $implicitDirs[] = dirname($file); +            } + +            $incDirs = $ds->getIncludedDirectories(); +             +            // we'll need to add to that list of implicit dirs any directories +            // that contain other *directories* (and not files), since otherwise +            // we get duplicate directories in the resulting tar +            foreach($incDirs as $dir) { +                foreach($incDirs as $dircheck) { +                    if (!empty($dir) && $dir == dirname($dircheck)) { +                        $implicitDirs[] = $dir; +                    } +                } +            } +             +            $implicitDirs = array_unique($implicitDirs); +             +            $emptyDirectories = array(); +             +            if ($includeEmpty) { +                // Now add any empty dirs (dirs not covered by the implicit dirs) +                // to the files array.  +                 +                foreach($incDirs as $dir) { // we cannot simply use array_diff() since we want to disregard empty/. dirs +                    if ($dir != "" && $dir != "." && !in_array($dir, $implicitDirs)) { +                        // it's an empty dir, so we'll add it. +                        $emptyDirectories[] = $dir; +                    } +                } +            } // if $includeEmpty +             +            $this->files = array_merge($implicitDirs, $emptyDirectories, $this->files); +            sort($this->files); +        } // if ($this->files===null) +         +        return $this->files; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/apigen/ApiGenTask.php b/buildscripts/phing/classes/phing/tasks/ext/apigen/ApiGenTask.php new file mode 100644 index 00000000..d8438b3e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/apigen/ApiGenTask.php @@ -0,0 +1,439 @@ +<?php +/* + * 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/Task.php'; + +/** + * ApiGen task (http://apigen.org). + * + * @package   phing.tasks.ext.apigen + * @author    Martin Srank <martin@smasty.net> + * @author    Jaroslav HanslÃk <kukulich@kukulich.cz> + * @since     2.4.10 + */ +class ApiGenTask extends Task +{ +    /** +     * Default ApiGen executable name. +     * +     * @var string +     */ +    private $executable = 'apigen'; + +    /** +     * Default options for ApiGen. +     * +     * @var array +     */ +    private $options = array( +        'progressbar' => false, +        'colors' => false, +        'update-check' => false +    ); + +    /** +     * Sets the ApiGen executable name. +     * +     * @param string $executable +     */ +    public function setExecutable($executable) +    { +        $this->executable = (string) $executable; +    } + +    /** +     * Sets the config file name. +     * +     * @param string $config +     */ +    public function setConfig($config) +    { +        $this->options['config'] = (string) $config; +    } + +    /** +     * Sets source files or directories. +     * +     * @param string $source +     */ +    public function setSource($source) +    { +        $this->options['source'] = explode(',', $source); +    } + +    /** +     * Sets the destination directory. +     * +     * @param string $destination +     */ +    public function setDestination($destination) +    { +        $this->options['destination'] = (string) $destination; +    } + +    /** +     * Sets list of allowed file extensions. +     * +     * @param string $extensions +     */ +    public function setExtensions($extensions) +    { +        $this->options['extensions'] = explode(',', $extensions); +    } + +    /** +     * Sets masks (case sensitive) to exclude files or directories from processing. +     * +     * @param string $exclude +     */ +    public function setExclude($exclude) +    { +        $this->options['exclude'] = explode(',', $exclude); +    } + +    /** +     * Sets masks to exclude elements from documentation generating. +     * +     * @param string $skipDocPath +     */ +    public function setSkipDocPath($skipDocPath) +    { +        $this->options['skip-doc-path'] = explode(',', $skipDocPath); +    } + +    /** +     * Sets a name prefix to exclude elements from documentation generating. +     * +     * @param string $skipDocPrefix +     */ +    public function setSkipDocPrefix($skipDocPrefix) +    { +        $this->options['skip-doc-prefix'] = explode(',', $skipDocPrefix); +    } + +    /** +     * Sets the character set of source files. +     * +     * @param string $charset +     */ +    public function setCharset($charset) +    { +        $this->options['charset'] = explode(',', $charset); +    } + +    /** +     * Sets the main project name prefix. +     * +     * @param string $main +     */ +    public function setMain($main) +    { +        $this->options['main'] = (string) $main; +    } + +    /** +     * Sets the title of generated documentation. +     * +     * @param string $title +     */ +    public function setTitle($title) +    { +        $this->options['title'] = (string) $title; +    } + +    /** +     * Sets the documentation base URL. +     * +     * @param string $baseUrl +     */ +    public function setBaseUrl($baseUrl) +    { +        $this->options['base-url'] = (string) $baseUrl; +    } + +    /** +     * Sets the Google Custom Search ID. +     * +     * @param string $googleCseId +     */ +    public function setGoogleCseId($googleCseId) +    { +        $this->options['google-cse-id'] = (string) $googleCseId; +    } + +    /** +     * Sets the Google Custom Search label. +     * +     * @param string $googleCseLabel +     */ +    public function setGoogleCseLabel($googleCseLabel) +    { +        $this->options['google-cse-label'] = (string) $googleCseLabel; +    } + +    /** +     * Sets the Google Analytics tracking code. +     * +     * @param string $googleAnalytics +     */ +    public function setGoogleAnalytics($googleAnalytics) +    { +        $this->options['google-analytics'] = (string) $googleAnalytics; +    } + +    /** +     * Sets the template config file name. +     * +     * @param string $templateConfig +     */ +    public function setTemplateConfig($templateConfig) +    { +        $this->options['template-config'] = (string) $templateConfig; +    } + +    /** +     * Sets a list of HTML tags allowed in the documentation. +     * +     * @param string $allowedHtml +     */ +    public function setAllowedHtml($allowedHtml) +    { +        $this->options['allowed-html'] = (string) $allowedHtml; +    } + +    /** +     * Sets how elements should be grouped in the menu. +     * +     * @param string $groups +     */ +    public function setGroups($groups) +    { +        $this->options['groups'] = (string) $groups; +    } + +    /** +     * Sets element types for search input autocomplete. +     * +     * @param string $autocomplete +     */ +    public function setAutocomplete($autocomplete) +    { +        $this->options['autocomplete'] = (string) $autocomplete; +    } + +    /** +     * Sets the element access levels. +     * +     * Documentation only for methods and properties with the given access level will be generated. +     * +     * @param string $accessLevels +     */ +    public function setAccessLevels($accessLevels) +    { +        $this->options['access-levels'] = (string) $accessLevels; +    } + +    /** +     * Sets if documentation for elements marked as internal and internal documentation parts should be generated. +     * +     * @param boolean $internal +     */ +    public function setInternal($internal) +    { +        $this->options['internal'] = (bool) $internal; +    } + +    /** +     * Sets if documentation for PHP internal classes should be generated. +     * +     * @param boolean $php +     */ +    public function setPhp($php) +    { +        $this->options['php'] = (bool) $php; +    } + +    /** +     * Sets if tree view of classes, interfaces, traits and exceptions should be generated. +     * +     * @param boolean $tree +     */ +    public function setTree($tree) +    { +        $this->options['tree'] = (bool) $tree; +    } + +    /** +     * Sets if documentation for deprecated elements should be generated. +     * +     * @param boolean $deprecated +     */ +    public function setDeprecated($deprecated) +    { +        $this->options['deprecated'] = (bool) $deprecated; +    } + +    /** +     * Sets if documentation of tasks should be generated. +     * +     * @param boolean $todo +     */ +    public function setTodo($todo) +    { +        $this->options['todo'] = (bool) $todo; +    } + +    /** +     * Sets if highlighted source code files should be generated. +     * +     * @param boolean $sourceCode +     */ +    public function setSourceCode($sourceCode) +    { +        $this->options['source-code'] = (bool) $sourceCode; +    } + +    /** +     * Sets if a link to download documentation as a ZIP archive should be generated. +     * +     * @param boolean $download +     */ +    public function setDownload($download) +    { +        $this->options['download'] = (bool) $download; +    } + +    /** +     * Sets a file name for checkstyle report of poorly documented elements. +     * +     * @param string $report +     */ +    public function setReport($report) +    { +        $this->options['report'] = (string) $report; +    } + +    /** +     * Sets if the destination directory should be wiped out first. +     * +     * @param boolean $wipeout +     */ +    public function setWipeout($wipeout) +    { +        $this->options['wipeout'] = (bool) $wipeout; +    } + +    /** +     * Enables/disables scaning and generating messages. +     * +     * @param boolean $quiet +     */ +    public function setQuiet($quiet) +    { +        $this->options['quiet'] = (bool) $quiet; +    } + +    /** +     * Enables/disables the check for ApiGen updates. +     * +     * @param boolean $updateCheck +     */ +    public function setUpdateCheck($updateCheck) +    { +        $this->options['update-check'] = (bool) $updateCheck; +    } + +    /** +     * Enables/disables the debug mode. +     * +     * @param boolean $debug +     */ +    public function setDebug($debug) +    { +        $this->options['debug'] = (bool) $debug; +    } + +    /** +     * Runs ApiGen. +     * +     * @throws BuildException If something is wrong. +     * @see Task::main() +     */ +    public function main() +    { +        if ('apigen' !== $this->executable && !is_file($this->executable)) { +            throw new BuildException(sprintf('Executable %s not found', $this->executable), $this->getLocation()); +        } + +        if (!empty($this->options['config'])) { +            // Config check +            if (!is_file($this->options['config'])) { +                throw new BuildException(sprintf('Config file %s doesn\'t exist', $this->options['config']), $this->getLocation()); +            } +        } else { +            // Source check +            if (empty($this->options['source'])) { +                throw new BuildException('Source is not set', $this->getLocation()); +            } +            // Destination check +            if (empty($this->options['destination'])) { +                throw new BuildException('Destination is not set', $this->getLocation()); +            } +        } + +        // Source check +        if (!empty($this->options['source'])) { +            foreach ($this->options['source'] as $source) { +                if (!file_exists($source)) { +                    throw new BuildException(sprintf('Source %s doesn\'t exist', $source), $this->getLocation()); +                } +            } +        } + +        // Execute ApiGen +        exec(escapeshellcmd($this->executable) . ' ' . $this->constructArguments(), $output, $return); + +        $logType = 0 === $return ? Project::MSG_INFO : Project::MSG_ERR; +        foreach ($output as $line) { +            $this->log($line, $logType); +        } +    } + +    /** +     * Generates command line arguments for the ApiGen executable. +     * +     * @return string +     */ +    protected function constructArguments() +    { +        $args = array(); +        foreach ($this->options as $option => $value) { +            if (is_bool($value)) { +                $args[] = '--' . $option . '=' . ($value ? 'yes' : 'no'); +            } elseif (is_array($value)) { +                foreach ($value as $v) { +                    $args[] = '--' . $option . '=' . escapeshellarg($v); +                } +            } else { +                $args[] = '--' . $option . '=' . escapeshellarg($value); +            } +        } +        return implode(' ', $args); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php index 99bcc7c4..71eba460 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: CoverageMerger.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 83f3748d0690f9fc69c2618191f272e5661c0501 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,104 +24,131 @@ require_once 'phing/system/util/Properties.php';  /**   * Saves coverage output of the test to a specified database   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageMerger.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 83f3748d0690f9fc69c2618191f272e5661c0501 $   * @package phing.tasks.ext.coverage   * @since 2.1.0   */  class CoverageMerger  { -	private static function mergeCodeCoverage($left, $right) -	{ -		$coverageMerged = array(); +    private static function mergeCodeCoverage($left, $right) +    { +        $coverageMerged = array(); -		reset($left); -		reset($right); +        reset($left); +        reset($right); -		while (current($left) && current($right)) -		{ -			$linenr_left = key($left); -			$linenr_right = key($right); +        while (current($left) !== false && current($right) !== false) { +            $linenr_left = key($left); +            $linenr_right = key($right); -			if ($linenr_left < $linenr_right) -			{ -				$coverageMerged[$linenr_left] = current($left); +            if ($linenr_left < $linenr_right) { +                $coverageMerged[$linenr_left] = current($left); +                next($left); +            } elseif ($linenr_right < $linenr_left) { +                $coverageMerged[$linenr_right] = current($right); +                next($right); +            } else { +                if ((current($left) < 0) || (current($right) < 0)) { +                    $coverageMerged[$linenr_right] = current($right); +                } else { +                    $coverageMerged[$linenr_right] = current($left) + current($right); +                } +                 +                next($left); +                next($right); +            } +        } -				next($left); -			} -			else -			if ($linenr_right < $linenr_left) -			{ -				$coverageMerged[$linenr_right] = current($right); -				next($right); -			} -			else -			{ -				if (current($left) < 0) -				{ -					$coverageMerged[$linenr_right] = current($right); -				} -				else -				if (current($right) < 0) -				{ -					$coverageMerged[$linenr_right] = current($left); -				} -				else -				{ -					$coverageMerged[$linenr_right] = current($left) + current($right); -				} -				 -				next($left); -				next($right); -			} -		} +        while (current($left) !== false) { +            $coverageMerged[key($left)] = current($left); +            next($left); +        } -		while (current($left)) -		{ -			$coverageMerged[key($left)] = current($left); -			next($left); -		} +        while (current($right) !== false) { +            $coverageMerged[key($right)] = current($right); +            next($right); +        } -		while (current($right)) -		{ -			$coverageMerged[key($right)] = current($right); -			next($right); -		} +        return $coverageMerged; +    } +     +    /** +     * @param  Project $project +     * @return Properties +     * @throws BuildException +     */ +    protected static function _getDatabase($project) +    { +        $coverageDatabase = $project->getProperty('coverage.database'); +         +        if (!$coverageDatabase) { +            throw new BuildException("Property coverage.database is not set - please include coverage-setup in your build file"); +        } +         +        $database = new PhingFile($coverageDatabase); -		return $coverageMerged; -	} +        $props = new Properties(); +        $props->load($database); +         +        return $props; +    } +     +    public static function getWhiteList($project) +    { +        $whitelist = array(); +        $props = self::_getDatabase($project); +         +        foreach ($props->getProperties() as $property) { +            $data = unserialize($property); +            $whitelist[] = $data['fullname']; +        } +         +        return $whitelist; +    } -	static function merge($project, $codeCoverageInformation) -	{ -		$database = new PhingFile($project->getProperty('coverage.database')); +    public static function merge($project, $codeCoverageInformation) +    { +        $props = self::_getDatabase($project); +         +        $coverageTotal = $codeCoverageInformation; +         +        foreach ($coverageTotal as $filename => $data) { +            $ignoreLines = PHP_CodeCoverage_Util::getLinesToBeIgnored($filename); +             +            $lines = array(); +            $filename = strtolower($filename); -		$props = new Properties(); -		$props->load($database); -		 -		$coverageTotal = $codeCoverageInformation; -		 -		foreach ($coverageTotal as $coverage) -		{ -			foreach ($coverage as $filename => $coverageFile) -			{ -				$filename = strtolower($filename); -				 -				if ($props->getProperty($filename) != null) -				{ -					$file = unserialize($props->getProperty($filename)); -					$left = $file['coverage']; -					$right = $coverageFile; -					 -					$coverageMerged = CoverageMerger::mergeCodeCoverage($left, $right); -					 -					$file['coverage'] = $coverageMerged; -					 -					$props->setProperty($filename, serialize($file)); -				} -			} -		} +            if ($props->getProperty($filename) != null) { +                foreach ($data as $_line => $_data) { +                    if (is_array($_data)) { +                        $count = count($_data); +                    } else if(isset($ignoreLines[$_line])) { +                    	// line is marked as ignored +                    	$count = 1; +                    } else if ($_data == -1) { +                        // not executed +                        $count = -1; +                    } else if ($_data == -2) { +                        // dead code +                        $count = -2; +                    } -		$props->store($database); -	} -} -?>
\ No newline at end of file +                    $lines[$_line] = $count; +                } + +                ksort($lines); + +                $file = unserialize($props->getProperty($filename)); +                $left = $file['coverage']; + +                $coverageMerged = CoverageMerger::mergeCodeCoverage($left, $lines); + +                $file['coverage'] = $coverageMerged; +                $props->setProperty($filename, serialize($file)); +            }            +        } + +        $props->store(); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php index 4a78df6f..fd141cb5 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: CoverageMergerTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 324ec42a8015e3b82e90ee3bfaad1bc069fec409 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,65 +28,65 @@ require_once 'phing/tasks/ext/coverage/CoverageMerger.php';  /**   * Merges code coverage snippets into a code coverage database   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageMergerTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 324ec42a8015e3b82e90ee3bfaad1bc069fec409 $   * @package phing.tasks.ext.coverage   * @since 2.1.0   */  class CoverageMergerTask extends Task  { -	/** the list of filesets containing the .php filename rules */ -	private $filesets = array(); +    /** the list of filesets containing the .php filename rules */ +    private $filesets = array(); -	/** -	 * Add a new fileset containing the .php files to process -	 * -	 * @param FileSet the new fileset containing .php files -	 */ -	function addFileSet(FileSet $fileset) -	{ -		$this->filesets[] = $fileset; -	} +    /** +     * Add a new fileset containing the .php files to process +     * +     * @param FileSet the new fileset containing .php files +     */ +    function addFileSet(FileSet $fileset) +    { +        $this->filesets[] = $fileset; +    } -	/** -	 * Iterate over all filesets and return all the filenames. -	 * -	 * @return array an array of filenames -	 */ -	private function getFilenames() -	{ -		$files = array(); +    /** +     * Iterate over all filesets and return all the filenames. +     * +     * @return array an array of filenames +     */ +    private function getFilenames() +    { +        $files = array(); -		foreach ($this->filesets as $fileset) -		{ -			$ds = $fileset->getDirectoryScanner($this->project); -			$ds->scan(); +        foreach ($this->filesets as $fileset) +        { +            $ds = $fileset->getDirectoryScanner($this->project); +            $ds->scan(); -			$includedFiles = $ds->getIncludedFiles(); -			 -			foreach ($includedFiles as $file) -			{ -				$fs = new PhingFile(basename($ds->getBaseDir()), $file); -					 -				$files[] = $fs->getAbsolutePath(); -			} -		} +            $includedFiles = $ds->getIncludedFiles(); +             +            foreach ($includedFiles as $file) +            { +                $fs = new PhingFile(basename($ds->getBaseDir()), $file); +                     +                $files[] = $fs->getAbsolutePath(); +            } +        } -		return $files; -	} -	 -	function main() -	{ -		$files = $this->getFilenames(); -		 -		$this->log("Merging " . count($files) . " coverage files"); +        return $files; +    } +     +    function main() +    { +        $files = $this->getFilenames(); +         +        $this->log("Merging " . count($files) . " coverage files"); -		foreach ($files as $file) -		{ -			$coverageInformation = unserialize(file_get_contents($file)); -			 -			CoverageMerger::merge($this->project, array($coverageInformation)); -		} -	} +        foreach ($files as $file) +        { +            $coverageInformation = unserialize(file_get_contents($file)); +             +            CoverageMerger::merge($this->project, array($coverageInformation)); +        } +    }  } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php index 72fa57a7..dbfc3093 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: CoverageReportTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 564bbde3ec5084ed2db570958548af2b9d1c1127 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,384 +23,542 @@ require_once 'phing/Task.php';  require_once 'phing/system/io/PhingFile.php';  require_once 'phing/system/io/Writer.php';  require_once 'phing/system/util/Properties.php'; -require_once 'phing/tasks/ext/phpunit2/PHPUnit2Util.php'; +require_once 'phing/tasks/ext/phpunit/PHPUnitUtil.php';  require_once 'phing/tasks/ext/coverage/CoverageReportTransformer.php';  /**   * Transforms information in a code coverage database to XML   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageReportTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 564bbde3ec5084ed2db570958548af2b9d1c1127 $   * @package phing.tasks.ext.coverage   * @since 2.1.0   */  class CoverageReportTask extends Task  { -	private $outfile = "coverage.xml"; +    private $outfile = "coverage.xml"; -	private $transformers = array(); +    private $transformers = array(); -	/** the classpath to use (optional) */ -	private $classpath = NULL; -	 -	/** the path to the GeSHi library (optional) */ -	private $geshipath = ""; -	 -	/** the path to the GeSHi language files (optional) */ -	private $geshilanguagespath = ""; -	 -	function setClasspath(Path $classpath) -	{ -		if ($this->classpath === null) -		{ -			$this->classpath = $classpath; -		} -		else -		{ -			$this->classpath->append($classpath); -		} -	} +    /** the classpath to use (optional) */ +    private $classpath = NULL; +     +    /** the path to the GeSHi library (optional) */ +    private $geshipath = ""; +     +    /** the path to the GeSHi language files (optional) */ +    private $geshilanguagespath = ""; +     +    function setClasspath(Path $classpath) +    { +        if ($this->classpath === null) +        { +            $this->classpath = $classpath; +        } +        else +        { +            $this->classpath->append($classpath); +        } +    } -	function createClasspath() -	{ -		$this->classpath = new Path(); -		return $this->classpath; -	} -	 -	function setGeshiPath($path) -	{ -		$this->geshipath = $path; -	} +    function createClasspath() +    { +        $this->classpath = new Path(); +        return $this->classpath; +    } +     +    function setGeshiPath($path) +    { +        $this->geshipath = $path; +    } -	function setGeshiLanguagesPath($path) -	{ -		$this->geshilanguagespath = $path; -	} +    function setGeshiLanguagesPath($path) +    { +        $this->geshilanguagespath = $path; +    } -	function __construct() -	{ -		$this->doc = new DOMDocument(); -		$this->doc->encoding = 'UTF-8'; -		$this->doc->formatOutput = true; -		$this->doc->appendChild($this->doc->createElement('snapshot')); -	} +    function __construct() +    { +        $this->doc = new DOMDocument(); +        $this->doc->encoding = 'UTF-8'; +        $this->doc->formatOutput = true; +        $this->doc->appendChild($this->doc->createElement('snapshot')); +    } -	function setOutfile($outfile) -	{ -		$this->outfile = $outfile; -	} +    function setOutfile($outfile) +    { +        $this->outfile = $outfile; +    } -	/** -	 * Generate a report based on the XML created by this task -	 */ -	function createReport() -	{ -		$transformer = new CoverageReportTransformer($this); -		$this->transformers[] = $transformer; -		return $transformer; -	} +    /** +     * Generate a report based on the XML created by this task +     */ +    function createReport() +    { +        $transformer = new CoverageReportTransformer($this); +        $this->transformers[] = $transformer; +        return $transformer; +    } -	protected function getPackageElement($packageName) -	{ -		$packages = $this->doc->documentElement->getElementsByTagName('package'); +    protected function getPackageElement($packageName) +    { +        $packages = $this->doc->documentElement->getElementsByTagName('package'); -		foreach ($packages as $package) -		{ -			if ($package->getAttribute('name') == $packageName) -			{ -				return $package; -			} -		} +        foreach ($packages as $package) +        { +            if ($package->getAttribute('name') == $packageName) +            { +                return $package; +            } +        } -		return NULL; -	} +        return NULL; +    } -	protected function addClassToPackage($classname, $element) -	{ -		$packageName = PHPUnit2Util::getPackageName($classname); +    protected function addClassToPackage($classname, $element) +    { +        $packageName = PHPUnitUtil::getPackageName($classname); -		$package = $this->getPackageElement($packageName); +        $package = $this->getPackageElement($packageName); -		if ($package === NULL) -		{ -			$package = $this->doc->createElement('package'); -			$package->setAttribute('name', $packageName); -			$this->doc->documentElement->appendChild($package); -		} +        if ($package === NULL) +        { +            $package = $this->doc->createElement('package'); +            $package->setAttribute('name', $packageName); +            $this->doc->documentElement->appendChild($package); +        } -		$package->appendChild($element); -	} +        $package->appendChild($element); +    } -	protected function stripDiv($source) -	{ -		$openpos = strpos($source, "<div"); -		$closepos = strpos($source, ">", $openpos); +    /** +     * Adds a subpackage to their package +     * +     * @param string $packageName    The name of the package +     * @param string $subpackageName The name of the subpackage +     * +     * @author Benjamin Schultz <bschultz@proqrent.de> +     * @return void +     */ +    protected function addSubpackageToPackage($packageName, $subpackageName) +    { +        $package    = $this->getPackageElement($packageName); +        $subpackage = $this->getSubpackageElement($subpackageName); -		$line = substr($source, $closepos + 1); +        if ($package === null) { +            $package = $this->doc->createElement('package'); +            $package->setAttribute('name', $packageName); +            $this->doc->documentElement->appendChild($package); +        } -		$tagclosepos = strpos($line, "</div>"); +        if ($subpackage === null) { +            $subpackage = $this->doc->createElement('subpackage'); +            $subpackage->setAttribute('name', $subpackageName); +        } -		$line = substr($line, 0, $tagclosepos); +        $package->appendChild($subpackage); +    } -		return $line; -	} +    /** +     * Returns the subpackage element +     * +     * @param string $subpackageName The name of the subpackage +     * +     * @author Benjamin Schultz <bschultz@proqrent.de> +     * @return DOMNode|null null when no DOMNode with the given name exists +     */ +    protected function getSubpackageElement($subpackageName) +    { +        $subpackages = $this->doc->documentElement->getElementsByTagName('subpackage'); -	protected function highlightSourceFile($filename) -	{ -		if ($this->geshipath) -		{ -			require_once $this->geshipath . '/geshi.php'; -			 -			$source = file_get_contents($filename); +        foreach ($subpackages as $subpackage) { +            if ($subpackage->getAttribute('name') == $subpackageName) { +                return $subpackage; +            } +        } -			$geshi = new GeSHi($source, 'php', $this->geshilanguagespath); +        return null; +    } -			$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); +    /** +     * Adds a class to their subpackage +     * +     * @param string  $classname The name of the class +     * @param DOMNode $element   The dom node to append to the subpackage element +     * +     * @author Benjamin Schultz <bschultz@proqrent.de> +     * @return void +     */ +    protected function addClassToSubpackage($classname, $element) +    { +        $subpackageName = PHPUnitUtil::getSubpackageName($classname); -			$geshi->enable_strict_mode(true); +        $subpackage = $this->getSubpackageElement($subpackageName); -			$geshi->enable_classes(true); +        if ($subpackage === null) { +            $subpackage = $this->doc->createElement('subpackage'); +            $subpackage->setAttribute('name', $subpackageName); +            $this->doc->documentElement->appendChild($subpackage); +        } -			$geshi->set_url_for_keyword_group(3, '');  +        $subpackage->appendChild($element); +    } -			$html = $geshi->parse_code(); +    protected function stripDiv($source) +    { +        $openpos = strpos($source, "<div"); +        $closepos = strpos($source, ">", $openpos); -			$lines = split("<li>|</li>", $html); +        $line = substr($source, $closepos + 1); -			// skip first and last line -			array_pop($lines); -			array_shift($lines); +        $tagclosepos = strpos($line, "</div>"); -			$lines = array_filter($lines); +        $line = substr($line, 0, $tagclosepos); -			$lines = array_map(array($this, 'stripDiv'), $lines); +        return $line; +    } -			return $lines; -		} -		else -		{ -			$lines = file($filename); -			 -			for ($i = 0; $i < count($lines); $i++) -			{ -				$line = $lines[$i]; -				 -				$line = rtrim($line); +    protected function highlightSourceFile($filename) +    { +        if ($this->geshipath) +        { +            require_once $this->geshipath . '/geshi.php'; +             +            $source = file_get_contents($filename); -				$lines[$i] = utf8_encode($line); -			} -			 -			return $lines; -		} -	} +            $geshi = new GeSHi($source, 'php', $this->geshilanguagespath); -	protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1) -	{ -		$sourceElement = $this->doc->createElement('sourcefile'); -		$sourceElement->setAttribute('name', basename($filename)); +            $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); -		$filelines = $this->highlightSourceFile($filename); +            $geshi->enable_strict_mode(true); -		$linenr = 1; +            $geshi->enable_classes(true); -		foreach ($filelines as $line) -		{ -			$lineElement = $this->doc->createElement('sourceline'); -			$lineElement->setAttribute('coveredcount', (isset($coverageInformation[$linenr]) ? $coverageInformation[$linenr] : '0')); +            $geshi->set_url_for_keyword_group(3, '');  -			if ($linenr == $classStartLine) -			{ -				$lineElement->setAttribute('startclass', 1); -			} +            $html = $geshi->parse_code(); -			$textnode = $this->doc->createTextNode($line); -			$lineElement->appendChild($textnode); +            $lines = preg_split("#</?li>#", $html); -			$sourceElement->appendChild($lineElement); +            // skip first and last line +            array_pop($lines); +            array_shift($lines); -			$linenr++; -		} +            $lines = array_filter($lines); -		return $sourceElement; -	} -	 -	protected function filterCovered($var) -	{ -		return ($var >= 0); -	} +            $lines = array_map(array($this, 'stripDiv'), $lines); -	protected function transformCoverageInformation($filename, $coverageInformation) -	{ -		$classes = PHPUnit2Util::getDefinedClasses($filename, $this->classpath); -		 -		if (is_array($classes)) -		{ -			foreach ($classes as $classname) -			{ -				$reflection = new ReflectionClass($classname); -				 -				$methods = $reflection->getMethods(); -				 -				$classElement = $this->doc->createElement('class'); -				$classElement->setAttribute('name', $reflection->getName()); -				 -				$this->addClassToPackage($reflection->getName(), $classElement); +            return $lines; +        } +        else +        { +            $lines = file($filename); +             +            for ($i = 0; $i < count($lines); $i++) +            { +                $line = $lines[$i]; +                 +                $line = rtrim($line); +                 +                if (function_exists('mb_check_encoding') && mb_check_encoding($line, 'UTF-8')) { +                	$lines[$i] = $line; +                } +                else if (function_exists('mb_convert_encoding')) +                { +                    $lines[$i] = mb_convert_encoding($line, 'UTF-8'); +                } +                else +                { +                    $lines[$i] = utf8_encode($line); +                } +            } +             +            return $lines; +        } +    } -				$classStartLine = $reflection->getStartLine(); -				 -				$methodscovered = 0; -				$methodcount = 0; -				 -				end($coverageInformation); -				unset($coverageInformation[key($coverageInformation)]); -				 -				// Strange PHP5 reflection bug, classes without parent class or implemented interfaces seem to start one line off -				if ($reflection->getParentClass() == NULL && count($reflection->getInterfaces()) == 0) -				{ -					unset($coverageInformation[$classStartLine + 1]); -				} -				else -				{ -					unset($coverageInformation[$classStartLine]); -				} -				 -				reset($coverageInformation);				 -				 -				foreach ($methods as $method) -				{ -					// PHP5 reflection considers methods of a parent class to be part of a subclass, we don't -					if ($method->getDeclaringClass()->getName() != $reflection->getName()) -					{ -						continue; -					} +    protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1) +    { +        $sourceElement = $this->doc->createElement('sourcefile'); +        $sourceElement->setAttribute('name', basename($filename)); +         +        /** +         * Add original/full filename to document +         */ +        $sourceElement->setAttribute('sourcefile', $filename); -					// small fix for XDEBUG_CC_UNUSED -					if (isset($coverageInformation[$method->getStartLine()])) -					{ -						unset($coverageInformation[$method->getStartLine()]); -					} +        $filelines = $this->highlightSourceFile($filename); -					if (isset($coverageInformation[$method->getEndLine()])) -					{ -						unset($coverageInformation[$method->getEndLine()]); -					} +        $linenr = 1; -					if ($method->isAbstract()) -					{ -						continue; -					} +        foreach ($filelines as $line) +        { +            $lineElement = $this->doc->createElement('sourceline'); +            $lineElement->setAttribute('coveredcount', (isset($coverageInformation[$linenr]) ? $coverageInformation[$linenr] : '0')); -					$linenr = key($coverageInformation); +            if ($linenr == $classStartLine) +            { +                $lineElement->setAttribute('startclass', 1); +            } -					while ($linenr < $method->getStartLine()) -					{ -						next($coverageInformation); -						$linenr = key($coverageInformation); -					} +            $textnode = $this->doc->createTextNode($line); +            $lineElement->appendChild($textnode); -					if (current($coverageInformation) > 0 && $method->getStartLine() <= $linenr && $linenr <= $method->getEndLine()) -					{ -						$methodscovered++; -					} +            $sourceElement->appendChild($lineElement); -					$methodcount++; -				} +            $linenr++; +        } -				$statementcount = count($coverageInformation); -				$statementscovered = count(array_filter($coverageInformation, array($this, 'filterCovered'))); +        return $sourceElement; +    } +     +    /** +     * Transforms the coverage information +     * +     * @param string $filename            The filename +     * @param array  $coverageInformation Array with covergae information +     * +     * @author Michiel Rook <mrook@php.net> +     * @author Benjamin Schultz <bschultz@proqrent.de> +     * @return void +     */ +    protected function transformCoverageInformation($filename, $coverageInformation) +    {    +        $classes = PHPUnitUtil::getDefinedClasses($filename, $this->classpath); +         +        if (is_array($classes)) +        { +            foreach ($classes as $classname) +            { +                $reflection = new ReflectionClass($classname); +                 +                $methods = $reflection->getMethods(); +                 +                $classElement = $this->doc->createElement('class'); +                $classElement->setAttribute('name', $reflection->getName()); +                 +                $packageName    = PHPUnitUtil::getPackageName($reflection->getName()); +                $subpackageName = PHPUnitUtil::getSubpackageName($reflection->getName()); -				$classElement->appendChild($this->transformSourceFile($filename, $coverageInformation, $classStartLine)); +                if ($subpackageName !== null) { +                    $this->addSubpackageToPackage($packageName, $subpackageName); +                    $this->addClassToSubpackage($reflection->getName(), $classElement); +                } else { +                $this->addClassToPackage($reflection->getName(), $classElement); +                } -				$classElement->setAttribute('methodcount', $methodcount); -				$classElement->setAttribute('methodscovered', $methodscovered); -				$classElement->setAttribute('statementcount', $statementcount); -				$classElement->setAttribute('statementscovered', $statementscovered); -				$classElement->setAttribute('totalcount', $methodcount + $statementcount); -				$classElement->setAttribute('totalcovered', $methodscovered + $statementscovered); -			} -		} -	} +                $classStartLine = $reflection->getStartLine(); +                 +                $methodscovered = 0; +                $methodcount = 0; +                 +                // Strange PHP5 reflection bug, classes without parent class or implemented interfaces seem to start one line off +                if ($reflection->getParentClass() == NULL && count($reflection->getInterfaces()) == 0) +                { +                    unset($coverageInformation[$classStartLine + 1]); +                } +                else +                { +                    unset($coverageInformation[$classStartLine]); +                } +                 +                // Remove out-of-bounds info +                unset($coverageInformation[0]); +                 +                reset($coverageInformation);                 +                 +                foreach ($methods as $method) +                { +                    // PHP5 reflection considers methods of a parent class to be part of a subclass, we don't +                    if ($method->getDeclaringClass()->getName() != $reflection->getName()) +                    { +                        continue; +                    } -	protected function calculateStatistics() -	{ -		$packages = $this->doc->documentElement->getElementsByTagName('package'); +                    // small fix for XDEBUG_CC_UNUSED +                    if (isset($coverageInformation[$method->getStartLine()])) +                    { +                        unset($coverageInformation[$method->getStartLine()]); +                    } -		$totalmethodcount = 0; -		$totalmethodscovered = 0; +                    if (isset($coverageInformation[$method->getEndLine()])) +                    { +                        unset($coverageInformation[$method->getEndLine()]); +                    } -		$totalstatementcount = 0; -		$totalstatementscovered = 0; +                    if ($method->isAbstract()) +                    { +                        continue; +                    } -		foreach ($packages as $package) -		{ -			$methodcount = 0; -			$methodscovered = 0; +                    $linenr = key($coverageInformation); -			$statementcount = 0; -			$statementscovered = 0; +                    while ($linenr !== null && $linenr < $method->getStartLine()) +                    { +                        next($coverageInformation); +                        $linenr = key($coverageInformation); +                    } -			$classes = $package->getElementsByTagName('class'); +                    $methodCoveredCount = 0; +                    $methodTotalCount = 0; +                     +                    $methodHasCoveredLine = false; -			foreach ($classes as $class) -			{ -				$methodcount += $class->getAttribute('methodcount'); -				$methodscovered += $class->getAttribute('methodscovered'); +                    while ($linenr !== null && $linenr <= $method->getEndLine()) { +                        $methodTotalCount++; +                        $methodHasCoveredLine = true; -				$statementcount += $class->getAttribute('statementcount'); -				$statementscovered += $class->getAttribute('statementscovered'); -			} +                        // set covered when CODE is other than -1 (not executed) +                        if ($coverageInformation[$linenr] > 0 || $coverageInformation[$linenr] == -2) { +                            $methodCoveredCount++; +                        } +                         +                        next($coverageInformation); +                        $linenr = key($coverageInformation); +                    } +                     +                    if (($methodTotalCount == $methodCoveredCount) && $methodHasCoveredLine) { +                        $methodscovered++; +                    } -			$package->setAttribute('methodcount', $methodcount); -			$package->setAttribute('methodscovered', $methodscovered); +                    $methodcount++; +                } -			$package->setAttribute('statementcount', $statementcount); -			$package->setAttribute('statementscovered', $statementscovered); +                $statementcount = count(array_filter( +                    $coverageInformation,  +                    create_function('$var', 'return ($var != -2);') +                )); +                 +                $statementscovered = count(array_filter( +                    $coverageInformation,  +                    create_function('$var', 'return ($var >= 0);') +                )); +                 +                $classElement->appendChild($this->transformSourceFile($filename, $coverageInformation, $classStartLine)); -			$package->setAttribute('totalcount', $methodcount + $statementcount); -			$package->setAttribute('totalcovered', $methodscovered + $statementscovered); +                $classElement->setAttribute('methodcount', $methodcount); +                $classElement->setAttribute('methodscovered', $methodscovered); +                $classElement->setAttribute('statementcount', $statementcount); +                $classElement->setAttribute('statementscovered', $statementscovered); +                $classElement->setAttribute('totalcount', $methodcount + $statementcount); +                $classElement->setAttribute('totalcovered', $methodscovered + $statementscovered); +            } +        } +    } -			$totalmethodcount += $methodcount; -			$totalmethodscovered += $methodscovered; +    protected function calculateStatistics() +    { +        $packages = $this->doc->documentElement->getElementsByTagName('package'); -			$totalstatementcount += $statementcount; -			$totalstatementscovered += $statementscovered; -		} +        $totalmethodcount = 0; +        $totalmethodscovered = 0; -		$this->doc->documentElement->setAttribute('methodcount', $totalmethodcount); -		$this->doc->documentElement->setAttribute('methodscovered', $totalmethodscovered); +        $totalstatementcount = 0; +        $totalstatementscovered = 0; -		$this->doc->documentElement->setAttribute('statementcount', $totalstatementcount); -		$this->doc->documentElement->setAttribute('statementscovered', $totalstatementscovered); +        foreach ($packages as $package) { +            $methodcount = 0; +            $methodscovered = 0; -		$this->doc->documentElement->setAttribute('totalcount', $totalmethodcount + $totalstatementcount); -		$this->doc->documentElement->setAttribute('totalcovered', $totalmethodscovered + $totalstatementscovered); -	} +            $statementcount = 0; +            $statementscovered = 0; -	function main() -	{ -		$this->log("Transforming coverage report"); -		 -		$database = new PhingFile($this->project->getProperty('coverage.database')); -		 -		$props = new Properties(); -		$props->load($database); +            $subpackages = $package->getElementsByTagName('subpackage'); -		foreach ($props->keys() as $filename) -		{ -			$file = unserialize($props->getProperty($filename)); +            foreach ($subpackages as $subpackage) { +                $subpackageMethodCount    = 0; +                $subpackageMethodsCovered = 0; -			$this->transformCoverageInformation($file['fullname'], $file['coverage']); -		} -		 -		$this->calculateStatistics(); +                $subpackageStatementCount    = 0; +                $subpackageStatementsCovered = 0; -		$this->doc->save($this->outfile); +                $subpackageClasses = $subpackage->getElementsByTagName('class'); -		foreach ($this->transformers as $transformer) -		{ -			$transformer->setXmlDocument($this->doc); -			$transformer->transform(); -		} -	} +                foreach ($subpackageClasses as $subpackageClass) { +                    $subpackageMethodCount    += $subpackageClass->getAttribute('methodcount'); +                    $subpackageMethodsCovered += $subpackageClass->getAttribute('methodscovered'); + +                    $subpackageStatementCount    += $subpackageClass->getAttribute('statementcount'); +                    $subpackageStatementsCovered += $subpackageClass->getAttribute('statementscovered'); +                } + +                $subpackage->setAttribute('methodcount', $subpackageMethodCount); +                $subpackage->setAttribute('methodscovered', $subpackageMethodsCovered); + +                $subpackage->setAttribute('statementcount', $subpackageStatementCount); +                $subpackage->setAttribute('statementscovered', $subpackageStatementsCovered); + +                $subpackage->setAttribute('totalcount', $subpackageMethodCount + $subpackageStatementCount); +                $subpackage->setAttribute('totalcovered', $subpackageMethodsCovered + $subpackageStatementsCovered); +            } + +            $classes = $package->getElementsByTagName('class'); + +            foreach ($classes as $class) { +                $methodcount += $class->getAttribute('methodcount'); +                $methodscovered += $class->getAttribute('methodscovered'); + +                $statementcount += $class->getAttribute('statementcount'); +                $statementscovered += $class->getAttribute('statementscovered'); +            } + +            $package->setAttribute('methodcount', $methodcount); +            $package->setAttribute('methodscovered', $methodscovered); + +            $package->setAttribute('statementcount', $statementcount); +            $package->setAttribute('statementscovered', $statementscovered); + +            $package->setAttribute('totalcount', $methodcount + $statementcount); +            $package->setAttribute('totalcovered', $methodscovered + $statementscovered); + +            $totalmethodcount += $methodcount; +            $totalmethodscovered += $methodscovered; + +            $totalstatementcount += $statementcount; +            $totalstatementscovered += $statementscovered; +        } + +        $this->doc->documentElement->setAttribute('methodcount', $totalmethodcount); +        $this->doc->documentElement->setAttribute('methodscovered', $totalmethodscovered); + +        $this->doc->documentElement->setAttribute('statementcount', $totalstatementcount); +        $this->doc->documentElement->setAttribute('statementscovered', $totalstatementscovered); + +        $this->doc->documentElement->setAttribute('totalcount', $totalmethodcount + $totalstatementcount); +        $this->doc->documentElement->setAttribute('totalcovered', $totalmethodscovered + $totalstatementscovered); +    } + +    function main() +    { +        $coverageDatabase = $this->project->getProperty('coverage.database'); +         +        if (!$coverageDatabase) +        { +            throw new BuildException("Property coverage.database is not set - please include coverage-setup in your build file"); +        } +         +        $database = new PhingFile($coverageDatabase); + +        $this->log("Transforming coverage report"); +         +        $props = new Properties(); +        $props->load($database); + +        foreach ($props->keys() as $filename) +        { +            $file = unserialize($props->getProperty($filename)); +             +            $this->transformCoverageInformation($file['fullname'], $file['coverage']); +        } +         +        $this->calculateStatistics(); + +        $this->doc->save($this->outfile); + +        foreach ($this->transformers as $transformer) +        { +            $transformer->setXmlDocument($this->doc); +            $transformer->transform(); +        } +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php index b7fee32f..cc37800f 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: CoverageReportTransformer.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c1667521b5959687560a1bf015905d627785a3c6 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,94 +28,149 @@ require_once 'phing/util/ExtendedFileStream.php';   * Transform a Phing/Xdebug code coverage xml report.   * The default transformation generates an html report in framed style.   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageReportTransformer.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: c1667521b5959687560a1bf015905d627785a3c6 $   * @package phing.tasks.ext.coverage   * @since 2.1.0   */  class CoverageReportTransformer  { -	private $task = NULL; -	private $styleDir = ""; -	private $toDir = ""; -	private $document = NULL; +    private $task = NULL; +    private $styleDir = ""; +     +    /** +     * @var PhingFile +     */ +    private $toDir = ""; +     +    private $document = NULL; -	function __construct(Task $task) -	{ -		$this->task = $task; -	} +    /** title of the project, used in the coverage report */ +    private $title = ""; +     +    /** +     * Whether to use the sorttable JavaScript library, defaults to false +     * See {@link http://www.kryogenix.org/code/browser/sorttable/)} +     * +     * @var boolean +     */ +    private $useSortTable = false; +     +    function __construct(Task $task) +    { +        $this->task = $task; +    } -	function setStyleDir($styleDir) -	{ -		$this->styleDir = $styleDir; -	} +    function setStyleDir($styleDir) +    { +        $this->styleDir = $styleDir; +    } -	function setToDir($toDir) -	{ -		$this->toDir = $toDir; -	} +    function setToDir(PhingFile $toDir) +    { +        $this->toDir = $toDir; +    } -	function setXmlDocument($document) -	{ -		$this->document = $document; -	} +    function setXmlDocument($document) +    { +        $this->document = $document; +    } -	function transform() -	{ -        $dir = new PhingFile($this->toDir); +    /** +     * Setter for title parameter +     */ +    function setTitle($title) { +        $this->title = $title; +    } -        if (!$dir->exists()) +    /** +     * Sets whether to use the sorttable JavaScript library, defaults to false +     * See {@link http://www.kryogenix.org/code/browser/sorttable/)} +     * +     * @param boolean $useSortTable +     */ +    public function setUseSortTable($useSortTable) +    { +        $this->useSortTable = (boolean) $useSortTable; +    } +     +    function transform() +    { +        if (!$this->toDir->exists())          {              throw new BuildException("Directory '" . $this->toDir . "' does not exist");          } -		$xslfile = $this->getStyleSheet(); +        $xslfile = $this->getStyleSheet(); -		$xsl = new DOMDocument(); -		$xsl->load($xslfile->getAbsolutePath()); +        $xsl = new DOMDocument(); +        $xsl->load($xslfile->getAbsolutePath()); -		$proc = new XSLTProcessor(); -		$proc->importStyleSheet($xsl); +        $proc = new XSLTProcessor(); +        if (defined('XSL_SECPREF_WRITE_FILE')) +        { +            if (version_compare(PHP_VERSION,'5.4',"<")) +            { +                ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); +            } +            else +            { +                $proc->setSecurityPrefs(XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); +            } +        } +         +        $proc->importStyleSheet($xsl); -		ExtendedFileStream::registerStream(); +        ExtendedFileStream::registerStream(); -		// no output for the framed report -		// it's all done by extension... -		$proc->setParameter('', 'output.dir', $dir->getAbsolutePath()); -		$proc->transformToXML($this->document); -	} +        $toDir = (string) $this->toDir; +             +        // urlencode() the path if we're on Windows +        if (FileSystem::getFileSystem()->getSeparator() == '\\') { +            $toDir = urlencode($toDir); +        } -	private function getStyleSheet() -	{ -		$xslname = "coverage-frames.xsl"; +        // no output for the framed report +        // it's all done by extension... +        $proc->setParameter('', 'output.dir', $toDir); -		if ($this->styleDir) -		{ -			$file = new PhingFile($this->styleDir, $xslname); -		} -		else -		{ -			$path = Phing::getResourcePath("phing/etc/$xslname"); -			 -			if ($path === NULL) -			{ -				$path = Phing::getResourcePath("etc/$xslname"); +        $proc->setParameter('', 'output.sorttable', $this->useSortTable); +        $proc->setParameter('', 'document.title', $this->title); +        $proc->transformToXML($this->document); +         +        ExtendedFileStream::unregisterStream(); +    } -				if ($path === NULL) -				{ -					throw new BuildException("Could not find $xslname in resource path"); -				} -			} -			 -			$file = new PhingFile($path); -		} +    private function getStyleSheet() +    { +        $xslname = "coverage-frames.xsl"; -		if (!$file->exists()) -		{ -			throw new BuildException("Could not find file " . $file->getPath()); -		} +        if ($this->styleDir) +        { +            $file = new PhingFile($this->styleDir, $xslname); +        } +        else +        { +            $path = Phing::getResourcePath("phing/etc/$xslname"); +             +            if ($path === NULL) +            { +                $path = Phing::getResourcePath("etc/$xslname"); + +                if ($path === NULL) +                { +                    throw new BuildException("Could not find $xslname in resource path"); +                } +            } +             +            $file = new PhingFile($path); +        } + +        if (!$file->exists()) +        { +            throw new BuildException("Could not find file " . $file->getPath()); +        } -		return $file; -	} +        return $file; +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php index 058b891b..889a9042 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: CoverageSetupTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: da84ff4b224cdf3a8061e02d782320ccc492c253 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,136 +28,137 @@ require_once 'phing/tasks/ext/coverage/CoverageMerger.php';  /**   * Initializes a code coverage database   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageSetupTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: da84ff4b224cdf3a8061e02d782320ccc492c253 $   * @package phing.tasks.ext.coverage   * @since 2.1.0   */  class CoverageSetupTask extends Task  { -	/** the list of filesets containing the .php filename rules */ -	private $filesets = array(); +    /** the list of filesets containing the .php filename rules */ +    private $filesets = array(); -	/** the filename of the coverage database */ -	private $database = "coverage.db"; +    /** Any filelists of files containing the .php filenames */ +    private $filelists = array(); -	/** the classpath to use (optional) */ -	private $classpath = NULL; +    /** the filename of the coverage database */ +    private $database = "coverage.db"; -	/** -	 * Add a new fileset containing the .php files to process -	 * -	 * @param FileSet the new fileset containing .php files -	 */ -	function addFileSet(FileSet $fileset) -	{ -		$this->filesets[] = $fileset; -	} +    /** the classpath to use (optional) */ +    private $classpath = NULL; -	/** -	 * Sets the filename of the coverage database to use -	 * -	 * @param string the filename of the database -	 */ -	function setDatabase($database) -	{ -		$this->database = $database; -	} +    /** +     * Add a new fileset containing the .php files to process +     * +     * @param FileSet the new fileset containing .php files +     */ +    function addFileSet(FileSet $fileset) +    { +        $this->filesets[] = $fileset; +    } -	function setClasspath(Path $classpath) -	{ -		if ($this->classpath === null) -		{ -			$this->classpath = $classpath; -		} -		else -		{ -			$this->classpath->append($classpath); -		} -	} +    /** +     * Supports embedded <filelist> element. +     * @return FileList +     */ +    function createFileList() { +        $num = array_push($this->filelists, new FileList()); +        return $this->filelists[$num-1]; +    } -	function createClasspath() -	{ -		$this->classpath = new Path(); -		return $this->classpath; -	} -	 -	/** -	 * Iterate over all filesets and return the filename of all files -	 * that end with .php. This is to avoid loading an xml file -	 * for example. -	 * -	 * @return array an array of (basedir, filenames) pairs -	 */ -	private function getFilenames() -	{ -		$files = array(); +    /** +     * Sets the filename of the coverage database to use +     * +     * @param string the filename of the database +     */ +    function setDatabase($database) +    { +        $this->database = $database; +    } -		foreach ($this->filesets as $fileset) -		{ -			$ds = $fileset->getDirectoryScanner($this->project); -			$ds->scan(); +    function setClasspath(Path $classpath) +    { +        if ($this->classpath === null) +        { +            $this->classpath = $classpath; +        } +        else +        { +            $this->classpath->append($classpath); +        } +    } -			$includedFiles = $ds->getIncludedFiles(); +    function createClasspath() +    { +        $this->classpath = new Path(); +        return $this->classpath; +    } +     +    /** +     * Iterate over all filesets and return the filename of all files. +     * +     * @return array an array of (basedir, filenames) pairs +     */ +    private function getFilenames() +    { +        $files = array(); -			foreach ($includedFiles as $file) -			{ -				if (strstr($file, ".php")) -				{ -					$fs = new PhingFile(realpath($ds->getBaseDir()), $file); -					 -					$files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); -				} -			} -		} +        foreach($this->filelists as $fl) { +            try { +                $list = $fl->getFiles($this->project); +                foreach($list as $file) { +                    $fs = new PhingFile(strval($fl->getDir($this->project)), $file); +                    $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); +                } +            } catch (BuildException $be) { +                $this->log($be->getMessage(), Project::MSG_WARN); +            } +        } -		return $files; -	} -	 -	function init() -	{ -		include_once 'PHPUnit2/Framework/TestCase.php'; -		if (!class_exists('PHPUnit2_Framework_TestCase')) { -			throw new Exception("PHPUnit2Task depends on PEAR PHPUnit2 package being installed."); -		} -	} -	function main() -	{ -		$files = $this->getFilenames(); +        foreach ($this->filesets as $fileset) +        { +            $ds = $fileset->getDirectoryScanner($this->project); +            $ds->scan(); -		$this->log("Setting up coverage database for " . count($files) . " files"); +            $includedFiles = $ds->getIncludedFiles(); -		$props = new Properties(); +            foreach ($includedFiles as $file) +            { +                $fs = new PhingFile(realpath($ds->getBaseDir()), $file); +                     +                $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); +            } +        } -		foreach ($files as $file) -		{ -			$fullname = $file['fullname']; -			$filename = $file['key']; -			 -			$props->setProperty($filename, serialize(array('fullname' => $fullname, 'coverage' => array()))); -		} +        return $files; +    } +     +    function init() +    { +    } -		$dbfile = new PhingFile($this->database); +    function main() +    { +        $files = $this->getFilenames(); -		$props->store($dbfile); +        $this->log("Setting up coverage database for " . count($files) . " files"); -		$this->project->setProperty('coverage.database', $dbfile->getAbsolutePath()); -	 -		foreach ($files as $file) -		{ -			$fullname = $file['fullname']; -			 -			xdebug_start_code_coverage(XDEBUG_CC_UNUSED); -			 -			Phing::__import($fullname, $this->classpath); -			 -			$coverage = xdebug_get_code_coverage(); -			 -			xdebug_stop_code_coverage(); -			 -			CoverageMerger::merge($this->project, array($coverage)); -		} -	} +        $props = new Properties(); + +        foreach ($files as $file) +        { +            $fullname = $file['fullname']; +            $filename = $file['key']; +             +            $props->setProperty($filename, serialize(array('fullname' => $fullname, 'coverage' => array()))); +        } + +        $dbfile = new PhingFile($this->database); + +        $props->store($dbfile); + +        $this->project->setProperty('coverage.database', $dbfile->getAbsolutePath()); +    }  } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageThresholdTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageThresholdTask.php new file mode 100644 index 00000000..d9afbb00 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageThresholdTask.php @@ -0,0 +1,458 @@ +<?php +/** + * $Id: ed00d6f1d05bb5dc7c9967c9ec67fa6f958682ec $ + * + * 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/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/util/Properties.php'; +require_once 'phing/types/Excludes.php'; + +/** + * Stops the build if any of the specified coverage threshold was not reached + * + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: ed00d6f1d05bb5dc7c9967c9ec67fa6f958682ec $ + * @package phing.tasks.ext.coverage + * @since   2.4.1 + */ +class CoverageThresholdTask extends Task +{ +    /** +     * Holds an optional classpath +     * +     * @var Path +     */ +    private $_classpath = null; + +    /** +     * Holds the exclusions +     * +     * @var Excludes +     */ +    private $_excludes = null; + +    /** +     * Holds an optional database file +     * +     * @var PhingFile +     */ +    private $_database = null; + +    /** +     * Holds the coverage threshold for the entire project +     * +     * @var integer +     */ +    private $_perProject = 25; + +    /** +     * Holds the coverage threshold for any class +     * +     * @var integer +     */ +    private $_perClass = 25; + +    /** +     * Holds the coverage threshold for any method +     * +     * @var integer +     */ +    private $_perMethod = 25; + +    /** +     * Holds the minimum found coverage value for a class +     * +     * @var integer +     */ +    private $_minClassCoverageFound = null; + +    /** +     * Holds the minimum found coverage value for a method +     * +     * @var integer +     */ +    private $_minMethodCoverageFound = null; + +    /** +     * Number of statements in the entire project +     * +     * @var integer +     */ +    private $_projectStatementCount = 0; + +    /** +     * Number of covered statements in the entire project +     * +     * @var integer +     */ +    private $_projectStatementsCovered = 0; + +    /** +     * Whether to enable detailed logging +     * +     * @var boolean +     */ +    private $_verbose = false; + +    /** +     * Sets an optional classpath +     * +     * @param Path $classpath The classpath +     */ +    public function setClasspath(Path $classpath) +    { +        if ($this->_classpath === null) { +            $this->_classpath = $classpath; +        } else { +            $this->_classpath->append($classpath); +        } +    } + +    /** +     * Sets the optional coverage database to use +     * +     * @param PhingFile The database file +     */ +    public function setDatabase(PhingFile $database) +    { +        $this->_database = $database; +    } + +    /** +     * Create classpath object +     * +     * @return Path +     */ +    public function createClasspath() +    { +        $this->classpath = new Path(); +        return $this->classpath; +    } + +    /** +     * Sets the coverage threshold for entire project +     * +     * @param integer $threshold Coverage threshold for entire project +     */ +    public function setPerProject($threshold) +    { +        $this->_perProject = $threshold; +    } + +    /** +     * Sets the coverage threshold for any class +     * +     * @param integer $threshold Coverage threshold for any class +     */ +    public function setPerClass($threshold) +    { +        $this->_perClass = $threshold; +    } + +    /** +     * Sets the coverage threshold for any method +     * +     * @param integer $threshold Coverage threshold for any method +     */ +    public function setPerMethod($threshold) +    { +        $this->_perMethod = $threshold; +    } + +    /** +     * Sets whether to enable detailed logging or not +     * +     * @param boolean $verbose +     */ +    public function setVerbose($verbose) +    { +        $this->_verbose = StringHelper::booleanValue($verbose); +    } + +    /** +     * Filter covered statements +     * +     * @param integer $var Coverage CODE/count +     * @return boolean +     */ +    protected function filterCovered($var) +    { +        return ($var >= 0 || $var === -2); +    } + +    /** +     * Create excludes object +     * +     * @return Excludes +     */ +    public function createExcludes() +    { +        $this->_excludes = new Excludes($this->project); +        return $this->_excludes; +    } + +    /** +     * Calculates the coverage threshold +     * +     * @param string $filename            The filename to analyse +     * @param array  $coverageInformation Array with coverage information +     */ +    protected function calculateCoverageThreshold($filename, $coverageInformation) +    { +        $classes = PHPUnitUtil::getDefinedClasses($filename, $this->_classpath); + +        if (is_array($classes)) { +            foreach ($classes as $className) { +                // Skip class if excluded from coverage threshold validation +                if ($this->_excludes !== null) { +                    if (in_array($className, $this->_excludes->getExcludedClasses())) { +                        continue; +                    } +                } + +                $reflection     = new ReflectionClass($className); +                $classStartLine = $reflection->getStartLine(); + +                // Strange PHP5 reflection bug, classes without parent class +                // or implemented interfaces seem to start one line off +                if ($reflection->getParentClass() === null +                    && count($reflection->getInterfaces()) === 0 +                ) { +                    unset($coverageInformation[$classStartLine + 1]); +                } else { +                    unset($coverageInformation[$classStartLine]); +                } + +                reset($coverageInformation); + +                $methods = $reflection->getMethods(); + +                foreach ($methods as $method) { +                    // PHP5 reflection considers methods of a parent class +                    // to be part of a subclass, we don't +                    if ($method->getDeclaringClass()->getName() != $reflection->getName()) { +                        continue; +                    } + +                    // Skip method if excluded from coverage threshold validation +                    if ($this->_excludes !== null) { +                        $excludedMethods = $this->_excludes->getExcludedMethods(); + +                        if (isset($excludedMethods[$className])) { +                            if (in_array($method->getName(), $excludedMethods[$className]) +                                || in_array($method->getName() . '()', $excludedMethods[$className]) +                            ) { +                                continue; +                            } +                        } +                    } + +                    $methodStartLine = $method->getStartLine(); +                    $methodEndLine   = $method->getEndLine(); + +                    // small fix for XDEBUG_CC_UNUSED +                    if (isset($coverageInformation[$methodStartLine])) { +                        unset($coverageInformation[$methodStartLine]); +                    } + +                    if (isset($coverageInformation[$methodEndLine])) { +                        unset($coverageInformation[$methodEndLine]); +                    } + +                    if ($method->isAbstract()) { +                        continue; +                    } + +                    $lineNr = key($coverageInformation); + +                    while ($lineNr !== null && $lineNr < $methodStartLine) { +                        next($coverageInformation); +                        $lineNr = key($coverageInformation); +                    } + +                    $methodStatementsCovered = 0; +                    $methodStatementCount    = 0; + +                    while ($lineNr !== null && $lineNr <= $methodEndLine) { +                        $methodStatementCount++; + +                        $lineCoverageInfo = $coverageInformation[$lineNr]; +                        // set covered when CODE is other than -1 (not executed) +                        if ($lineCoverageInfo > 0 || $lineCoverageInfo === -2) { +                            $methodStatementsCovered++; +                        } + +                        next($coverageInformation); +                        $lineNr = key($coverageInformation); +                    } + +                    if ($methodStatementCount > 0) { +                        $methodCoverage = (  $methodStatementsCovered +                                           / $methodStatementCount) * 100; +                    } else { +                        $methodCoverage = 0; +                    } + +                    if ($methodCoverage < $this->_perMethod +                        && !$method->isAbstract() +                    ) { +                        throw new BuildException( +                            'The coverage (' . round($methodCoverage, 2) . '%) ' +                            . 'for method "' . $method->getName() . '" is lower' +                            . ' than the specified threshold (' +                            . $this->_perMethod . '%), see file: "' +                            . $filename . '"' +                        ); +                    } elseif ($methodCoverage < $this->_perMethod +                              && $method->isAbstract() +                              && $this->_verbose === true +                    ) { +                        $this->log( +                            'Skipped coverage threshold for abstract method "' +                            . $method->getName() . '"' +                        ); +                    } + +                    // store the minimum coverage value for logging (see #466) +                    if ($this->_minMethodCoverageFound !== null) { +                        if ($this->_minMethodCoverageFound > $methodCoverage) { +                            $this->_minMethodCoverageFound = $methodCoverage; +                        } +                    } else { +                        $this->_minMethodCoverageFound = $methodCoverage; +                    } +                } + +                $classStatementCount    = count($coverageInformation); +                $classStatementsCovered = count( +                    array_filter( +                        $coverageInformation, +                        array($this, 'filterCovered') +                    ) +                ); + +                if ($classStatementCount > 0) { +                    $classCoverage = (  $classStatementsCovered +                                      / $classStatementCount) * 100; +                } else { +                    $classCoverage = 0; +                } + +                if ($classCoverage < $this->_perClass +                    && !$reflection->isAbstract() +                ) { +                    throw new BuildException( +                        'The coverage (' . round($classCoverage, 2) . '%) for class "' +                        . $reflection->getName() . '" is lower than the ' +                        . 'specified threshold (' . $this->_perClass . '%), ' +                        . 'see file: "' . $filename . '"' +                    ); +                } elseif ($classCoverage < $this->_perClass +                          && $reflection->isAbstract() +                          && $this->_verbose === true +                ) { +                    $this->log( +                        'Skipped coverage threshold for abstract class "' +                        . $reflection->getName() . '"' +                    ); +                } + +                // store the minimum coverage value for logging (see #466) +                if ($this->_minClassCoverageFound !== null) { +                    if ($this->_minClassCoverageFound > $classCoverage) { +                        $this->_minClassCoverageFound = $classCoverage; +                    } +                } else { +                    $this->_minClassCoverageFound = $classCoverage; +                } + +                $this->_projectStatementCount    += $classStatementCount; +                $this->_projectStatementsCovered += $classStatementsCovered; +            } +        } +    } + +    public function main() +    { +        if ($this->_database === null) { +            $coverageDatabase = $this->project +                                     ->getProperty('coverage.database'); + +            if (! $coverageDatabase) { +                throw new BuildException( +                    'Either include coverage-setup in your build file or set ' +                    . 'the "database" attribute' +                ); +            } + +            $database = new PhingFile($coverageDatabase); +        } else { +            $database = $this->_database; +        } + +        $this->log( +            'Calculating coverage threshold: min. ' +            . $this->_perProject . '% per project, ' +            . $this->_perClass . '% per class and ' +            . $this->_perMethod . '% per method is required' +        ); + +        $props = new Properties(); +        $props->load($database); + +        foreach ($props->keys() as $filename) { +            $file = unserialize($props->getProperty($filename)); + +            // Skip file if excluded from coverage threshold validation +            if ($this->_excludes !== null) { +                if (in_array($file['fullname'], $this->_excludes->getExcludedFiles())) { +                    continue; +                } +            } + +            $this->calculateCoverageThreshold( +                $file['fullname'], +                $file['coverage'] +            ); +        } + +        if ($this->_projectStatementCount > 0) { +            $coverage = (  $this->_projectStatementsCovered +                         / $this->_projectStatementCount) * 100; +        } else { +            $coverage = 0; +        } + +        if ($coverage < $this->_perProject) { +            throw new BuildException( +                'The coverage (' . round($coverage, 2) . '%) for the entire project ' +                . 'is lower than the specified threshold (' +                . $this->_perProject . '%)' +            ); +        } + +        $this->log( +            'Passed coverage threshold. Minimum found coverage values are: ' +            . round($coverage, 2) . '% per project, ' +            . round($this->_minClassCoverageFound, 2) . '% per class and ' +            . round($this->_minMethodCoverageFound, 2) . '% per method' +        ); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleSQLExecTask.php index d35e44f4..1ea3d5ba 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleSQLExecTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: CreoleSQLExecTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: f8f62d67a784faced2621d2ffc3b1c92e8703b05 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,7 +19,7 @@   * <http://phing.info>.   */ -require_once 'phing/tasks/ext/CreoleTask.php'; +require_once 'phing/tasks/ext/creole/CreoleTask.php';  include_once 'phing/system/io/StringReader.php';  /** @@ -48,8 +48,8 @@ include_once 'phing/system/io/StringReader.php';   * @author    Jeff Martin <jeff@custommonkey.org> (Ant)   * @author    Michael McCallum <gholam@xtra.co.nz> (Ant)   * @author    Tim Stephenson <tim.stephenson@sybase.com> (Ant) - * @package   phing.tasks.ext - * @version   $Revision: 1.21 $ + * @package   phing.tasks.ext.creole + * @version   $Id: f8f62d67a784faced2621d2ffc3b1c92e8703b05 $   */  class CreoleSQLExecTask extends CreoleTask { @@ -70,6 +70,11 @@ class CreoleSQLExecTask extends CreoleTask {      private $filesets = array();      /** +     * all filterchains objects assigned to this task +     */ +    private $filterChains  = array(); + +    /**       * SQL statement       */      private $statement = null; @@ -155,6 +160,17 @@ class CreoleSQLExecTask extends CreoleTask {      }      /** +     * Creates a filterchain +     * +     * @access public +     * @return  object  The created filterchain object +     */ +    function createFilterChain() { +        $num = array_push($this->filterChains, new FilterChain($this->project)); +        return $this->filterChains[$num-1]; +    } + +    /**       * Add a SQL transaction to execute       */      public function createTransaction() { @@ -303,7 +319,7 @@ class CreoleSQLExecTask extends CreoleTask {                  try {                      if ($this->output !== null) { -                        $this->log("Opening output file " . $this->output, PROJECT_MSG_VERBOSE); +                        $this->log("Opening output file " . $this->output, Project::MSG_VERBOSE);                          $out = new BufferedWriter(new FileWriter($this->output->getAbsolutePath(), $this->append));                      } @@ -311,7 +327,7 @@ class CreoleSQLExecTask extends CreoleTask {                      for ($i=0,$size=count($this->transactions); $i < $size; $i++) {                          $this->transactions[$i]->runTransaction($out);                          if (!$this->isAutocommit()) { -                            $this->log("Commiting transaction", PROJECT_MSG_VERBOSE); +                            $this->log("Commiting transaction", Project::MSG_VERBOSE);                              $this->conn->commit();                          }                      } @@ -357,9 +373,25 @@ class CreoleSQLExecTask extends CreoleTask {      public function runStatements(Reader $reader, $out = null) {          $sql = "";          $line = ""; -        $in = new BufferedReader($reader); -        try { + +        $buffer = ''; + +        if ((is_array($this->filterChains)) && (!empty($this->filterChains))) {     +            $in = FileUtils::getChainedReader(new BufferedReader($reader), $this->filterChains, $this->getProject()); +            while(-1 !== ($read = $in->read())) { // -1 indicates EOF +                   $buffer .= $read; +            } +            $lines = explode("\n", $buffer); +        } else { +            $in = new BufferedReader($reader); +              while (($line = $in->readLine()) !== null) { +                $lines[] = $line; +            } +        } + +        try { +            foreach ($lines as $line) {                  $line = trim($line);                  $line = ProjectConfigurator::replaceProperties($this->project, $line,                          $this->project->getProperties()); @@ -389,8 +421,8 @@ class CreoleSQLExecTask extends CreoleTask {                          && StringHelper::endsWith($this->delimiter, $sql)                          || $this->delimiterType == self::DELIM_ROW                          && $line == $this->delimiter) { -                    $this->log("SQL: " . $sql, PROJECT_MSG_VERBOSE); -                    $this->execSQL(StringHelper::substring($sql, 0, strlen($sql) - strlen($this->delimiter)) - 1, $out); +                    $this->log("SQL: " . $sql, Project::MSG_VERBOSE); +                    $this->execSQL(StringHelper::substring($sql, 0, strlen($sql) - strlen($this->delimiter)), $out);                      $sql = "";                  }              } @@ -418,7 +450,7 @@ class CreoleSQLExecTask extends CreoleTask {          try {              $this->totalSql++;              if (!$this->statement->execute($sql)) { -                $this->log($this->statement->getUpdateCount() . " rows affected", PROJECT_MSG_VERBOSE); +                $this->log($this->statement->getUpdateCount() . " rows affected", Project::MSG_VERBOSE);              } else {                  if ($this->print) {                      $this->printResults($out); @@ -428,27 +460,27 @@ class CreoleSQLExecTask extends CreoleTask {              $this->goodSql++;          } catch (SQLException $e) {             -            $this->log("Failed to execute: " . $sql, PROJECT_MSG_ERR); +            $this->log("Failed to execute: " . $sql, Project::MSG_ERR);              if ($this->onError != "continue") {                              throw new BuildException("Failed to execute SQL", $e);              } -            $this->log($e->getMessage(), PROJECT_MSG_ERR); +            $this->log($e->getMessage(), Project::MSG_ERR);          }      }      /**       * print any results in the statement. -     * @throw SQLException +     * @throws SQLException       */      protected function printResults($out = null) { -        $lSep = Phing::getProperty('line.separator'); +                  $rs = null;                  do {              $rs = $this->statement->getResultSet();              if ($rs !== null) { -                $this->log("Processing new result set.", PROJECT_MSG_VERBOSE);             +                $this->log("Processing new result set.", Project::MSG_VERBOSE);                              $line = ""; @@ -467,7 +499,7 @@ class CreoleSQLExecTask extends CreoleTask {                              $out->write($line);                              $out->newLine();                          } else { -                            print($line.$lSep); +                            print($line.PHP_EOL);                          }                          $line = "";                          $colsprinted = true; @@ -492,14 +524,14 @@ class CreoleSQLExecTask extends CreoleTask {                          $out->write($line);                          $out->newLine();                      } else {                     -                        print($line . $lSep); +                        print($line . PHP_EOL);                      }                      $line = "";                  } // while rs->next()              }          } while ($this->statement->getMoreResults()); -        print($lSep); +        print(PHP_EOL);          if ($out !== null) $out->newLine();      }  } @@ -510,6 +542,8 @@ class CreoleSQLExecTask extends CreoleTask {   * Transactions allow several files or blocks of statements   * to be executed using the same JDBC connection and commit   * operation in between. + * + * @package   phing.tasks.ext.creole   */  class SQLExecTransaction { @@ -539,14 +573,16 @@ class SQLExecTransaction {      public function runTransaction($out = null)      {          if (!empty($this->tSqlCommand)) { -            $this->parent->log("Executing commands", PROJECT_MSG_INFO); +            $this->parent->log("Executing commands", Project::MSG_INFO);              $this->parent->runStatements(new StringReader($this->tSqlCommand), $out);          }          if ($this->tSrcFile !== null) {              $this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(), -                PROJECT_MSG_INFO); +                Project::MSG_INFO); +              $reader = new FileReader($this->tSrcFile); +              $this->parent->runStatements($reader, $out);              $reader->close();          } diff --git a/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleTask.php index a1b439e5..6cff2033 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: CreoleTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 91a6dbbd682e6afa8befa95f01ae5fbaed11a72a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/types/Reference.php';   * @author    Jeff Martin <jeff@custommonkey.org> (Ant)   * @author    Michael McCallum <gholam@xtra.co.nz> (Ant)   * @author    Tim Stephenson <tim.stephenson@sybase.com> (Ant) - * @version   $Revision: 1.13 $ + * @version   $Id$   * @package   phing.tasks.system   */  abstract class CreoleTask extends Task { @@ -164,7 +164,7 @@ abstract class CreoleTask extends Task {          try { -            $this->log("Connecting to " . $this->getUrl(), PROJECT_MSG_VERBOSE); +            $this->log("Connecting to " . $this->getUrl(), Project::MSG_VERBOSE);              $info = new Properties();              $dsn = Creole::parseDSN($this->url); diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbDeployTask.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbDeployTask.php new file mode 100755 index 00000000..a5cc23ff --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbDeployTask.php @@ -0,0 +1,436 @@ +<?php +/* + *  $Id: 035d43c0c50ca9567e9c8a016fef6a3053164acb $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php'; + + +/** + * Generate SQL script for db using dbdeploy schema version table + * and delta scripts + * + * <dbdeploy url="mysql:host=localhost;dbname=test" + *     userid="dbdeploy" password="dbdeploy" dir="db" outputfile=""> + * + * @author   Luke Crouch at SourceForge (http://sourceforge.net) + * @version  $Id$ + * @package  phing.tasks.ext.dbdeploy + */ +class DbDeployTask extends Task +{ +    /** +     * The tablename to use from the database for storing all changes +     * This cannot be changed +     * +     * @var string +     */ +    public static $TABLE_NAME = 'changelog'; + +    /** +     * Connection string for the database connection +     * +     * @var string +     */ +    protected $url; + +    /** +     * The userid for the database connection +     * +     * @var string +     */ +    protected $userid; + +    /** +     * The password of the database user +     * +     * @var string +     */ +    protected $password; + +    /** +     * Path to the directory that holds the database patch files +     * +     * @var string +     */ +    protected $dir; + +    /** +     * Output file for performing all database patches of this deployment +     * Contains all the SQL statements that need to be executed +     * +     * @var string +     */ +    protected $outputFile = 'dbdeploy_deploy.sql'; + +    /** +     * Outputfile for undoing the database patches of this deployment +     * Contains all the SQL statements that need to be executed +     * +     * @var string +     */ +    protected $undoOutputFile = 'dbdeploy_undo.sql'; + +    /** +     * The deltaset that's being used +     * +     * @var string +     */ +    protected $deltaSet = 'Main'; + +    /** +     * The number of the last change to apply +     * +     * @var int +     */ +    protected $lastChangeToApply = 999; + +    /** +     * Contains the object for the DBMS that is used +     * +     * @var object +     */ +    protected $dbmsSyntax = null; + +    /** +     * Array with all change numbers that are applied already +     * +     * @var array +     */ +    protected $appliedChangeNumbers = array(); + +    /** +     * Checkall attribute +     * False means dbdeploy will only apply patches that have a higher number +     * than the last patchnumber that was applied +     * True means dbdeploy will apply all changes that aren't applied +     * already (in ascending order) +     * +     * @var int +     */ +    protected $checkall = false; + +    /** +     * The main function for the task +     * +     * @throws BuildException +     * @return void +     */ +    public function main() +    { +        try { +            // get correct DbmsSyntax object +            $dbms = substr($this->url, 0, strpos($this->url, ':')); +            $dbmsSyntaxFactory = new DbmsSyntaxFactory($dbms); +            $this->dbmsSyntax = $dbmsSyntaxFactory->getDbmsSyntax(); + +            // figure out which revisions are in the db already +            $this->appliedChangeNumbers = $this->getAppliedChangeNumbers(); +            $this->log('Current db revision: '.$this->getLastChangeAppliedInDb()); +            $this->log('Checkall: ' . $this->checkall); + +            $this->deploy(); + +        } catch (Exception $e) { +            throw new BuildException($e); +        } +    } + +    /** +     * Get the numbers of all the patches that are already applied according to +     * the changelog table in the database +     * +     * @return array +     */ +    protected function getAppliedChangeNumbers() +    { +        if (count($this->appliedChangeNumbers) == 0) { +            $this->log('Getting applied changed numbers from DB: ' . $this->url); +            $appliedChangeNumbers = array(); +            $dbh = new PDO($this->url, $this->userid, $this->password); +            $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +            $sql = "SELECT * +                    FROM " . DbDeployTask::$TABLE_NAME . " +                    WHERE delta_set = '$this->deltaSet' +                    ORDER BY change_number"; +            foreach ($dbh->query($sql) as $change) { +                $appliedChangeNumbers[] = $change['change_number']; +            } +            $this->appliedChangeNumbers = $appliedChangeNumbers; +        } +        return $this->appliedChangeNumbers; +    } + +    /** +     * Get the number of the last patch applied to the database +     * +     * @return int|mixed The highest patch number that is applied in the db +     */ +    protected function getLastChangeAppliedInDb() +    { +        return (count($this->appliedChangeNumbers) > 0) +                ? max($this->appliedChangeNumbers) : 0; +    } + +    /** +     * Create the deploy and undo deploy outputfiles +     * +     * @return void +     */ +    protected function deploy() +    { +        // create deploy outputfile +        $this->createOutputFile($this->outputFile, false); + +        // create undo deploy outputfile +        $this->createOutputFile($this->undoOutputFile, true); +    } + +    /** +     * Generate the sql for doing/undoing the deployment and write it to a file +     * +     * @param string $file +     * @param bool $undo +     * @return void +     */ +    protected function createOutputFile($file, $undo = false) +    { +        $fileHandle = fopen($file, "w+"); +        $sql = $this->generateSql($undo); +        fwrite($fileHandle, $sql); +    } + +    /** +     * Generate the sql for doing/undoing this deployment +     * +     * @param bool $undo +     * @return string The sql +     */ +    protected function generateSql($undo = false) +    { +        $sql = ''; +        $lastChangeAppliedInDb = $this->getLastChangeAppliedInDb(); +        $files = $this->getDeltasFilesArray(); +        $this->sortFiles($files, $undo); + +        foreach ($files as $fileChangeNumber => $fileName) { +            if ($this->fileNeedsToBeRead($fileChangeNumber, $lastChangeAppliedInDb)) { +                $sql .= '-- Fragment begins: ' . $fileChangeNumber . ' --' . "\n"; + +                if (!$undo) { +                    $sql .= 'INSERT INTO ' . DbDeployTask::$TABLE_NAME . ' +                                (change_number, delta_set, start_dt, applied_by, description)' . +                            ' VALUES (' . $fileChangeNumber . ', \'' . $this->deltaSet . '\', ' . +                                $this->dbmsSyntax->generateTimestamp() . +                                ', \'dbdeploy\', \'' . $fileName . '\');' . "\n"; +                } + +                // read the file +                $fullFileName = $this->dir . '/' . $fileName; +                $fh = fopen($fullFileName, 'r'); +                $contents = fread($fh, filesize($fullFileName)); +                // allow construct with and without space added +                $split = strpos($contents, '-- //@UNDO'); +                if ($split === false) +                    $split = strpos($contents, '--//@UNDO'); + +                if ($undo) { +                    $sql .= substr($contents, $split + 10) . "\n"; +                    $sql .= 'DELETE FROM ' . DbDeployTask::$TABLE_NAME . ' +	                         WHERE change_number = ' . $fileChangeNumber . ' +	                         AND delta_set = \'' . $this->deltaSet . '\';' . "\n"; +                } else { +                    $sql .= substr($contents, 0, $split); +                    $sql .= 'UPDATE ' . DbDeployTask::$TABLE_NAME . ' +	                         SET complete_dt = ' . $this->dbmsSyntax->generateTimestamp() . ' +	                         WHERE change_number = ' . $fileChangeNumber . ' +	                         AND delta_set = \'' . $this->deltaSet . '\';' . "\n"; +                } + +                $sql .= '-- Fragment ends: ' . $fileChangeNumber . ' --' . "\n"; +            } +        } + +        return $sql; +    } + +    /** +     * Get a list of all the patch files in the patch file directory +     * +     * @return array +     */ +    protected function getDeltasFilesArray() +    { +        $files = array(); +        $baseDir = realpath($this->dir); +        $dh = opendir($baseDir); +        $fileChangeNumberPrefix = ''; +        while (($file = readdir($dh)) !== false) { +            if (preg_match('[\d+]', $file, $fileChangeNumberPrefix)) { +                $files[intval($fileChangeNumberPrefix[0])] = $file; +            } +        } +        return $files; +    } + +    /** +     * Sort files in the patch files directory (ascending or descending depending on $undo boolean) +     * +     * @param array $files +     * @param bool $undo +     * @return void +     */ +    protected function sortFiles(&$files, $undo) +    { +        if ($undo) { +            krsort($files); +        } else { +            ksort($files); +        } +    } + +    /** +     * Determine if this patch file need to be deployed +     * (using fileChangeNumber, lastChangeAppliedInDb and $this->checkall) +     * +     * @param int $fileChangeNumber +     * @param string $lastChangeAppliedInDb +     * @return bool True or false if patch file needs to be deployed +     */ +    protected function fileNeedsToBeRead($fileChangeNumber, $lastChangeAppliedInDb) +    { +        if ($this->checkall) { +            return (!in_array($fileChangeNumber, $this->appliedChangeNumbers)); +        } else { +            return ($fileChangeNumber > $lastChangeAppliedInDb && $fileChangeNumber <= $this->lastChangeToApply); +        } +    } + +    /** +     * Set the url for the database connection +     * +     * @param string $url +     * @return void +     */ +    public function setUrl($url) +    { +        $this->url = $url; +    } + +    /** +     * Set the userid for the database connection +     * +     * @param string $userid +     * @return void +     */ +    public function setUserId($userid) +    { +        $this->userid = $userid; +    } + +    /** +     * Set the password for the database connection +     * +     * @param string $password +     * @return void +     */ +    public function setPassword($password) +    { +        $this->password = $password; +    } + +    /** +     * Set the directory where to find the patchfiles +     * +     * @param string $dir +     * @return void +     */ +    public function setDir($dir) +    { +        $this->dir = $dir; +    } + +    /** +     * Set the outputfile which contains all patch sql statements for this deployment +     * +     * @param string $outputFile +     * @return void +     */ +    public function setOutputFile($outputFile) +    { +        $this->outputFile = $outputFile; +    } + +    /** +     * Set the undo outputfile which contains all undo statements for this deployment +     * +     * @param string $undoOutputFile +     * @return void +     */ +    public function setUndoOutputFile($undoOutputFile) +    { +        $this->undoOutputFile = $undoOutputFile; +    } + +    /** +     * Set the lastchangetoapply property +     * +     * @param int $lastChangeToApply +     * @return void +     */ +    public function setLastChangeToApply($lastChangeToApply) +    { +        $this->lastChangeToApply = $lastChangeToApply; +    } + +    /** +     * Set the deltaset property +     * +     * @param string $deltaSet +     * @return void +     */ +    public function setDeltaSet($deltaSet) +    { +        $this->deltaSet = $deltaSet; +    } + +    /** +     * Set the checkall property +     * +     * @param bool $checkall +     * @return void +     */ +    public function setCheckAll($checkall) +    { +        $this->checkall = (int)$checkall; +    } + +    /** +     * Add a new fileset. +     * @return FileSet +     */ +    public function createFileSet() +    { +        $this->fileset = new FileSet(); +        $this->filesets[] = $this->fileset; +        return $this->fileset; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php new file mode 100755 index 00000000..f20d2df4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php @@ -0,0 +1,34 @@ +<?php +/* + *  $Id: 40826765e423da7500094b84f0025f75c8fdde87 $ + * + * 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>. + */ +  +/** + *  Utility class for generating necessary server-specific SQL commands + * + *  @author   Luke Crouch at SourceForge (http://sourceforge.net) + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ + +abstract class DbmsSyntax +{ +    public abstract function generateTimestamp(); +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php new file mode 100755 index 00000000..1cc163f5 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php @@ -0,0 +1,67 @@ +<?php +/* + *  $Id: 0efe41b73233dd4396055518a125e4ff642693c5 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/dbdeploy/DbmsSyntax.php'; + +/** + *  Factory for generating dbms-specific syntax-generating objects + * + *  @author   Luke Crouch at SourceForge (http://sourceforge.net) + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxFactory +{ +    private $dbms; +     +    public function __construct($dbms) +    { +        $this->dbms = $dbms; +    } +     +    public function getDbmsSyntax() +    { +        switch ($this->dbms){ +            case('sqlite') : +                require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php'; +                return new DbmsSyntaxSQLite(); +            case('mysql'): +                require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php'; +                return new DbmsSyntaxMysql(); +            case 'odbc': +            case('mssql'): +            case 'dblib': +                require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php'; +                return new DbmsSyntaxMsSql(); +            case('pgsql'): +                require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php'; +                return new DbmsSyntaxPgSQL(); +            case 'oci': +                require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php'; +                return new DbmsSyntaxOracle(); +            default: +                throw new Exception($this->dbms . ' is not supported by dbdeploy task.'); +        } +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php new file mode 100755 index 00000000..0b505d8e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php @@ -0,0 +1,37 @@ +<?php +/* + *  $Id: 10012c2626ef9befc8c18efa5898704e269d6164 $ + * + * 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>. + */ +  +/** + *  Utility class for generating necessary server-specific SQL commands + * + *  @author   Luke Crouch at SourceForge (http://sourceforge.net) + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxMsSql extends DbmsSyntax  +{ +    public function generateTimestamp() +    { +        return "DATEDIFF(s, '19700101', GETDATE())"; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php new file mode 100755 index 00000000..86bf8ae0 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php @@ -0,0 +1,37 @@ +<?php +/* + *  $Id: 3a8bab5e99f20e29f5c7dfe7d02f7a91fb8ccecd $ + * + * 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>. + */ +  +/** + *  Utility class for generating necessary server-specific SQL commands + * + *  @author   Luke Crouch at SourceForge (http://sourceforge.net) + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxMysql extends DbmsSyntax  +{ +    public function generateTimestamp() +    { +        return "NOW()"; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php new file mode 100755 index 00000000..15b0b0a0 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php @@ -0,0 +1,37 @@ +<?php +/* + *  $Id: be6f99d787b94f7f2c1c8e359def3d465386bba9 $ + * + * 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>. + */ +  +/** + *  Utility class for generating necessary server-specific SQL commands + * + *  @author   Luke Crouch at SourceForge (http://sourceforge.net) + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxOracle extends DbmsSyntax  +{ +    public function generateTimestamp() +    { +        return "(sysdate - to_date('01-JAN-1970','DD-MON-YYYY')) * (86400)"; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php new file mode 100755 index 00000000..6c07931c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php @@ -0,0 +1,36 @@ +<?php +/* + *  $Id: 17845f06b311dbe508e7cb1244cd849a1d3fcada $ + * + * 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>. + */ +  +/** + *  Utility class for generating necessary server-specific SQL commands + * + *  @author   R�my BREUILS + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ +class DbmsSyntaxPgSQL extends DbmsSyntax  +{ +    public function generateTimestamp() +    { +        return "NOW()"; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php new file mode 100755 index 00000000..32aa023e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php @@ -0,0 +1,37 @@ +<?php +/* + *  $Id: a48723b4c3ef1e5c15417f5ea6e495960e5e018b $ + * + * 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>. + */ +  +/** + *  Utility class for generating necessary server-specific SQL commands + * + *  @author   Luke Crouch at SourceForge (http://sourceforge.net) + *  @version  $Id$ + *  @package  phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxSQLite extends DbmsSyntax  +{ +    public function generateTimestamp() +    { +        return "strftime('%s','now')"; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/docblox/DocBloxTask.php b/buildscripts/phing/classes/phing/tasks/ext/docblox/DocBloxTask.php new file mode 100755 index 00000000..0c1556c8 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/docblox/DocBloxTask.php @@ -0,0 +1,221 @@ +<?php +/* + *  $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * + * 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/Task.php'; +require_once 'phing/system/io/FileOutputStream.php'; + +/** + * DocBlox Task (http://www.docblox-project.org) + * + * @author    Michiel Rook <mrook@php.net> + * @version   $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * @since     2.4.6 + * @package   phing.tasks.ext.docblox + */ +class DocBloxTask extends Task +{ +    /** +     * List of filesets +     * @var FileSet[] +     */ +    private $filesets = array(); +     +    /** +     * Destination/target directory +     * @var PhingFile +     */ +    private $destDir = null; + +    /** +     * name of the template to use +     * @var string +     */ +    private $template = "new_black"; +     +    /** +     * Title of the project +     * @var string +     */ +    private $title = ""; +     +    /** +     * Force DocBlox to be quiet +     * @var boolean +     */ +    private $quiet = true; +     +    /** +     * Nested creator, adds a set of files (nested fileset attribute). +     *  +     * @return FileSet +     */ +    public function createFileSet() +    { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } +     +    /** +     * Sets destination/target directory +     * @param PhingFile $destDir +     */ +    public function setDestDir(PhingFile $destDir) +    { +        $this->destDir = $destDir; +    } + +    /** +     * Convenience setter (@see setDestDir) +     * @param PhingFile $output +     */ +    public function setOutput(PhingFile $output) +    { +        $this->destDir = $output; +    } + +    /** +     * Sets the template to use +     * @param strings $template +     */ +    public function setTemplate($template) +    { +        $this->template = (string) $template; +    } +     +    /** +     * Sets the title of the project +     * @param strings $title +     */ +    public function setTitle($title) +    { +        $this->title = (string) $title; +    } +     +    /** +     * Forces DocBlox to be quiet +     * @param boolean $quiet +     */ +    public function setQuiet($quiet) +    { +        $this->quiet = (boolean) $quiet; +    } +     +    /** +     * Finds and initializes the DocBlox installation +     */ +    private function initializeDocBlox() +    { +        $docbloxPath = null; +         +        foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) { +            $testDocBloxPath = $path . DIRECTORY_SEPARATOR . 'DocBlox' . DIRECTORY_SEPARATOR . 'src'; + +            if (file_exists($testDocBloxPath)) { +                $docbloxPath = $testDocBloxPath; +            } +        } + +        if (empty($docbloxPath)) { +            throw new BuildException("Please make sure DocBlox is installed and on the include_path.", $this->getLocation()); +        } +         +        set_include_path($docbloxPath . PATH_SEPARATOR . get_include_path()); +         +        require_once $docbloxPath.'/DocBlox/Bootstrap.php'; +             +        $bootstrap = DocBlox_Bootstrap::createInstance(); +             +        $autoloader = $bootstrap->registerAutoloader(); +             +        if ($this->quiet) { +            DocBlox_Core_Abstract::config()->logging->level = 'quiet'; +        } else { +            DocBlox_Core_Abstract::config()->logging->level = 'debug'; +        } +             +        $bootstrap->registerPlugins($autoloader); +    } +     +    /** +     * Build a list of files (from the fileset elements) and call the DocBlox parser +     * @return string +     */ +    private function parseFiles() +    { +        $parser = new DocBlox_Parser(); +         +        //Only initialize the dispatcher when not already done +        if (is_null(DocBlox_Parser_Abstract::$event_dispatcher)) { +        	DocBlox_Parser_Abstract::$event_dispatcher = new sfEventDispatcher(); +        } +        $parser->setTitle($this->title); +         +        $paths = array(); +         +        // filesets +        foreach ($this->filesets as $fs) { +            $ds    = $fs->getDirectoryScanner($this->project); +            $dir   = $fs->getDir($this->project); +            $srcFiles = $ds->getIncludedFiles(); +             +            foreach ($srcFiles as $file) { +                $paths[] = $dir . FileSystem::getFileSystem()->getSeparator() . $file; +            } +        } +         +        $this->log("Will parse " . count($paths) . " file(s)", Project::MSG_VERBOSE); +         +        $files = new DocBlox_Parser_Files(); +        $files->addFiles($paths); +         +        $parser->setPath($files->getProjectRoot()); +         +        return $parser->parseFiles($files); +    } + +    /** +     * Task entry point +     * @see Task::main() +     */ +    public function main() +    { +        if (empty($this->destDir)) { +            throw new BuildException("You must supply the 'destdir' attribute", $this->getLocation()); +        } +         +        if (empty($this->filesets)) { +            throw new BuildException("You have not specified any files to include (<fileset>)", $this->getLocation()); +        } +         +        $this->initializeDocBlox(); +         +        $xml = $this->parseFiles(); +         +        $this->log("Transforming...", Project::MSG_VERBOSE); +         +        $transformer = new DocBlox_Transformer(); +        $transformer->setTemplatesPath(DocBlox_Core_Abstract::config()->paths->templates); +        $transformer->setTemplates($this->template); +        $transformer->setSource($xml); +        $transformer->setTarget($this->destDir->getAbsolutePath()); +        $transformer->execute(); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitBaseTask.php new file mode 100644 index 00000000..8381cc64 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitBaseTask.php @@ -0,0 +1,134 @@ +<?php +/* + *  $Id: 5ffc8c9c51dfa9bd0d691a88db670cdeb5f985c1 $ + * + * 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/Task.php'; +require_once 'phing/BuildException.php'; + +/** + * Base class for Git tasks + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 5ffc8c9c51dfa9bd0d691a88db670cdeb5f985c1 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +abstract class GitBaseTask extends Task +{ +    /** +     * Bath to git binary +     * @var string +     */ +    private $gitPath = '/usr/bin/git'; + +    /** +     * @var VersionControl_Git +     */ +    private $gitClient = null; + +    /** +     * Current repository directory +     * @var string +     */ +    private $repository;  + +    /** +     * Initialize Task. +     * Check and include necessary libraries. +     */ +    public function init()  +    { +        @include_once 'VersionControl/Git.php'; +        if (false == class_exists('VersionControl_Git')) { +            throw new BuildException("The Git tasks depend on PEAR\'s "  +                . "VersionControl_Git package.", $this->getLocation()); +        } +    } + +    /** +     * Set repository directory +     * +     * @param string $repository Repo directory +     * @return GitBaseTask +     */ +    public function setRepository($repository) +    { +        $this->repository = $repository; +        return $this; +    } + +    /** +     * Get repository directory +     * +     * @return string +     */ +    public function getRepository() +    { +        return $this->repository; +    } + +    /** +     * Set path to git executable +     * +     * @param string $gitPath New path to git repository +     * @return GitBaseTask +     */ +    public function setGitPath($gitPath) +    { +        $this->gitPath = $gitPath; +        return $this; +    } + +    /** +     * Get path to git executable +     * +     * @return string +     */ +    public function getGitPath() +    { +        return $this->gitPath; +    } + +    protected function getGitClient($reset = false, $repository = null) +    { +        $this->gitClient = ($reset === true) ? null : $this->gitClient; +        $repository = (null === $repository)  +                    ? $this->getRepository()  +                    : $repository; + +        if(null === $this->gitClient) { +            try { +                $this->gitClient = new VersionControl_Git($repository); +            } catch (VersionControl_Git_Exception $e) { +                // re-package +                throw new BuildException( +                    'You must specify readable directory as repository.'); + +            } +        } +        $this->gitClient->setGitCommandPath($this->getGitPath()); + +        return $this->gitClient; +    } +} + + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitBranchTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitBranchTask.php new file mode 100644 index 00000000..54a0eb20 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitBranchTask.php @@ -0,0 +1,296 @@ +<?php +/* + *  $Id: 88a8737d783614bcd5acb103738fafc23c509225 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-branch + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 88a8737d783614bcd5acb103738fafc23c509225 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitBranchTask extends GitBaseTask +{ +    /** +     * Branch name +     * @var string +     */ +    private $branchname; + +    /** +     * New Branch name for git-branch -m | -M +     * @var string +     */ +    private $newbranch; + +    /** +     * If not HEAD, specify starting point +     * @var string +     */ +    private $startPoint; + +    /** +     * --set-upstream key to git-branch +     * @var boolean +     */ +    private $setUpstream = false; + +    /** +     * --track key to git-branch +     * @var boolean +     */ +    private $track = false; + +    /** +     * --no-track key to git-branch +     * @var boolean +     */ +    private $noTrack = false; + +    /** +     * --force, -f key to git-branch +     * @var boolean +     */ +    private $force = false; + +    /** +     * -d, -D, -m, -M options to git-branch +     * Respective task options: +     * delete, forceDelete, move, forceMove +     * @var array +     */ +    private $extraOptions = array( +        'd' => false, +        'D' => false, +        'm' => false, +        'M' => false, +    ); + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } +        if (null === $this->getBranchname()) { +            throw new BuildException('"branchname" is required parameter'); +        } + +        // if we are moving branch, we need to know new name +        if ($this->isMove() || $this->isForceMove()) { +            if (null === $this->getNewbranch()) { +                throw new BuildException('"newbranch" is required parameter'); +            } +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('branch'); +        $command +            ->setOption('set-upstream', $this->isSetUpstream()) +            ->setOption('no-track', $this->isNoTrack()) +            ->setOption('force', $this->isForce()); +        if ($this->isNoTrack() == false) { +            $command->setOption('track', $this->getTrack()); +        } + +        // check extra options (delete, move) +        foreach ($this->extraOptions as $option => $flag) { +            if ($flag) { +                $command->setOption($option, true); +            } +        } + +        $command->addArgument($this->getBranchname()); + +        if (null !== $this->getStartPoint()) { +            $command->addArgument($this->getStartPoint()); +        } + +        if (null !== $this->getNewbranch()) { +            $command->addArgument($this->getNewbranch()); +        } + +        $this->log('git-branch command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed.'); +        } + +        $this->log( +            sprintf('git-branch: branch "%s" repository', $this->getRepository()),  +            Project::MSG_INFO);  +        $this->log('git-branch output: ' . trim($output), Project::MSG_INFO); +    } + +    public function setSetUpstream($flag) +    { +        $this->setUpstream = $flag; +    } + +    public function getSetUpstream() +    { +        return $this->setUpstream; +    } + +    public function isSetUpstream() +    { +        return $this->getSetUpstream(); +    } + +    public function setTrack($flag) +    { +        $this->track = $flag; +    } + +    public function getTrack() +    { +        return $this->track; +    } + +    public function isTrack() +    { +        return $this->getTrack(); +    } + +    public function setNoTrack($flag) +    { +        $this->noTrack = $flag; +    } + +    public function getNoTrack() +    { +        return $this->noTrack; +    } + +    public function isNoTrack() +    { +        return $this->getNoTrack(); +    } + +    public function setForce($flag) +    { +        $this->force = $flag; +    } + +    public function getForce() +    { +        return $this->force; +    } + +    public function isForce() +    { +        return $this->getForce(); +    } + +    public function setBranchname($branchname) +    { +        $this->branchname = $branchname; +    } + +    public function getBranchname() +    { +        return $this->branchname; +    } + +    public function setStartPoint($startPoint) +    { +        $this->startPoint = $startPoint; +    } + +    public function getStartPoint() +    { +        return $this->startPoint; +    } + +    public function setDelete($flag) +    { +        $this->extraOptions['d'] = $flag; +    } +     +    public function getDelete() +    { +        return $this->extraOptions['d']; +    } + +    public function isDelete() +    { +        return $this->getDelete(); +    } + +    public function setForceDelete($flag) +    { +        $this->extraOptions['D'] = $flag; +    } +     +    public function getForceDelete() +    { +        return $this->extraOptions['D']; +    } + +    public function setMove($flag) +    { +        $this->extraOptions['m'] = $flag; +    } +     +    public function getMove() +    { +        return $this->extraOptions['m']; +    } + +    public function isMove() +    { +        return $this->getMove(); +    } + +    public function setForceMove($flag) +    { +        $this->extraOptions['M'] = $flag; +    } +     +    public function getForceMove() +    { +        return $this->extraOptions['M']; +    } + +    public function isForceMove() +    { +        return $this->getForceMove(); +    } + +    public function setNewBranch($name) +    { +        $this->newbranch = $name; +    } + +    public function getNewBranch() +    { +        return $this->newbranch; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitCheckoutTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitCheckoutTask.php new file mode 100644 index 00000000..16a2bd9f --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitCheckoutTask.php @@ -0,0 +1,256 @@ +<?php +/* + *  $Id: a1dcb809b44bfd34c3af154683dd2200c814e5f0 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-checkout + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: a1dcb809b44bfd34c3af154683dd2200c814e5f0 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitCheckoutTask extends GitBaseTask +{ +    /** +     * Branch name +     * @var string +     */ +    private $branchname; + +    /** +     * If not HEAD, specify starting point +     * @var string +     */ +    private $startPoint; + +    /** +     * --force, -f key to git-checkout +     * @var boolean +     */ +    private $force = false; + +    /** +     * --quiet, -q key to git-checkout +     * @var boolean +     */ +    private $quiet = false; + +    /** +     * When creating a new branch, set up "upstream" configuration. +     * --track key to git-checkout +     * @var boolean +     */ +    private $track = false; + +    /** +     * Do not set up "upstream" configuration +     * --no-track key to git-checkout +     * @var boolean +     */ +    private $noTrack = false; + +    /** +     * -b, -B, -m  options to git-checkout +     * Respective task options: +     * create, forceCreate, merge +     * @var array +     */ +    private $extraOptions = array( +        'b' => false, +        'B' => false, +        'm' => false, +    ); + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } +        if (null === $this->getBranchname()) { +            throw new BuildException('"branchname" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('checkout'); +        $command +            ->setOption('no-track', $this->isNoTrack()) +            ->setOption('q', $this->isQuiet()) +            ->setOption('force', $this->isForce()) +            ->setOption('b', $this->isCreate()) +            ->setOption('B', $this->isForceCreate()) +            ->setOption('m', $this->isMerge()); +        if ($this->isNoTrack()) { +            $command->setOption('track', $this->isTrack()); +        } + +        $command->addArgument($this->getBranchname()); + +        if (null !== $this->getStartPoint()) { +            $command->addArgument($this->getStartPoint()); +        } + +        $this->log('git-checkout command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed.'); +        } + +        $this->log( +            sprintf('git-checkout: checkout "%s" repository', $this->getRepository()),  +            Project::MSG_INFO);  +        $this->log('git-checkout output: ' . trim($output), Project::MSG_INFO); +    } + +    public function setBranchname($branchname) +    { +        $this->branchname = $branchname; +    } + +    public function getBranchname() +    { +        return $this->branchname; +    } + +    public function setStartPoint($startPoint) +    { +        $this->startPoint = $startPoint; +    } + +    public function getStartPoint() +    { +        return $this->startPoint; +    } + +    public function setForce($flag) +    { +        $this->force = $flag; +    } + +    public function getForce() +    { +        return $this->force; +    } + +    public function isForce() +    { +        return $this->getForce(); +    } + +    public function setQuiet($flag) +    { +        $this->quiet = $flag; +    } + +    public function getQuiet() +    { +        return $this->quiet; +    } + +    public function isQuiet() +    { +        return $this->getQuiet(); +    } + +    public function setTrack($flag) +    { +        $this->track = $flag; +    } + +    public function getTrack() +    { +        return $this->track; +    } + +    public function isTrack() +    { +        return $this->getTrack(); +    } + +    public function setNoTrack($flag) +    { +        $this->noTrack = $flag; +    } + +    public function getNoTrack() +    { +        return $this->noTrack; +    } + +    public function isNoTrack() +    { +        return $this->getNoTrack(); +    } +     +    public function setCreate($flag) +    { +        $this->extraOptions['b'] = $flag; +    } +     +    public function getCreate() +    { +        return $this->extraOptions['b']; +    } + +    public function isCreate() +    { +        return $this->getCreate(); +    } + +    // -B flag is not found in all versions of git +    // --force is present everywhere +    public function setForceCreate($flag) +    { +        $this->setForce($flag); +    } +     +    public function getForceCreate() +    { +        return $this->extraOptions['B']; +    } + +    public function isForceCreate() +    { +        return $this->getForceCreate(); +    } + +    public function setMerge($flag) +    { +        $this->extraOptions['m'] = $flag; +    } +     +    public function getMerge() +    { +        return $this->extraOptions['m']; +    } + +    public function isMerge() +    { +        return $this->getMerge(); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitCloneTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitCloneTask.php new file mode 100644 index 00000000..3d1eb76f --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitCloneTask.php @@ -0,0 +1,128 @@ +<?php +/* + *  $Id: 0d9ce448c11e505885b9c5362f5c2d399e205f90 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-clone + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 0d9ce448c11e505885b9c5362f5c2d399e205f90 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitCloneTask extends GitBaseTask +{ +    /** +     * Whether --bare key should be set for git-init +     * @var string +     */ +    private $isBare = false; + +    /** +     * Path to target directory +     * @var string +     */ +    private $targetPath; + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        if (null === $this->getTargetPath()) { +            throw new BuildException('"targetPath" is required parameter'); +        } + +        $files = @scandir($this->getTargetPath()); +        if (isset($files) && is_array($files) && (count($files) > 2)) { +            throw new BuildException( +                sprintf( +                    '"%s" target directory is not empty', +                    $this->getTargetPath()) +            ); +        } + +        $client = $this->getGitClient(false, getcwd()); + +        try { +            $client->createClone( +                $this->getRepository(),  +                $this->isBare(),  +                $this->getTargetPath()); +        } catch (Exception $e) { +            throw new BuildException('The remote end hung up unexpectedly'); +        } + +        $msg = 'git-clone: cloning '  +            . ($this->isBare() ? '(bare) ' : '') +            . '"' . $this->getRepository() .'" repository' +            . ' to "' . $this->getTargetPath() .'" directory';  +        $this->log($msg, Project::MSG_INFO);  +    } + +    /** +     * Get path to target direcotry repo +     * +     * @return string +     */ +    public function getTargetPath() +    { +        return $this->targetPath; +    } + +    /** +     * Set path to source repo +     * +     * @param string $targetPath Path to repository used as source +     * @return void +     */ +    public function setTargetPath($targetPath) +    { +        $this->targetPath = $targetPath; +    } + +    /** +     * Alias @see getBare() +     * +     * @return string +     */ +    public function isBare() +    { +        return $this->getBare(); +    } + +    public function getBare() +    { +        return $this->isBare; +    } + +    public function setBare($flag) +    { +        $this->isBare = (bool)$flag; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitCommitTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitCommitTask.php new file mode 100644 index 00000000..71b26ab9 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitCommitTask.php @@ -0,0 +1,179 @@ +<?php +/* + *  $Id: 355a6d3cf8e182652b4acf3af0a6cd3eaa58fd02 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-commit + * + * @package Phing.tasks.ext.git + * @author Jonathan Creasy <jonathan.creasy@gmail.com> + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitCommitTask extends GitBaseTask +{ +    /** +     * Path to target directory +     * @var string +     */ +    private $targetPath; +     +    private $allFiles; +     +    private $message; +     +    private $files; + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        if (null === $this->getTargetPath()) { +            throw new BuildException('"targetPath" is required parameter'); +        } + +        if ($this->allFiles !== true && empty($this->files)) +        { +        	throw new BuildException('"allFiles" cannot be false if no files are specified.'); +        } + +        $client = $this->getGitClient(false, $this->getTargetPath()); + +        $options = Array(); + +        if ($this->allFiles === true) +        { +        	$options['all'] = true; +        } + +        $arguments = Array(); +        if ($this->allFiles !== true && is_array($this->files)) +        { +        	foreach($files as $file) +        	{ +	        	$arguments[] = $file; +        	} +        } + +        if (!empty($this->message)) +        { +        	$arguments[] = $this->message; +        } else { +        	$options['allow-empty-message'] = true;	 +        } + +        try { +        	$command = $git->Command('commit'); +        	$command->setArguments($arguments); +        	$command->setOptions($options); +        	$command->execute(); +        } catch (Exception $e) { +            throw new BuildException('The remote end hung up unexpectedly'); +        } + +        $msg = 'git-commit: Executed git commit '; +        foreach ($options as $option=>$value) +        { +        	 +        	$msg .= ' --' . $options . '=' . $value; +        } + +        foreach ($arguments as $argument) +        { +        	$msg .= ' ' . $argument; +        } + +        $this->log($msg, Project::MSG_INFO);  +    } + +    /** +     * Get path to target direcotry repo +     * +     * @return string +     */ +    public function getTargetPath() +    { +        return $this->targetPath; +    } + +    /** +     * Set path to source repo +     * +     * @param string $targetPath Path to repository used as source +     * @return void +     */ +    public function setTargetPath($targetPath) +    { +        $this->targetPath = $targetPath; +    } + +    /** +     * Alias @see getAllFiles() +     * +     * @return string +     */ +    public function isallFiles() +    { +        return $this->getallFiles(); +    } + +    public function getallFiles() +    { +        return $this->allFiles; +    } + +    public function setallFiles($flag) +    { +        $this->allFiles = (bool)$flag; +    } + +    public function getMessage() +    { +    	return $this->message; +    } +     +    public function setMessage($message) +    { +    	$this->message = $message; +    } +     +    public function getFiles() +    { +    	return $this->files; +    } +     +    public function setFiles($files) +    { +    	if (!$empty($files) && is_array($files)) +    	{ +    		$this->setallfiles(false); +    		$this->Files = $files; +    	} else { +    		$this->Files = null; +    	} +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitFetchTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitFetchTask.php new file mode 100644 index 00000000..4b3e8a3d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitFetchTask.php @@ -0,0 +1,284 @@ +<?php +/* + *  $Id: bcddbc1cd2e77003746b048568da8111b48da2fb $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-fetch + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: bcddbc1cd2e77003746b048568da8111b48da2fb $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitFetchTask extends GitBaseTask +{ +    /** +     * --force, -f key to git-fetch +     * @var boolean +     */ +    private $force = false; + +    /** +     * --quiet, -q key to git-fetch +     * @var boolean +     */ +    private $quiet = false; + +    /** +     * Fetch all remotes +     * --all key to git-fetch +     * @var boolean +     */ +    private $allRemotes = false; + +    /** +     * Keep downloaded pack +     * --keep key to git-fetch +     * @var boolean +     */ +    private $keepFiles = false; + +    /** +     * After fetching, remove any remote tracking branches which no longer  +     * exist on the remote.  +     * --prune key to git fetch +     * @var boolean +     */ +    private $prune = false; + +    /** +     * Disable/enable automatic tag following +     * --no-tags key to git-fetch +     * @var boolean +     */ +    private $noTags = false; + +    /** +     * Fetch all tags (even not reachable from branch heads) +     * --tags key to git-fetch +     * @var boolean +     */ +    private $tags = false; + +    /** +     * <group> argument to git-fetch +     * @var string +     */ +    private $group; + +    /** +     * <repository> argument to git-fetch +     * @var string +     */ +    private $source = 'origin'; + +    /** +     * <refspec> argument to git-fetch +     * @var string +     */ +    private $refspec; + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('fetch'); +        $command +            ->setOption('tags', $this->isTags()) +            ->setOption('no-tags', $this->isNoTags()) +            ->setOption('prune', $this->isPrune()) +            ->setOption('keep', $this->isKeepFiles()) +            ->setOption('q', $this->isQuiet()) +            ->setOption('force', $this->isForce()); + +        // set operation target +        if ($this->isAllRemotes()) {            // --all +            $command->setOption('all', true); +        } elseif ($this->getGroup()) {          // <group> +            $command->addArgument($this->getGroup()); +        } elseif ($this->getSource()) {         // <repository> [<refspec>] +            $command->addArgument($this->getSource()); +            if ($this->getRefspec()) { +                $command->addArgument($this->getRefspec()); +            } +        } else { +            throw new BuildException('No remote repository specified'); +        } + +        $this->log('git-fetch command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed.'); +        } + +        $this->log( +            sprintf('git-fetch: branch "%s" repository', $this->getRepository()),  +            Project::MSG_INFO);  +        $this->log('git-fetch output: ' . trim($output), Project::MSG_INFO); +    } + +    public function setForce($flag) +    { +        $this->force = $flag; +    } + +    public function getForce() +    { +        return $this->force; +    } + +    public function isForce() +    { +        return $this->getForce(); +    } + +    public function setQuiet($flag) +    { +        $this->quiet = $flag; +    } + +    public function getQuiet() +    { +        return $this->quiet; +    } + +    public function isQuiet() +    { +        return $this->getQuiet(); +    } + +    public function setAll($flag) +    { +        $this->allRemotes = $flag; +    } + +    public function getAll() +    { +        return $this->allRemotes; +    } + +    public function isAllRemotes() +    { +        return $this->getAll(); +    } + +    public function setKeep($flag) +    { +        $this->keepFiles = $flag; +    } + +    public function getKeep() +    { +        return $this->keepFiles; +    } + +    public function isKeepFiles() +    { +        return $this->getKeep(); +    } + +    public function setPrune($flag) +    { +        $this->prune = $flag; +    } + +    public function getPrune() +    { +        return $this->prune; +    } + +    public function isPrune() +    { +        return $this->getPrune(); +    } +     +    public function setNoTags($flag) +    { +        $this->noTags = $flag; +    } + +    public function getNoTags() +    { +        return $this->noTags; +    } + +    public function isNoTags() +    { +        return $this->getNoTags(); +    } + +    public function setTags($flag) +    { +        $this->tags = $flag; +    } + +    public function getTags() +    { +        return $this->tags; +    } + +    public function isTags() +    { +        return $this->getTags(); +    } + +    public function setSource($source) +    { +        $this->source = $source; +    } + +    public function getSource() +    { +        return $this->source; +    } + +    public function setRefspec($spec) +    { +        $this->refspec = $spec; +    } + +    public function getRefspec() +    { +        return $this->refspec; +    } + +    public function setGroup($group) +    { +        $this->group = $group; +    } + +    public function getGroup() +    { +        return $this->group; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitGcTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitGcTask.php new file mode 100644 index 00000000..12de4119 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitGcTask.php @@ -0,0 +1,158 @@ +<?php +/* + *  $Id: 13487520850c3a7ad71d85f02afbddfd408bfbba $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-gc + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 13487520850c3a7ad71d85f02afbddfd408bfbba $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitGcTask extends GitBaseTask +{ +    /** +     * --aggressive key to git-gc +     * @var boolean +     */ +    private $isAggressive = false; + +    /** +     * --auto key to git-gc +     * @var boolean +     */ +    private $isAuto = false; + +    /** +     * --no-prune key to git-gc +     * @var boolean +     */ +    private $noPrune = false; + +    /** +     * --prune=<date>option of git-gc +     * @var string +     */ +    private $prune = '2.weeks.ago'; + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('gc'); +        $command +            ->setOption('aggressive', $this->isAggressive()) +            ->setOption('auto', $this->isAuto()) +            ->setOption('no-prune', $this->isNoPrune()); +        if ($this->isNoPrune() == false) { +            $command->setOption('prune', $this->getPrune()); +        } + +        // suppress output +        $command->setOption('q'); + +        $this->log('git-gc command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed'); +        } + +        $this->log( +            sprintf('git-gc: cleaning up "%s" repository', $this->getRepository()),  +            Project::MSG_INFO);  +    } + +    /** +     * @see getAggressive() +     */ +    public function isAggressive() +    { +        return $this->getAggressive(); +    } + +    public function getAggressive() +    { +        return $this->isAggressive; +    } + +    public function setAggressive($flag) +    { +        $this->isAggressive = (bool)$flag; +    } + +    /** +     * @see getAuto() +     */ +    public function isAuto() +    { +        return $this->getAuto(); +    } + +    public function getAuto() +    { +        return $this->isAuto; +    } + +    public function setAuto($flag) +    { +        $this->isAuto = (bool)$flag; +    } + +    /** +     * @see NoPrune() +     */ +    public function isNoPrune() +    { +        return $this->getNoPrune(); +    } + +    public function getNoPrune() +    { +        return $this->noPrune; +    } + +    public function setNoPrune($flag) +    { +        $this->noPrune = (bool)$flag; +    } + +    public function getPrune() +    { +        return $this->prune; +    } + +    public function setPrune($date) +    { +        $this->prune = $date; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitInitTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitInitTask.php new file mode 100644 index 00000000..b4654cae --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitInitTask.php @@ -0,0 +1,81 @@ +<?php +/* + *  $Id: 5e66bb51f299c733e4410258f40dcf61f6e96e2f $ + * + * 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/Task.php'; +require_once 'phing/BuildException.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Repository initialization task + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 5e66bb51f299c733e4410258f40dcf61f6e96e2f $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitInitTask extends GitBaseTask +{ + +    /** +     * Whether --bare key should be set for git-init +     * @var string +     */ +    private $isBare = false; + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(); +        $client->initRepository($this->isBare()); + +        $msg = 'git-init: initializing '  +            . ($this->isBare() ? '(bare) ' : '') +            . '"' . $this->getRepository() .'" repository';  +        $this->log($msg, Project::MSG_INFO);  +    } + +    /** +     * Alias @see getBare() +     * +     * @return string +     */ +    public function isBare() +    { +        return $this->getBare(); +    } + +    public function getBare() +    { +        return $this->isBare; +    } + +    public function setBare($flag) +    { +        $this->isBare = (bool)$flag; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitLogTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitLogTask.php new file mode 100644 index 00000000..c1d8058a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitLogTask.php @@ -0,0 +1,270 @@ +<?php +/* + *  $Id: 27b94c44aa26823164ce02628de06ff8b44717f7 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-log + * + * @author Evan Kaufman <evan@digitalflophouse.com> + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 27b94c44aa26823164ce02628de06ff8b44717f7 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.5 + */ +class GitLogTask extends GitBaseTask +{ +    /** +     * Generate a diffstat. See --stat of git-log +     * @var string|boolean +     */ +    private $stat = false; +     +    /** +     * Names + status of changed files. See --name-status of git-log +     * @var boolean +     */ +    private $nameStatus = false; +     +    /** +     * Number of commits to show. See -<n>|-n|--max-count of git-log +     * @var integer +     */ +    private $maxCount; +     +    /** +     * Don't show commits with more than one parent. See --no-merges of git-log +     * @var boolean +     */ +    private $noMerges = false; +     +    /** +     * Commit format. See --format of git-log +     * @var string +     */ +    private $format = 'medium'; +     +    /** +     * Date format. See --date of git-log +     * @var string +     */ +    private $date; +     +    /** +     * <since> argument to git-log +     * @var string +     */ +    private $sinceCommit; + +    /** +     * <until> argument to git-log +     * @var string +     */ +    private $untilCommit = 'HEAD'; +     +    /** +     * <path> arguments to git-log +     * Accepts one or more paths delimited by PATH_SEPARATOR +     * @var string +     */ +    private $paths; +     +    /** +     * Property name to set with output value from git-log +     * @var string +     */ +    private $outputProperty; +     +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('log'); +        $command +            ->setOption('stat', $this->getStat()) +            ->setOption('name-status', $this->isNameStatus()) +            ->setOption('no-merges', $this->isNoMerges()) +            ->setOption('format', $this->getFormat()); +         +        if (null !== $this->getMaxCount()) { +            $command->setOption('max-count', $this->getMaxCount()); +        } +         +        if (null !== $this->getDate()) { +            $command->setOption('date', $this->getDate()); +        } + +        if (null !== $this->getSince()) { +            $command->setOption('since', $this->getSince()); +        } +        $command->setOption('until', $this->getUntil()); + +        $command->addDoubleDash(true); +        if (null !== $this->getPaths()) { +            $command->addDoubleDash(false); +            $paths = explode(PATH_SEPARATOR, $this->getPaths()); +            foreach ($paths as $path) { +                $command->addArgument($path); +            } +        } + +        $this->log('git-log command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed'); +        } + +        if (null !== $this->outputProperty) { +            $this->project->setProperty($this->outputProperty, $output); +        } + +        $this->log( +            sprintf('git-log: commit log for "%s" repository', $this->getRepository()),  +            Project::MSG_INFO);  +        $this->log('git-log output: ' . trim($output), Project::MSG_INFO); +    } +     +    public function setStat($stat) +    { +        $this->stat = $stat; +    } +     +    public function getStat() +    { +        return $this->stat; +    } +     +    public function setNameStatus($flag) +    { +        $this->nameStatus = (boolean)$flag; +    } +     +    public function getNameStatus() +    { +        return $this->nameStatus; +    } +     +    public function isNameStatus() +    { +        return $this->getNameStatus(); +    } +     +    public function setMaxCount($count) +    { +        $this->maxCount = (int)$count; +    } +     +    public function getMaxCount() +    { +        return $this->maxCount; +    } +     +    public function setNoMerges($flag) +    { +        $this->noMerges = (bool)$flag; +    } +     +    public function getNoMerges() +    { +        return $this->noMerges; +    } +     +    public function isNoMerges() +    { +        return $this->getNoMerges(); +    } +     +    public function setFormat($format) +    { +        $this->format = $format; +    } +     +    public function getFormat() +    { +        return $this->format; +    } +     +    public function setDate($date) +    { +        $this->date = $date; +    } +     +    public function getDate() +    { +        return $this->date; +    } +     +    public function setSince($since) +    { +        $this->sinceCommit = $since; +    } + +    public function getSince() +    { +        return $this->sinceCommit; +    } + +    public function setAfter($after) +    { +        $this->setSince($after); +    } + +    public function setUntil($until) +    { +        $this->untilCommit = $until; +    } + +    public function getUntil() +    { +        return $this->untilCommit; +    } + +    public function setBefore($before) +    { +        $this->setUntil($before); +    } + +    public function setPaths($paths) +    { +        $this->paths = $paths; +    } +     +    public function getPaths() +    { +        return $this->paths; +    } +     +    public function setOutputProperty($prop) +    { +        $this->outputProperty = $prop; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitMergeTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitMergeTask.php new file mode 100644 index 00000000..7a3e17fb --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitMergeTask.php @@ -0,0 +1,258 @@ +<?php +/* + *  $Id: 82fabd65e9247cb37fa3fe16c122d525db4fc697 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-merge + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 82fabd65e9247cb37fa3fe16c122d525db4fc697 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + * @link http://www.kernel.org/pub/software/scm/git/docs/git-merge.html + */ +class GitMergeTask extends GitBaseTask +{ +    /** +     * <commit> of git-merge +     * @var string +     */ +    private $remote; + +    /** +     * Commit message +     * @var string +     */ +    private $message; + +    /** +     * Merge strategy. See -s <strategy> of git-merge +     * Available strategies are: octopus ours recursive resolve subtree +     * @var string +     */ +    private $strategy; + +    /** +     * -X or --strategy-option of git-merge +     * @var string +     */ +    private $strategyOption; + +    /** +     * --commit key of git-merge +     * @var boolean +     */ +    private $commit = false; + +    /** +     * --no-commit key of git-merge +     * @var boolean +     */ +    private $noCommit = false; + +    /** +     * --ff --no-ff keys to git-merge +     * @var boolean +     */ +    private $fastForwardCommit = false; + +    /** +     * --quiet, -q key to git-merge +     * @var boolean +     */ +    private $quiet = false; + +    /** +     * Valid merge strategies +     * @var array +     */ +    private $validStrategies = array( +        'octopus', 'ours', 'recursive', 'resolve', 'subtree'); + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } +        $remotes = trim($this->getRemote()); +        if (null === $remotes || '' === $remotes) { +            throw new BuildException('"remote" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('merge'); +        $command +            ->setOption('commit', $this->isCommit()) +            ->setOption('q', $this->isQuiet()); + +        if ($this->getMessage()) { +            $command->setOption('message', $this->getMessage()); +        } + +        if (!$this->isCommit()) { +            $command->setOption('no-commit', $this->isNoCommit()); +        } + +        if ($this->isFastForwardCommit()) { +            $command->setOption('no-ff', true); +        } + +        $strategy = $this->getStrategy(); +        if ($strategy) { +            // check if strategy is valid +            if (false === in_array($strategy, $this->validStrategies)) { +                throw new BuildException( +                    "Could not find merge strategy '" . $strategy . "'\n". +                    "Available strategies are: " . implode(', ', $this->validStrategies)); +            } +            $command->setOption('strategy', $strategy); +            if ($this->getStrategyOption()) { +                $command->setOption( +                    'strategy-option', $this->getStrategyOption()); +            } +        } + +        $remotes = explode(' ', $this->getRemote()); +        foreach ($remotes as $remote) { +            $command->addArgument($remote); +        } + +        $this->log('git-merge command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed.'); +        } + +        $this->log( +            sprintf('git-merge: replaying "%s" commits', $this->getRemote()),  +            Project::MSG_INFO);  +        $this->log('git-merge output: ' . trim($output), Project::MSG_INFO); + +    } + +    public function setRemote($remote) +    { +        $this->remote = $remote; +    } + +    public function getRemote() +    { +        return $this->remote; +    } + +    public function setMessage($message) +    { +        $this->message = $message; +    } + +    public function getMessage() +    { +        return $this->message; +    } + +    public function setStrategy($strategy) +    { +        $this->strategy = $strategy; +    } + +    public function getStrategy() +    { +        return $this->strategy; +    } + +    public function setStrategyOption($strategyOption) +    { +        $this->strategyOption = $strategyOption; +    } + +    public function getStrategyOption() +    { +        return $this->strategyOption; +    } + +    public function setQuiet($flag) +    { +        $this->quiet = $flag; +    } + +    public function getQuiet() +    { +        return $this->quiet; +    } + +    public function isQuiet() +    { +        return $this->getQuiet(); +    } + +    public function setCommit($flag) +    { +        $this->commit = (boolean)$flag; +    } + +    public function getCommit() +    { +        return $this->commit; +    } + +    public function isCommit() +    { +        return $this->getCommit(); +    } + +    public function setNoCommit($flag) +    { +        $this->noCommit = (boolean)$flag; +    } + +    public function getNoCommit() +    { +        return $this->noCommit; +    } + +    public function isNoCommit() +    { +        return $this->getNoCommit(); +    } + +    public function setFastForwardCommit($flag) +    { +        $this->fastForwardCommit = $flag; +    } + +    public function getFastForwardCommit() +    { +        return $this->fastForwardCommit; +    } + +    public function isFastForwardCommit() +    { +        return $this->getFastForwardCommit(); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitPullTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitPullTask.php new file mode 100644 index 00000000..1f7cfcc1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitPullTask.php @@ -0,0 +1,373 @@ +<?php +/* + *  $Id: f96a4faad59ab1b29abccd59d04269fe0c409084 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-pull + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: f96a4faad59ab1b29abccd59d04269fe0c409084 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitPullTask extends GitBaseTask +{ +    /** +     * <repository> argument to git-pull +     * @var string +     */ +    private $source = 'origin'; + +    /** +     * <refspec> argument to git-pull +     * @var string +     */ +    private $refspec; + +    /** +     * --rebase key to git-pull +     * @var boolean +     */ +    private $rebase = false; + +    /** +     * --no-rebase key to git-pull +     * Allow to override --rebase (if set to default true in configuration) +     * @var boolean +     */ +    private $noRebase = false; + +    /** +     * Merge strategy. See -s <strategy> of git-pull +     * @var string +     */ +    private $strategy; + +    /** +     * -X or --strategy-option of git-pull +     * @var string +     */ +    private $strategyOption; + +    /** +     * Fetch all remotes +     * --all key to git-pull +     * @var boolean +     */ +    private $allRemotes = false; + +    /** +     * --append key to git-pull +     * @var boolean +     */ +    private $append = false; + +    /** +     * Keep downloaded pack +     * --keep key to git-pull +     * @var boolean +     */ +    private $keepFiles = false; + +    /** +     * Disable/enable automatic tag following +     * --no-tags key to git-pull +     * @var boolean +     */ +    private $noTags = false; + +    /** +     * Fetch all tags (even not reachable from branch heads) +     * --tags key to git-pull +     * @var boolean +     */ +    private $tags = false; + +    /** +     * --quiet, -q key to git-pull +     * @var boolean +     */ +    private $quiet = true; + +    /** +     * --force, -f key to git-pull +     * @var boolean +     */ +    private $force = false; + +    /** +     * Valid merge strategies +     * @var array +     */ +    private $validStrategies = array( +        'octopus', 'ours', 'recursive', 'resolve', 'subtree'); + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('pull'); +        $command +            ->setOption('rebase', $this->isRebase()); + +        if (!$this->isRebase()) { +            $command->setOption('no-rebase', $this->isNoRebase()); +        } + +        $strategy = $this->getStrategy(); +        if ($strategy) { +            // check if strategy is valid +            if (false === in_array($strategy, $this->validStrategies)) { +                throw new BuildException( +                    "Could not find merge strategy '" . $strategy . "'\n". +                    "Available strategies are: " . implode(', ', $this->validStrategies)); +            } +            $command->setOption('strategy', $strategy); +            if ($this->getStrategyOption()) { +                $command->setOption( +                    'strategy-option', $this->getStrategyOption()); +            } +        } + +        // order of arguments is important +        $command +            ->setOption('tags', $this->isTags()) +            ->setOption('no-tags', $this->isNoTags()) +            ->setOption('keep', $this->isKeepFiles()) +            ->setOption('append', $this->isAppend()) +            ->setOption('q', $this->isQuiet()) +            ->setOption('force', $this->isForce()); + +        // set operation target +        if ($this->isAllRemotes()) {            // --all +            $command->setOption('all', true); +            $this->log('git-pull: fetching from all remotes', Project::MSG_INFO); +        } elseif ($this->getSource()) {         // <repository> [<refspec>] +            $command->addArgument($this->getSource()); +            if ($this->getRefspec()) { +                $command->addArgument($this->getRefspec()); +            } +            $this->log( +                sprintf('git-pull: pulling from %s %s',  +                    $this->getSource(), $this->getRefspec()),  +                Project::MSG_INFO);  +        } else { +            throw new BuildException('No source repository specified'); +        } + +        $this->log('git-pull command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed.'); +        } + +        $this->log('git-pull: complete', Project::MSG_INFO);  +        $this->log('git-pull output: ' . trim($output), Project::MSG_INFO); + +    } + +    public function setStrategy($strategy) +    { +        $this->strategy = $strategy; +    } + +    public function getStrategy() +    { +        return $this->strategy; +    } + +    public function setStrategyOption($strategyOption) +    { +        $this->strategyOption = $strategyOption; +    } + +    public function getStrategyOption() +    { +        return $this->strategyOption; +    } + +    public function setSource($source) +    { +        $this->source = $source; +    } + +    public function getSource() +    { +        return $this->source; +    } + +    public function setRefspec($spec) +    { +        $this->refspec = $spec; +    } + +    public function getRefspec() +    { +        return $this->refspec; +    } + +    public function setAll($flag) +    { +        $this->allRemotes = $flag; +    } + +    public function getAll() +    { +        return $this->allRemotes; +    } + +    public function isAllRemotes() +    { +        return $this->getAll(); +    } + +    public function setAppend($flag) +    { +        $this->append = (boolean)$flag; +    } + +    public function getAppend() +    { +        return $this->append; +    } + +    public function isAppend() +    { +        return $this->getAppend(); +    } + +    public function setKeep($flag) +    { +        $this->keepFiles = $flag; +    } + +    public function getKeep() +    { +        return $this->keepFiles; +    } + +    public function isKeepFiles() +    { +        return $this->getKeep(); +    } + +    public function setNoTags($flag) +    { +        $this->noTags = $flag; +    } + +    public function getNoTags() +    { +        return $this->noTags; +    } + +    public function isNoTags() +    { +        return $this->getNoTags(); +    } + +    public function setTags($flag) +    { +        $this->tags = $flag; +    } + +    public function getTags() +    { +        return $this->tags; +    } + +    public function isTags() +    { +        return $this->getTags(); +    } + +    public function setQuiet($flag) +    { +        $this->quiet = $flag; +    } + +    public function getQuiet() +    { +        return $this->quiet; +    } + +    public function isQuiet() +    { +        return $this->getQuiet(); +    } + +    public function setRebase($flag) +    { +        $this->rebase = (boolean)$flag; +    } + +    public function getRebase() +    { +        return $this->rebase; +    } + +    public function isRebase() +    { +        return $this->getRebase(); +    } + +    public function setNoRebase($flag) +    { +        $this->noRebase = (boolean)$flag; +    } + +    public function getNoRebase() +    { +        return $this->noRebase; +    } + +    public function isNoRebase() +    { +        return $this->getNoRebase(); +    } + +    public function setForce($flag) +    { +        $this->force = $flag; +    } + +    public function getForce() +    { +        return $this->force; +    } + +    public function isForce() +    { +        return $this->getForce(); +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitPushTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitPushTask.php new file mode 100644 index 00000000..996fa57f --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitPushTask.php @@ -0,0 +1,255 @@ +<?php +/* + *  $Id: a01e7e9f6cc92e419e82b4e99e4a45de6a61eba8 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-push + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: a01e7e9f6cc92e419e82b4e99e4a45de6a61eba8 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + * @link http://www.kernel.org/pub/software/scm/git/docs/git-push.html + */ +class GitPushTask extends GitBaseTask +{ +    /** +     * Instead of naming each ref to push, specifies that all refs +     * --all key to git-push +     * @var boolean +     */ +    private $allRemotes = false; + +    /** +     * Mirror to remote repository +     * --mirror key to git-push +     * @var boolean +     */ +    private $mirror = false; + +    /** +     * Same as prefixing repos with colon +     * --delete argument to git-push +     * @var string +     */ +    private $delete = false; + +    /** +     * Push all refs under refs/tags +     * --tags key to git-fetch +     * @var boolean +     */ +    private $tags = false; + +    /** +     * <repository> argument to git-push +     * @var string +     */ +    private $destination = 'origin'; + +    /** +     * <refspec> argument to git-push +     * @var string +     */ +    private $refspec; + +    /** +     * --force, -f key to git-push +     * @var boolean +     */ +    private $force = false; + +    /** +     * --quiet, -q key to git-push +     * @var boolean +     */ +    private $quiet = true; + +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('push'); +        $command +            ->setOption('tags', $this->isTags()) +            ->setOption('mirror', $this->isMirror()) +            ->setOption('delete', $this->isDelete()) +            ->setOption('q', $this->isQuiet()) +            ->setOption('force', $this->isForce()); + +        // set operation target +        if ($this->isAllRemotes()) {            // --all +            $command->setOption('all', true); +            $this->log('git-push: push to all refs', Project::MSG_INFO);  +        } elseif ($this->isMirror()) {         // <repository> [<refspec>] +            $command->setOption('mirror', true); +            $this->log('git-push: mirror all refs', Project::MSG_INFO);  +        } elseif ($this->getDestination()) {         // <repository> [<refspec>] +            $command->addArgument($this->getDestination()); +            if ($this->getRefspec()) { +                $command->addArgument($this->getRefspec()); +            } +            $this->log( +                sprintf('git-push: pushing to %s %s',  +                    $this->getDestination(), $this->getRefspec()),  +                Project::MSG_INFO);  +        } else { +            throw new BuildException('At least one destination must be provided'); +        } + +        $this->log('git-push command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            throw new BuildException('Task execution failed.'); +        } + +        $this->log('git-push: complete', Project::MSG_INFO);  +        if ($this->isDelete()) { +            $this->log('git-push: branch delete requested', Project::MSG_INFO); +        } +        $this->log('git-push output: ' . trim($output), Project::MSG_INFO); +    } + +    public function setAll($flag) +    { +        $this->allRemotes = $flag; +    } + +    public function getAll() +    { +        return $this->allRemotes; +    } + +    public function isAllRemotes() +    { +        return $this->getAll(); +    } + +    public function setMirror($flag) +    { +        $this->mirror = (boolean)$flag; +    } + +    public function getMirror() +    { +        return $this->mirror; +    } + +    public function isMirror() +    { +        return $this->getMirror(); +    } + +    public function setDelete($flag) +    { +        $this->delete = (boolean)$flag; +    } + +    public function getDelete() +    { +        return $this->delete; +    } + +    public function isDelete() +    { +        return $this->getDelete(); +    } + +    public function setTags($flag) +    { +        $this->tags = $flag; +    } + +    public function getTags() +    { +        return $this->tags; +    } + +    public function isTags() +    { +        return $this->getTags(); +    } + +    public function setDestination($destination) +    { +        $this->destination = $destination; +    } + +    public function getDestination() +    { +        return $this->destination; +    } + +    public function setRefspec($spec) +    { +        $this->refspec = $spec; +    } + +    public function getRefspec() +    { +        return $this->refspec; +    } + +    public function setForce($flag) +    { +        $this->force = $flag; +    } + +    public function getForce() +    { +        return $this->force; +    } + +    public function isForce() +    { +        return $this->getForce(); +    } + +    public function setQuiet($flag) +    { +        $this->quiet = $flag; +    } + +    public function getQuiet() +    { +        return $this->quiet; +    } + +    public function isQuiet() +    { +        return $this->getQuiet(); +    } + + + + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitTagTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitTagTask.php new file mode 100644 index 00000000..864e71ba --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitTagTask.php @@ -0,0 +1,406 @@ +<?php +/* + *  $Id: 127d4af12e159083935466773d1af788e46acd4e $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper around git-tag + * + * @author Evan Kaufman <evan@digitalflophouse.com> + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 127d4af12e159083935466773d1af788e46acd4e $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.5 + */ +class GitTagTask extends GitBaseTask +{ +    /** +     * Make unsigned, annotated tag object. See -a of git-tag +     * @var boolean +     */ +    private $annotate = false; +     +    /** +     * Make GPG-signed tag. See -s of git-tag +     * @var boolean +     */ +    private $sign = false; +     +    /** +     * Make GPG-signed tag, using given key. See -u of git-tag +     * @var string +     */ +    private $keySign; +     +    /** +     * Replace existing tag with given name. See -f of git-tag +     * @var boolean +     */ +    private $replace = false; +     +    /** +     * Delete existing tags with given names. See -d of git-tag +     * @var boolean +     */ +    private $delete = false; +     +    /** +     * Verify gpg signature of given tag names. See -v of git-tag +     * @var boolean +     */ +    private $verify = false; +     +    /** +     * List tags with names matching given pattern. See -l of git-tag +     * @var boolean +     */ +    private $list = false; + +    /** +     * <num> specifies how many lines from the annotation, if any, are printed  +     * when using -l. See -n of git-tag +     * @var int +     */ +    private $num; +     +    /** +     * Only list tags containing specified commit. See --contains of git-tag +     * @var string +     */ +    private $contains; +     +    /** +     * Use given tag message. See -m of git-tag +     * @var string +     */ +    private $message; +     +    /** +     * Take tag message from given file. See -F of git-tag +     * @var string +     */ +    private $file; +     +    /** +     * <tagname> argument to git-tag +     * @var string +     */ +    private $name; +     +    /** +     * <commit> argument to git-tag +     * @var string +     */ +    private $commit; +     +    /** +     * <object> argument to git-tag +     * @var string +     */ +    private $object; +     +    /** +     * <pattern> argument to git-tag +     * @var string +     */ +    private $pattern; +     +    /** +     * Property name to set with output value from git-tag +     * @var string +     */ +    private $outputProperty; +     +    /** +     * The main entry point for the task +     */ +    public function main() +    { +        if (null === $this->getRepository()) { +            throw new BuildException('"repository" is required parameter'); +        } + +        $client = $this->getGitClient(false, $this->getRepository()); +        $command = $client->getCommand('tag'); +        $command +            ->setOption('a', $this->isAnnotate()) +            ->setOption('s', $this->isSign()) +            ->setOption('f', $this->isReplace()) +            ->setOption('d', $this->isDelete()) +            ->setOption('v', $this->isVerify()) +            ->setOption('l', $this->isList()); +         +        if (null !== $this->getKeySign()) { +            $command->setOption('u', $this->getKeySign()); +        } + +        if (null !== $this->getMessage()) { +            $command->setOption('m', $this->getMessage()); +        } + +        if (null !== $this->getFile()) { +            $command->setOption('F', $this->getFile()); +        } +         +        // Use 'name' arg, if relevant +        if (null != $this->getName() && false == $this->isList()) { +            $command->addArgument($this->getName()); +        } +         +        if (null !== $this->getKeySign() || $this->isAnnotate() || $this->isSign()) { +            // Require a tag message or file +            if (null === $this->getMessage() && null === $this->getFile()) { +                throw new BuildException('"message" or "file" required to make a tag'); +            } +        } + +        // Use 'commit' or 'object' args, if relevant +        if (null !== $this->getCommit()) { +            $command->addArgument($this->getCommit()); +        } else if (null !== $this->getObject()) { +            $command->addArgument($this->getObject()); +        } +         +        // Customize list (-l) options +        if ($this->isList()) { +            if (null !== $this->getContains()) { +                $command->setOption('contains', $this->getContains()); +            } +            if (null !== $this->getPattern()) { +                $command->addArgument($this->getPattern()); +            } +            if (null != $this->getNum()) { +                $command->setOption('n', $this->getNum()); +            } +        } + +        $this->log('git-tag command: ' . $command->createCommandString(), Project::MSG_INFO); + +        try { +            $output = $command->execute(); +        } catch (Exception $e) { +            $this->log($e->getMessage(), Project::MSG_ERR); +            throw new BuildException('Task execution failed. ' . $e->getMessage()); +        } + +        if (null !== $this->outputProperty) { +            $this->project->setProperty($this->outputProperty, $output); +        } + +        $this->log( +            sprintf('git-tag: tags for "%s" repository', $this->getRepository()),  +            Project::MSG_INFO);  +        $this->log('git-tag output: ' . trim($output), Project::MSG_INFO); +    } +     +    public function setAnnotate($flag) +    { +        $this->annotate = (bool)$flag; +    } +     +    public function getAnnotate() +    { +        return $this->annotate; +    } +     +    public function isAnnotate() +    { +        return $this->getAnnotate(); +    } + +    public function setSign($flag) +    { +        $this->sign = (bool)$flag; +    } +     +    public function getSign() +    { +        return $this->sign; +    } +     +    public function isSign() +    { +        return $this->getSign(); +    } + +    public function setKeySign($keyId) +    { +        $this->keySign = $keyId; +    } +     +    public function getKeySign() +    { +        return $this->keySign; +    } + +    public function setReplace($flag) +    { +        $this->replace = (bool)$flag; +    } +     +    public function getReplace() +    { +        return $this->replace; +    } +     +    public function isReplace() +    { +        return $this->getReplace(); +    } + +    public function setForce($flag) +    { +        return $this->setReplace($flag); +    } +     +    public function setDelete($flag) +    { +        $this->delete = (bool)$flag; +    } +     +    public function getDelete() +    { +        return $this->delete; +    } +     +    public function isDelete() +    { +        return $this->getDelete(); +    } + +    public function setVerify($flag) +    { +        $this->verify = (bool)$flag; +    } +     +    public function getVerify() +    { +        return $this->verify; +    } +     +    public function isVerify() +    { +        return $this->getVerify(); +    } + +    public function setList($flag) +    { +        $this->list = (bool)$flag; +    } +     +    public function getList() +    { +        return $this->list; +    } +     +    public function isList() +    { +        return $this->getList(); +    } + +    public function setNum($num) +    { +        $this->num = (int)$num; +    } +     +    public function getNum() +    { +        return $this->num; +    } + +    public function setContains($commit) +    { +        $this->contains = $commit; +    } +     +    public function getContains() +    { +        return $this->contains; +    } + +    public function setMessage($msg) +    { +        $this->message = $msg; +    } +     +    public function getMessage() +    { +        return $this->message; +    } + +    public function setFile($file) +    { +        $this->file = $file; +    } +     +    public function getFile() +    { +        return $this->file; +    } + +    public function setName($name) +    { +        $this->name = $name; +    } +     +    public function getName() +    { +        return $this->name; +    } + +    public function setCommit($commit) +    { +        $this->commit = $commit; +    } +     +    public function getCommit() +    { +        return $this->commit; +    } + +    public function setObject($object) +    { +        $this->object = $object; +    } +     +    public function getObject() +    { +        return $this->object; +    } + +    public function setPattern($pattern) +    { +        $this->pattern = $pattern; +    } +     +    public function getPattern() +    { +        return $this->pattern; +    } +     +    public function setOutputProperty($prop) +    { +        $this->outputProperty = $prop; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php index 76780fa6..38ec99d4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: IoncubeComment.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: dbbc1b4830ba43116d5b5e5d20c749598eaf62b7 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,23 +22,22 @@  /**   * Wrapper for comments for ionCube tasks   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: IoncubeComment.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: dbbc1b4830ba43116d5b5e5d20c749598eaf62b7 $   * @package phing.tasks.ext.ioncube   * @since 2.2.0   */  class IoncubeComment  { -	private $value = ""; -	 -	public function getValue() -	{ -		return $this->value; -	} -	 -	public function addText($txt) -	{ -		$this->value = trim($txt); -	} +    private $value = ""; +     +    public function getValue() +    { +        return $this->value; +    } +     +    public function addText($txt) +    { +        $this->value = trim($txt); +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php index 9eecd5a0..5a31f355 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: IoncubeEncoderTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: a6ce870b3d14be7f365468e3a272e5ac16128e93 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,312 +25,618 @@ require_once 'phing/tasks/ext/ioncube/IoncubeComment.php';  /**   * Invokes the ionCube Encoder (PHP4 or PHP5)   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: IoncubeEncoderTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @author Andrew Eddie <andrew.eddie@jamboworks.com>  + * @author Domenico Sgarbossa <sbraaaa@yahoo.it>  + * @version $Id: a6ce870b3d14be7f365468e3a272e5ac16128e93 $   * @package phing.tasks.ext.ioncube   * @since 2.2.0   */  class IoncubeEncoderTask extends Task  { -	private $phpVersion = "5"; -	private $ioncubePath = "/usr/local/ioncube"; -	private $encoderName = "ioncube_encoder"; -	 -	private $fromDir = ""; -	private $toDir = ""; -	 -	private $encrypt = ""; -	 -	private $targetOption = ""; -	private $binary = false; -	private $optimize = ""; -	private $withoutRuntimeLoaderSupport = false; -	 -	private $licensePath = ""; -	private $passPhrase = ""; -	 -	private $comments = array(); +    private $ionSwitches = array(); +     +    private $ionOptions = array(); +     +    private $ionOptionsXS = array(); -	/** -	 * Sets the path to the ionCube encoder -	 */ -	function setIoncubePath($ioncubePath) -	{ -		$this->ioncubePath = $ioncubePath; -	} +    private $comments = array(); +     +    private $encoderName = 'ioncube_encoder'; +     +    private $fromDir = ''; -	/** -	 * Returns the path to the ionCube encoder -	 */ -	function getIoncubePath() -	{ -		return $this->ioncubePath; -	} +    private $ioncubePath = '/usr/local/ioncube'; -	/** -	 * Sets the version of PHP to use (defaults to 5) -	 */ -	function setPhpVersion($phpVersion) -	{ -		$this->phpVersion = $phpVersion; -	} +    private $phpVersion = '5'; -	/** -	 * Returns the version of PHP to use (defaults to 5) -	 */ -	function getPhpVersion() -	{ -		return $this->phpVersion; -	} -	 -	/** -	 * Sets the source directory -	 */ -	function setFromDir($fromDir) -	{ -		$this->fromDir = $fromDir; -	} +    private $targetOption = ''; -	/** -	 * Returns the source directory -	 */ -	function getFromDir($fromDir) -	{ -		return $this->fromDir; -	} -	 -	/** -	 * Sets the target directory -	 */ -	function setToDir($toDir) -	{ -		$this->toDir = $toDir; -	} +    private $toDir = ''; -	/** -	 * Returns the target directory -	 */ -	function getToDir($toDir) -	{ -		return $this->toDir; -	} +    private $showCommandLine = false; +  +    /** +     * Sets whether to show command line before it is executed +     */ +    function setShowCommandLine($value) +    { +        $this->showCommandLine = $value; +    } -	/** -	 * Sets regexps of additional files to encrypt (separated by space) -	 */ -	function setEncrypt($encrypt) -	{ -		$this->encrypt = $encrypt; -	} -	 -	/** -	 * Returns regexps of additional files to encrypt (separated by space) -	 */ -	function getEncrypt() -	{ -		return $this->encrypt; -	} -	 -	/** -	 * Sets the binary option -	 */ -	function setBinary($binary) -	{ -		$this->binary = $binary; -	} -	 -	/** -	 * Returns the binary option -	 */ -	function getBinary() -	{ -		return $this->binary; -	} +    /** +     * Adds a comment to be used in encoded files +     */ +    function addComment(IoncubeComment $comment) +    { +        $this->comments[] = $comment; +    } -	/** -	 * Sets the optimize option -	 */ -	function setOptimize($optimize) -	{ -		$this->optimize = $optimize; -	} -	 -	/** -	 * Returns the optimize option -	 */ -	function getOptimize() -	{ -		return $this->optimize; -	} +    /** +     * Sets the allowed server +     */ +    function setAllowedServer($value) +    { +        $this->ionOptionsXS['allowed-server'] = $value; +    } -	/** -	 * Sets the without-runtime-loader-support option -	 */ -	function setWithoutRuntimeLoaderSupport($withoutRuntimeLoaderSupport) -	{ -		$this->withoutRuntimeLoaderSupport = $withoutRuntimeLoaderSupport; -	} -	 -	/** -	 * Returns the without-runtime-loader-support option -	 */ -	function getWithoutRuntimeLoaderSupport() -	{ -		return $this->withoutRuntimeLoaderSupport; -	} -	 -	/** -	 * Sets the option to use when encoding target directory already exists (defaults to none) -	 */ -	function setTargetOption($targetOption) -	{ -		$this->targetOption = $targetOption; -	} +    /** +     * Returns the allowed server setting +     */ +    function getAllowedServer() +    { +        return $this->ionOptionsXS['allowed-server']; +    } -	/** -	 * Returns he option to use when encoding target directory already exists (defaults to none) -	 */ -	function getTargetOption() -	{ -		return $this->targetOption; -	} -	 -	/** -	 * Sets the path to the license file to use -	 */ -	function setLicensePath($licensePath) -	{ -		$this->licensePath = $licensePath; -	} +    /** +     * Sets the binary option +     */ +    function setBinary($value) +    { +        $this->ionSwitches['binary'] = $value; +    } -	/** -	 * Returns the path to the license file to use -	 */ -	function getLicensePath() -	{ -		return $this->licensePath; -	} +    /** +     * Returns the binary option +     */ +    function getBinary() +    { +        return $this->ionSwitches['binary']; +    } -	/** -	 * Sets the passphrase to use when encoding files -	 */ -	function setPassPhrase($passPhrase) -	{ -		$this->passPhrase = $passPhrase; -	} +    /** +     * Sets files or folders to copy (separated by space) +     */ +    function setCopy($value) +    { +        $this->ionOptionsXS['copy'] = $value; +    } -	/** -	 * Returns the passphrase to use when encoding files -	 */ -	function getPassPhrase() -	{ -		return $this->passPhrase; -	} +    /** +     * Returns the copy setting +     */ +    function getCopy() +    { +        return $this->ionOptionsXS['copy']; +    } -	/** -	 * Adds a comment to be used in encoded files -	 */ -	function addComment(IoncubeComment $comment) -	{ -		$this->comments[] = $comment; -	} +    /** +     * Sets additional file patterns, files or directories to encode, +     * or to reverse the effect of copy (separated by space) +     */ +    function setEncode($value) +    { +        $this->ionOptionsXS['encode'] = $value; +    } +     +    /** +     * Returns the encode setting +     */ +    function getEncode() +    { +        return $this->ionOptionsXS['encode']; +    } -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$arguments = $this->constructArguments(); -		 -		$encoder = new PhingFile($this->ioncubePath, $this->encoderName . ($this->phpVersion == 5 ? '5' : '')); -		 -		$this->log("Running ionCube Encoder..."); -		 -		exec($encoder->__toString() . " " . $arguments . " 2>&1", $output, $return); -		 +    /** +     * Sets regexps of additional files to encrypt (separated by space) +     */ +    function setEncrypt($value) +    { +        $this->ionOptionsXS['encrypt'] = $value; +    } +     +    /** +     * Returns regexps of additional files to encrypt (separated by space) +     */ +    function getEncrypt() +    { +        return $this->ionOptionsXS['encrypt']; +    } + +    /** +     * Sets a period after which the files expire +     */ +    function setExpirein($value) +    { +        $this->ionOptions['expire-in'] = $value; +    } +     +    /** +     * Returns the expireIn setting +     */ +    function getExpirein() +    { +        return $this->ionOptions['expire-in']; +    } + +    /** +     * Sets a YYYY-MM-DD date to expire the files  +     */ +    function setExpireon($value) +    { +        $this->ionOptions['expire-on'] = $value; +    } +     +    /** +     * Returns the expireOn setting +     */ +    function getExpireon() +    { +        return $this->ionOptions['expire-on']; +    } + +    /** +     * Sets the source directory +     */ +    function setFromDir($value) +    { +        $this->fromDir = $value; +    } + +    /** +     * Returns the source directory +     */ +    function getFromDir() +    { +        return $this->fromDir; +    } + +    /** +     * Set files and directories to ignore entirely and exclude from the target directory +     * (separated by space). +     */ +    function setIgnore($value) +    { +        $this->ionOptionsXS['ignore'] = $value; +    } + +    /** +     * Returns the ignore setting +     */ +    function getIgnore() +    { +        return $this->ionOptionsXS['ignore']; +    } + +    /** +     * Sets the path to the ionCube encoder +     */ +    function setIoncubePath($value) +    { +        $this->ioncubePath = $value; +    } + +    /** +     * Returns the path to the ionCube encoder +     */ +    function getIoncubePath() +    { +        return $this->ioncubePath; +    } + +    /** +     * Set files and directories not to be ignored (separated by space). +     */ +    function setKeep($value) +    { +        $this->ionOptionsXS['keep'] = $value; +    } + +    /** +     * Returns the ignore setting +     */ +    function getKeep() +    { +        return $this->ionOptionsXS['keep']; +    } + +    /** +     * Sets the path to the license file to use +     */ +    function setLicensePath($value) +    { +        $this->ionOptions['with-license'] = $value; +    } + +    /** +     * Returns the path to the license file to use +     */ +    function getLicensePath() +    { +        return $this->ionOptions['with-license']; +    } + +    /** +     * Sets the no-doc-comments option +     */ +    function setNoDocComments($value) +    { +        $this->ionSwitches['no-doc-comment'] = $value; +    } +     +    /** +     * Returns the no-doc-comments option +     */ +    function getNoDocComments() +    { +        return $this->ionSwitches['no-doc-comment']; +    } +     +    /** +     * Sets the obfuscate option +     */ +    function setObfuscate($value) +    { +        $this->ionOptionsXS['obfuscate'] = $value; +    } +     +    /** +     * Returns the optimize option +     */ +    function getObfuscate() +    { +        return $this->ionOptionsXS['obfuscate']; +    } + +    /** +     * Sets the obfuscation key (required if using the obfuscate option) +     */ +    function setObfuscationKey($value) +    { +        $this->ionOptions['obfuscation-key'] = $value; +    } +     +    /** +     * Returns the optimize option +     */ +    function getObfuscationKey() +    { +        return $this->ionOptions['obfuscation-key']; +    } + +    /** +     * Sets the optimize option +     */ +    function setOptimize($value) +    { +        $this->ionOptions['optimize'] = $value; +    } +     +    /** +     * Returns the optimize option +     */ +    function getOptimize() +    { +        return $this->ionOptions['optimize']; +    } + +    /** +     * Sets the passphrase to use when encoding files +     */ +    function setPassPhrase($value) +    { +        $this->ionOptions['passphrase'] = $value; +    } + +    /** +     * Returns the passphrase to use when encoding files +     */ +    function getPassPhrase() +    { +        return $this->ionOptions['passphrase']; +    } + +    /** +     * Sets the version of PHP to use (defaults to 5) +     */ +    function setPhpVersion($value) +    { +        $this->phpVersion = $value; +    } + +    /** +     * Returns the version of PHP to use (defaults to 5) +     */ +    function getPhpVersion() +    { +        return $this->phpVersion; +    } +     +    /** +     * Sets the target directory +     */ +    function setToDir($value) +    { +        $this->toDir = $value; +    } + +    /** +     * Returns the target directory +     */ +    function getToDir() +    { +        return $this->toDir; +    } + +    /** +     * Sets the without-runtime-loader-support option +     */ +    function setWithoutRuntimeLoaderSupport($value) +    { +        $this->ionSwitches['without-runtime-loader-support'] = $value; +    } +     +    /** +     * Returns the without-runtime-loader-support option +     */ +    function getWithoutRuntimeLoaderSupport() +    { +        return $this->ionSwitches['without-runtime-loader-support']; +    } + +    /** +     * Sets the no-short-open-tags option +     */ +    function setNoShortOpenTags($value) +    { +        $this->ionSwitches['no-short-open-tags'] = $value; +    } +     +    /** +     * Returns the no-short-open-tags option +     */ +    function getNoShortOpenTags() +    { +        return $this->ionSwitches['no-short-open-tags']; +    } + +    /** +     * Sets the ignore-deprecated-warnings option +     */ +    function setIgnoreDeprecatedWarnings($value) +    { +        $this->ionSwitches['ignore-deprecated-warnings'] = $value; +    } + +    /** +     * Returns the ignore-deprecated-warnings option +     */ +    function getIgnoreDeprecatedWarnings() +    { +        return $this->ionSwitches['ignore-deprecated-warnings']; +    } + +    /** +     * Sets the ignore-strict-warnings option +     */ +    function setIgnoreStrictWarnings($value) +    { +        $this->ionSwitches['ignore-strict-warnings'] = $value; +    } + +    /** +     * Returns the ignore-strict-warnings option +     */ +    function getIgnoreStrictWarnings() +    { +        return $this->ionSwitches['ignore-strict-warnings']; +    } + +    /** +     * Sets the allow-encoding-into-source option +     */ +    function setAllowEncodingIntoSource($value) +    { +        $this->ionSwitches['allow-encoding-into-source'] = $value; +    } + +    /** +     * Returns the allow-encoding-into-source option +     */ +    function getAllowEncodingIntoSource() +    { +        return $this->ionSwitches['allow-encoding-into-source']; +    } + +    /** +     * Sets the message-if-no-loader option +     */ +    function setMessageIfNoLoader($value) +    { +        $this->ionOptions['message-if-no-loader'] = $value; +    } + +    /** +     * Returns the message-if-no-loader option +     */ +    function getMessageIfNoLoader() +    { +        return $this->ionOptions['message-if-no-loader']; +    } + +    /** +     * Sets the action-if-no-loader option +     */ +    function setActionIfNoLoader($value) +    { +        $this->ionOptions['action-if-no-loader'] = $value; +    } + +    /** +     * Returns the action-if-no-loader option +     */ +    function getActionIfNoLoader() +    { +        return $this->ionOptions['action-if-no-loader']; +    } + +    /** +     * Sets the option to use when encoding target directory already exists (defaults to none) +     */ +    function setTargetOption($targetOption) +    { +        $this->targetOption = $targetOption; +    } + +    /** +     * Returns he option to use when encoding target directory already exists (defaults to none) +     */ +    function getTargetOption() +    { +        return $this->targetOption; +    } +     +    /** +     * Sets the callback-file option +     */ +    function setCallbackFile($value) +    { +        $this->ionOptions['callback-file'] = $value; +    } + +    /** +     * Returns the callback-file option +     */ +    function getCallbackFile() +    { +        return $this->ionOptions['callback-file']; +    } + +    /** +     * Sets the obfuscation-exclusions-file option +     */ +    function setObfuscationExclusionFile($value) +    { +        $this->ionOptions['obfuscation-exclusion-file'] = $value; +    } + +    /** +     * Returns the obfuscation-exclusions-file option +     */ +    function getObfuscationExclusionFile() +    { +        return $this->ionOptions['obfuscation-exclusion-file']; +    } +  +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $arguments = $this->constructArguments(); +         +        $encoder = new PhingFile($this->ioncubePath, $this->encoderName . ($this->phpVersion == 5 ? '5' : '')); +         +        $this->log("Running ionCube Encoder..."); +        +        if ($this->showCommandLine) +        { +            $this->log("Command line: ".$encoder->__toString() . ' ' . $arguments); +        } + +        exec($encoder->__toString() . ' ' . $arguments . " 2>&1", $output, $return); +                 if ($return != 0)          { -			throw new BuildException("Could not execute ionCube Encoder: " . implode(' ', $output)); +            throw new BuildException("Could not execute ionCube Encoder: " . implode(' ', $output));          }        -	} +    } -	/** -	 * Constructs an argument string for the ionCube encoder -	 */ -	private function constructArguments() -	{ -		$arguments = ""; -		 -		if ($this->binary) -		{ -			$arguments.= "--binary "; -		} -		 -		if (!empty($this->optimize)) -		{ -			$arguments.= "--optimize " . $this->optimize . " "; -		} -		 -		if ($this->withoutRuntimeLoaderSupport) -		{ -			$arguments.= "--without-runtime-loader-support "; -		} -		 -		if (!empty($this->targetOption)) -		{ -			switch ($this->targetOption) -			{ -				case "replace": -				case "merge": -				case "update": -				case "rename": -				{ -					$arguments.= "--" . $this->targetOption . "-target "; -				} break; -				 -				default: -				{ -					throw new BuildException("Unknown target option '" . $this->targetOption . "'"); -				} break; -			} -		} -		 -		if (!empty($this->encrypt)) -		{ -			foreach (explode(" ", $this->encrypt) as $encrypt) -			{ -				$arguments.= "--encrypt '$encrypt' "; -			} -		} -		 -		if (!empty($this->licensePath)) -		{ -			$arguments.= "--with-license '" . $this->licensePath . "' "; -		} +    /** +     * Constructs an argument string for the ionCube encoder +     */ +    private function constructArguments() +    { +        $arguments = ''; +         +        foreach ($this->ionSwitches as $name => $value) +        { +            if ($value) +            { +                $arguments.= "--$name "; +            } +        } -		if (!empty($this->passPhrase)) -		{ -			$arguments.= "--passphrase '" . $this->passPhrase . "' "; -		} -		 -		foreach ($this->comments as $comment) -		{ -			$arguments.= "--add-comment '" . $comment->getValue() . "' "; -		} -		 -		if ($this->fromDir != "") -		{ -			$arguments .= $this->fromDir . " "; -		} +        foreach ($this->ionOptions as $name => $value) +        { +            /** +             * action-if-no-loader value is a php source snippet so it is +	         * better to handle it this way to prevent quote problems! +	         */		 +            if ($name == 'action-if-no-loader') +            { +                $arguments.= "--$name \"$value\" "; +            } +            else +            { +                $arguments.= "--$name '$value' "; +            }             +        } -		if ($this->toDir != "") -		{ -			$arguments .= "-o " . $this->toDir . " "; -		} +        foreach ($this->ionOptionsXS as $name => $value) +        { +            foreach (explode(' ', $value) as $arg) +            { +                $arguments.= "--$name '$arg' "; +            } +        } -		return $arguments; -	} +        foreach ($this->comments as $comment) +        { +            $arguments.= "--add-comment '" . $comment->getValue() . "' "; +        } +         +        if (!empty($this->targetOption)) +        { +            switch ($this->targetOption) +            { +                case "replace": +                case "merge": +                case "update": +                case "rename": +                { +                    $arguments.= "--" . $this->targetOption . "-target "; +                } break; +                 +                default: +                { +                    throw new BuildException("Unknown target option '" . $this->targetOption . "'"); +                } break; +            } +        } +         +        if ($this->fromDir != '') +        { +            $arguments .= $this->fromDir . ' '; +        } + +        if ($this->toDir != '') +        { +            $arguments .= "-o " . $this->toDir . ' '; +        } +        +        return $arguments; +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php index 70abd544..6e7ab68a 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: IoncubeLicenseTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 555e4853cd742e4ef733e3df4051c49cda527b73 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,120 +25,184 @@ require_once 'phing/tasks/ext/ioncube/IoncubeComment.php';  /**   * Invokes the ionCube "make_license" program   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: IoncubeLicenseTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 555e4853cd742e4ef733e3df4051c49cda527b73 $   * @package phing.tasks.ext.ioncube   * @since 2.2.0   */  class IoncubeLicenseTask extends Task  { -	private $ioncubePath = "/usr/local/ioncube"; -	 -	private $licensePath = ""; -	private $passPhrase = ""; -	 -	private $comments = array(); +    private $ioncubePath = "/usr/local/ioncube"; +     +    private $licensePath = ""; +    private $passPhrase = ""; +    private $allowedServer = ""; +    private $expireOn = ""; +    private $expireIn = ""; +    private $comments = array(); -	/** -	 * Sets the path to the ionCube encoder -	 */ -	function setIoncubePath($ioncubePath) -	{ -		$this->ioncubePath = $ioncubePath; -	} +    /** +     * Sets the path to the ionCube encoder +     */ +    function setIoncubePath($ioncubePath) +    { +        $this->ioncubePath = $ioncubePath; +    } -	/** -	 * Returns the path to the ionCube encoder -	 */ -	function getIoncubePath() -	{ -		return $this->ioncubePath; -	} +    /** +     * Returns the path to the ionCube encoder +     */ +    function getIoncubePath() +    { +        return $this->ioncubePath; +    } -	/** -	 * Sets the path to the license file to use -	 */ -	function setLicensePath($licensePath) -	{ -		$this->licensePath = $licensePath; -	} +    /** +     * Sets the path to the license file to use +     */ +    function setLicensePath($licensePath) +    { +        $this->licensePath = $licensePath; +    } -	/** -	 * Returns the path to the license file to use -	 */ -	function getLicensePath() -	{ -		return $this->licensePath; -	} +    /** +     * Returns the path to the license file to use +     */ +    function getLicensePath() +    { +        return $this->licensePath; +    } -	/** -	 * Sets the passphrase to use when encoding files -	 */ -	function setPassPhrase($passPhrase) -	{ -		$this->passPhrase = $passPhrase; -	} +    /** +     * Sets the passphrase to use when encoding files +     */ +    function setPassPhrase($passPhrase) +    { +        $this->passPhrase = $passPhrase; +    } -	/** -	 * Returns the passphrase to use when encoding files -	 */ -	function getPassPhrase() -	{ -		return $this->passPhrase; -	} +    /** +     * Returns the passphrase to use when encoding files +     */ +    function getPassPhrase() +    { +        return $this->passPhrase; +    } -	/** -	 * Adds a comment to be used in encoded files -	 */ -	function addComment(IoncubeComment $comment) -	{ -		$this->comments[] = $comment; -	} +    /** +     * Adds a comment to be used in encoded files +     */ +    function addComment(IoncubeComment $comment) +    { +        $this->comments[] = $comment; +    } -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$arguments = $this->constructArguments(); -		 -		$makelicense = new PhingFile($this->ioncubePath, 'make_license'); -		 -		$this->log("Running ionCube make_license..."); -		 -		exec($makelicense->__toString() . " " . $arguments . " 2>&1", $output, $return); -		 +    /** +     * Sets the --allowed-server option to use when generating the license +     */  +    function setAllowedServer($allowedServer) +    { +	$this->allowedServer = $allowedServer; +    } + +    /** +     * Returns the --allowed-server option +     */ +    function getAllowedServer() +    { +	return $this->allowedServer; +    } + +    /** +     * Sets the --expire-on option to use when generating the license +     */ +    function setExpireOn($expireOn) +    { +        $this->expireOn = $expireOn; +    } + +    /** +     * Returns the --expire-on option +     */ +    function getExpireOn() +    { +        return $this->expireOn; +    } + +    /** +     * Sets the --expire-in option to use when generating the license +     */ +    function setExpireIn($expireIn) +    { +        $this->expireIn = $expireIn; +    } + +    /** +     * Returns the --expire-in option +     */ +    function getExpireIn() +    { +        return $this->expireIn; +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $arguments = $this->constructArguments(); +         +        $makelicense = new PhingFile($this->ioncubePath, 'make_license'); +         +        $this->log("Running ionCube make_license..."); + +        exec($makelicense->__toString() . " " . $arguments . " 2>&1", $output, $return); +                  if ($return != 0)          { -			throw new BuildException("Could not execute ionCube make_license: " . implode(' ', $output)); +            throw new BuildException("Could not execute ionCube make_license: " . implode(' ', $output));          }        -	} +    } -	/** -	 * Constructs an argument string for the ionCube make_license -	 */ -	private function constructArguments() -	{ -		$arguments = ""; -		 -		if (!empty($this->passPhrase)) -		{ -			$arguments.= "--passphrase '" . $this->passPhrase . "' "; -		} -		 -		foreach ($this->comments as $comment) -		{ -			$arguments.= "--header-line '" . $comment->getValue() . "' "; -		} -		 -		if (!empty($this->licensePath)) -		{ -			$arguments.= "--o '" . $this->licensePath . "' "; -		} +    /** +     * Constructs an argument string for the ionCube make_license +     */ +    private function constructArguments() +    { +        $arguments = ""; +         +        if (!empty($this->passPhrase)) +        { +            $arguments.= "--passphrase '" . $this->passPhrase . "' "; +        } +         +        foreach ($this->comments as $comment) +        { +            $arguments.= "--header-line '" . $comment->getValue() . "' "; +        } +         +        if (!empty($this->licensePath)) +        { +            $arguments.= "--o '" . $this->licensePath . "' "; +        } -		return $arguments; +	if (!empty($this->allowedServer)) +	{ +	    $arguments.= "--allowed-server {" . $this->allowedServer . "} ";  	} + +	if (!empty($this->expireOn)) +        { +            $arguments.= "--expire-on " . $this->expireOn . " "; +        } + +	if (!empty($this->expireIn)) +        { +            $arguments.= "--expire-in " . $this->expireIn . " "; +        } + +        return $arguments; +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMin.php b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMin.php new file mode 100644 index 00000000..44766fc1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMin.php @@ -0,0 +1,292 @@ +<?php
 +/**
 + * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
 + *
 + * This is pretty much a direct port of jsmin.c to PHP with just a few
 + * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
 + * outputs to stdout, this library accepts a string as input and returns another
 + * string as output.
 + *
 + * PHP 5 or higher is required.
 + *
 + * Permission is hereby granted to use this version of the library under the
 + * same terms as jsmin.c, which has the following license:
 + *
 + * --
 + * Copyright (c) 2002 Douglas Crockford  (www.crockford.com)
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a copy of
 + * this software and associated documentation files (the "Software"), to deal in
 + * the Software without restriction, including without limitation the rights to
 + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 + * of the Software, and to permit persons to whom the Software is furnished to do
 + * so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included in all
 + * copies or substantial portions of the Software.
 + *
 + * The Software shall be used for Good, not Evil.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 + * SOFTWARE.
 + * --
 + *
 + * @package JSMin
 + * @author Ryan Grove <ryan@wonko.com>
 + * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
 + * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
 + * @license http://opensource.org/licenses/mit-license.php MIT License
 + * @version 1.1.1 (2008-03-02)
 + * @link http://code.google.com/p/jsmin-php/
 + */
 +
 +class JSMin {
 +  const ORD_LF    = 10;
 +  const ORD_SPACE = 32;
 +
 +  protected $a           = '';
 +  protected $b           = '';
 +  protected $input       = '';
 +  protected $inputIndex  = 0;
 +  protected $inputLength = 0;
 +  protected $lookAhead   = null;
 +  protected $output      = '';
 +
 +  // -- Public Static Methods --------------------------------------------------
 +
 +  public static function minify($js) {
 +    $jsmin = new JSMin($js);
 +    return $jsmin->min();
 +  }
 +
 +  // -- Public Instance Methods ------------------------------------------------
 +
 +  public function __construct($input) {
 +    $this->input       = str_replace("\r\n", "\n", $input);
 +    $this->inputLength = strlen($this->input);
 +  }
 +
 +  // -- Protected Instance Methods ---------------------------------------------
 +
 +  protected function action($d) {
 +    switch($d) {
 +      case 1:
 +        $this->output .= $this->a;
 +
 +      case 2:
 +        $this->a = $this->b;
 +
 +        if ($this->a === "'" || $this->a === '"') {
 +          for (;;) {
 +            $this->output .= $this->a;
 +            $this->a       = $this->get();
 +
 +            if ($this->a === $this->b) {
 +              break;
 +            }
 +
 +            if (ord($this->a) <= self::ORD_LF) {
 +              throw new JSMinException('Unterminated string literal.');
 +            }
 +
 +            if ($this->a === '\\') {
 +              $this->output .= $this->a;
 +              $this->a       = $this->get();
 +            }
 +          }
 +        }
 +
 +      case 3:
 +        $this->b = $this->next();
 +
 +        if ($this->b === '/' && (
 +            $this->a === '(' || $this->a === ',' || $this->a === '=' ||
 +            $this->a === ':' || $this->a === '[' || $this->a === '!' ||
 +            $this->a === '&' || $this->a === '|' || $this->a === '?')) {
 +
 +          $this->output .= $this->a . $this->b;
 +
 +          for (;;) {
 +            $this->a = $this->get();
 +
 +            if ($this->a === '/') {
 +              break;
 +            } elseif ($this->a === '\\') {
 +              $this->output .= $this->a;
 +              $this->a       = $this->get();
 +            } elseif (ord($this->a) <= self::ORD_LF) {
 +              throw new JSMinException('Unterminated regular expression '.
 +                  'literal.');
 +            }
 +
 +            $this->output .= $this->a;
 +          }
 +
 +          $this->b = $this->next();
 +        }
 +    }
 +  }
 +
 +  protected function get() {
 +    $c = $this->lookAhead;
 +    $this->lookAhead = null;
 +
 +    if ($c === null) {
 +      if ($this->inputIndex < $this->inputLength) {
 +        $c = $this->input[$this->inputIndex];
 +        $this->inputIndex += 1;
 +      } else {
 +        $c = null;
 +      }
 +    }
 +
 +    if ($c === "\r") {
 +      return "\n";
 +    }
 +
 +    if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
 +      return $c;
 +    }
 +
 +    return ' ';
 +  }
 +
 +  protected function isAlphaNum($c) {
 +    return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
 +  }
 +
 +  protected function min() {
 +    $this->a = "\n";
 +    $this->action(3);
 +
 +    while ($this->a !== null) {
 +      switch ($this->a) {
 +        case ' ':
 +          if ($this->isAlphaNum($this->b)) {
 +            $this->action(1);
 +          } else {
 +            $this->action(2);
 +          }
 +          break;
 +
 +        case "\n":
 +          switch ($this->b) {
 +            case '{':
 +            case '[':
 +            case '(':
 +            case '+':
 +            case '-':
 +              $this->action(1);
 +              break;
 +
 +            case ' ':
 +              $this->action(3);
 +              break;
 +
 +            default:
 +              if ($this->isAlphaNum($this->b)) {
 +                $this->action(1);
 +              }
 +              else {
 +                $this->action(2);
 +              }
 +          }
 +          break;
 +
 +        default:
 +          switch ($this->b) {
 +            case ' ':
 +              if ($this->isAlphaNum($this->a)) {
 +                $this->action(1);
 +                break;
 +              }
 +
 +              $this->action(3);
 +              break;
 +
 +            case "\n":
 +              switch ($this->a) {
 +                case '}':
 +                case ']':
 +                case ')':
 +                case '+':
 +                case '-':
 +                case '"':
 +                case "'":
 +                  $this->action(1);
 +                  break;
 +
 +                default:
 +                  if ($this->isAlphaNum($this->a)) {
 +                    $this->action(1);
 +                  }
 +                  else {
 +                    $this->action(3);
 +                  }
 +              }
 +              break;
 +
 +            default:
 +              $this->action(1);
 +              break;
 +          }
 +      }
 +    }
 +
 +    return $this->output;
 +  }
 +
 +  protected function next() {
 +    $c = $this->get();
 +
 +    if ($c === '/') {
 +      switch($this->peek()) {
 +        case '/':
 +          for (;;) {
 +            $c = $this->get();
 +
 +            if (ord($c) <= self::ORD_LF) {
 +              return $c;
 +            }
 +          }
 +
 +        case '*':
 +          $this->get();
 +
 +          for (;;) {
 +            switch($this->get()) {
 +              case '*':
 +                if ($this->peek() === '/') {
 +                  $this->get();
 +                  return ' ';
 +                }
 +                break;
 +
 +              case null:
 +                throw new JSMinException('Unterminated comment.');
 +            }
 +          }
 +
 +        default:
 +          return $c;
 +      }
 +    }
 +
 +    return $c;
 +  }
 +
 +  protected function peek() {
 +    $this->lookAhead = $this->get();
 +    return $this->lookAhead;
 +  }
 +}
 +
 +/**
 + * @package JSMin
 + */
 +class JSMinException extends Exception {}
 diff --git a/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMinTask.php b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMinTask.php new file mode 100644 index 00000000..26202942 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMinTask.php @@ -0,0 +1,145 @@ +<?php
 +/*
 + *  $Id: 4a9a75fcd969cfc4e26a7f2c78836389e8be7864 $
 + *
 + * 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/Task.php';
 +require_once 'phing/tasks/ext/jsmin/JsMin.php';
 +
 +/**
 + * Task to minify javascript files.
 + *
 + * Requires JSMin which can be found at http://code.google.com/p/jsmin-php/ but
 + * is bundled with Phing so no additional install of JsMin is required.
 + *
 + * @author Frank Kleine <mikey@stubbles.net>
 + * @version $Id: 4a9a75fcd969cfc4e26a7f2c78836389e8be7864 $
 + * @package phing.tasks.ext
 + * @since 2.3.0
 + */
 +class JsMinTask extends Task
 +{
 +    /**
 +     * the source files
 +     *
 +     * @var  FileSet
 +     */
 +    protected $filesets    = array();
 +    /**
 +     * Whether the build should fail, if
 +     * errors occured
 +     *
 +     * @var boolean
 +     */
 +    protected $failonerror = false;
 +    
 +    /**
 +     * Define if the target should use or not a suffix -min
 +     *
 +     * @var boolean
 +     */
 +    protected $suffix   = '-min';
 +    
 +    /**
 +     * directory to put minified javascript files into
 +     *
 +     * @var  string
 +     */
 +    protected $targetDir;
 +
 +    /**
 +     *  Nested creator, adds a set of files (nested fileset attribute).
 +     */
 +    public function createFileSet()
 +    {
 +        $num = array_push($this->filesets, new FileSet());
 +        return $this->filesets[$num - 1];
 +    }
 +
 +    /**
 +     * Whether the build should fail, if an error occured.
 +     *
 +     * @param boolean $value
 +     */
 +    public function setFailonerror($value)
 +    {
 +        $this->failonerror = $value;
 +    }
 +
 +    /**
 +     * Define if the task should or not use a suffix (-min is the default)
 +     *
 +     * @param string $value
 +     */
 +    public function setSuffix($value)
 +    {
 +        $this->suffix = $value;
 +    }
 +    
 +    /**
 +     * sets the directory where minified javascript files should be put inot
 +     *
 +     * @param  string  $targetDir
 +     */
 +    public function setTargetDir($targetDir)
 +    {
 +        $this->targetDir = $targetDir;
 +    }
 +
 +    /**
 +     * The init method: Do init steps.
 +     */
 +    public function init()
 +    {
 +        return true;
 +    }
 +
 +    /**
 +     * The main entry point method.
 +     */
 +    public function main()
 +    {
 +        foreach ($this->filesets as $fs) {
 +            try {
 +                $files    = $fs->getDirectoryScanner($this->project)->getIncludedFiles();
 +                $fullPath = realpath($fs->getDir($this->project));
 +                foreach ($files as $file) {
 +                    $this->log('Minifying file ' . $file);
 +                    try {
 +                        $target = $this->targetDir . '/' . str_replace($fullPath, '', str_replace('.js', $this->suffix . '.js', $file));
 +                        if (file_exists(dirname($target)) === false) {
 +                            mkdir(dirname($target), 0700, true);
 +                        }
 +                        
 +                        file_put_contents($target, JSMin::minify(file_get_contents($fullPath . '/' . $file)));
 +                    } catch (JSMinException $jsme) {
 +                        $this->log("Could not minify file $file: " . $jsme->getMessage(), Project::MSG_ERR);
 +                    }
 +                }
 +            } catch (BuildException $be) {
 +                // directory doesn't exist or is not readable
 +                if ($this->failonerror) {
 +                    throw $be;
 +                } else {
 +                    $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
 +                }
 +            }
 +        }
 +    }
 +}
 diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php new file mode 100755 index 00000000..fbda3ecc --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php @@ -0,0 +1,184 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/system/ExecTask.php'; + +/** + * Abstract Liquibase task. Base class for all Liquibase Phing tasks. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +abstract class AbstractLiquibaseTask extends Task +{ +    protected $jar; +    protected $changeLogFile; +    protected $username; +    protected $password; +    protected $url; +    protected $classpathref; + + +    /** +     * Sets the absolute path to liquibase jar. +     * +     * @param string the absolute path to the liquibase jar. +     */ +    public function setJar($jar) +    { +        $this->jar = $jar; +    } + + +    /** +     * Sets the absolute path to the changelog file to use. +     * +     * @param string the absolute path to the changelog file +     */ +    public function setChangeLogFile($changelogFile) +    { +        $this->changeLogFile = $changelogFile; +    } + + +    /** +     * Sets the username to connect to the database. +     * +     * @param string the username +     */ +    public function setUsername($username) +    { +        $this->username = $username; +    } + + +    /** +     * Sets the password to connect to the database. +     * +     * @param string the password +     */ +    public function setPassword($password) +    { +        $this->password = $password; +    } + + +    /** +     * Sets the url to connect to the database in jdbc style, e.g. +     * <code> +     * jdbc:postgresql://psqlhost/mydatabase +     * </code> +     * +     * @param string jdbc connection string +     */ +    public function setUrl($url) +    { +        $this->url = $url; +    } + + +    /** +     * Sets the Java classpathref. +     * +     * @param string A reference to the classpath that contains the database +     * 					driver, liquibase.jar, and the changelog.xml file +     */ +    public function setclasspathref($classpathref) +    { +        $this->classpathref = $classpathref; +    } + + +    /** +     * Ensure that correct parameters were passed in. +     * +     * @return void +     */ +    protected function checkParams() +    { +        if((null === $this->jar) or !file_exists($this->jar)) +        { +            throw new BuildException( +            sprintf( +					'Specify the name of the LiquiBase.jar. "%s" does not exist!', +            $this->jar +            ) +            ); +        } + +        if((null === $this->changeLogFile) or !file_exists($this->changeLogFile)) +        { +            throw new BuildException( +            sprintf( +					'Specify the name of the Changelog file. "%s" does not exist!', +            $this->changeLogFile +            ) +            ); +        } + +        if(null === $this->classpathref) +        { +            throw new BuildException('Please provide a classpath!'); +        } + +        if(null === $this->username) +        { +            throw new BuildException('Please provide a username for database acccess!'); +        } + +        if(null === $this->password) +        { +            throw new BuildException('Please provide a password for database acccess!'); +        } + +        if(null === $this->url) +        { +            throw new BuildException('Please provide a url for database acccess!'); +        } +    } + + +    /** +     * Executes the given command and returns the output. +     * +     * @param string the command to execute +     * @param string additional parameters +     * @return string the output of the executed command +     */ +    protected function execute($lbcommand, $lbparams = '') +    { +        $command = sprintf( +			'java -jar %s --changeLogFile=%s --url=%s --username=%s --password=%s --classpath=%s %s %s', +        escapeshellarg($this->jar), +        escapeshellarg($this->changeLogFile), +        escapeshellarg($this->url), +        escapeshellarg($this->username), +        escapeshellarg($this->password), +        escapeshellarg($this->classpathref), +        escapeshellarg($lbcommand), +        $lbparams +        ); + +        passthru($command); + +        return; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php new file mode 100755 index 00000000..77fb97d2 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php @@ -0,0 +1,39 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to create a changelog file. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseChangeLogTask extends AbstractLiquibaseTask +{ +    /** +     * @see Task::main() +     */ +    public function main() +    { +        $this->checkParams(); +        $this->execute('generateChangeLog'); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php new file mode 100755 index 00000000..e79fae92 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php @@ -0,0 +1,86 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to create a javadoc-like documentation based on current database and + * changelog. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseDbDocTask extends AbstractLiquibaseTask +{ +    protected $outputDir; + + +    /** +     * Sets the output directory where the documentation gets generated to. +     * +     * @param string the output directory +     */ +    public function setOutputDir($outputDir) +    { +        $this->outputDir = $outputDir; +    } + + +    /** +     * @see AbstractTask::checkParams() +     */ +    protected function checkParams() +    { +        parent::checkParams(); + +        if((null === $this->outputDir) or !is_dir($this->outputDir)) +        { +            if(!mkdir($this->outputDir, 0777, true)) +            { +                throw new BuildException( +                sprintf( +					'The directory "%s" does not exist and could not be created!', +                $this->outputDir +                ) +                ); +            } +        } + +        if(!is_writable($this->outputDir)) +        { +            throw new BuildException( +            sprintf( +					'The directory "%s" is not writable!', +            $this->outputDir +            ) +            ); +        } +    } + + +    /** +     * @see Task::main() +     */ +    public function main() +    { +        $this->checkParams(); +        $this->execute('dbdoc', escapeshellarg($this->outputDir)); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php new file mode 100755 index 00000000..847f1401 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php @@ -0,0 +1,137 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to create the diff between two databases. Will output the changes needed + * to convert the reference database to the database. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseDiffTask extends AbstractLiquibaseTask +{ +    protected $referenceUsername; +    protected $referencePassword; +    protected $referenceUrl; + + +    /** +     * Sets the username to connect to the reference database. +     * +     * @param string the username +     */ +    public function setReferenceUsername($username) +    { +        $this->referenceUsername = $username; +    } + + +    /** +     * Sets the password to connect to the refernce database. +     * +     * @param string the password +     */ +    public function setReferencePassword($password) +    { +        $this->referencePassword = $password; +    } + + +    /** +     * Sets the url to connect to the reference database in jdbc style, e.g. +     * <code> +     * jdbc:postgresql://psqlhost/myrefdatabase +     * </code> +     * +     * @param string jdbc connection string +     */ +    public function setReferenceUrl($url) +    { +        $this->referenceUrl = $url; +    } + + +    /** +     * @see AbstractTask::checkParams() +     */ +    protected function checkParams() +    { +        parent::checkParams(); + +        if(null === $this->referenceUsername) +        { +            throw new BuildException('Please provide a username for the reference database acccess!'); +        } + +        if(null === $this->referencePassword) +        { +            throw new BuildException('Please provide a password for the reference database acccess!'); +        } + +        if(null === $this->referenceUrl) +        { +            throw new BuildException('Please provide a url for the reference database acccess!'); +        } +    } + + +    /** +     * @see Task::main() +     */ +    public function main() +    { +        $this->checkParams(); + +        $refparams = sprintf( +			'--referenceUsername=%s --referencePassword=%s --referenceUrl=%s', +        escapeshellarg($this->referenceUsername), +        escapeshellarg($this->referencePassword), +        escapeshellarg($this->referenceUrl) +        ); + +        // save main changelog file +        $changelogFile = $this->changeLogFile; + +        // set the name of the new generated changelog file +        $this->setChangeLogFile(dirname($changelogFile).'/diffs/'.date('YmdHis').'.xml'); +        if(!is_dir(dirname($changelogFile).'/diffs/')) +        { +            mkdir(dirname($changelogFile).'/diffs/', 0777, true); +        } +        $this->execute('diffChangeLog', $refparams); + +        $xmlFile = new DOMDocument(); +        $xmlFile->load($changelogFile); + +        // create the new node +        $rootNode    = $xmlFile->getElementsByTagName('databaseChangeLog')->item(0); +        $includeNode = $rootNode->appendChild($xmlFile->createElement('include')); + +        // set the attributes for the new node +        $includeNode->setAttribute('file', str_replace(dirname($changelogFile).'/', '', $this->changeLogFile)); +        $includeNode->setAttribute('relativeToChangelogFile', 'true'); +        file_put_contents($changelogFile, $xmlFile->saveXML()); + +        $this->setChangeLogFile($changelogFile); +        $this->execute('markNextChangeSetRan'); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php new file mode 100755 index 00000000..ec5584e6 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php @@ -0,0 +1,72 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Rollbacks the database changes. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseRollbackTask extends AbstractLiquibaseTask +{ +    protected $rollbackTag; + + +    /** +     * Sets the name of the tag to roll back to. +     * +     * @param string the name to roll back to +     */ +    public function setRollbackTag($rollbackTag) +    { +        $this->rollbackTag = $rollbackTag; +    } + + +    /** +     * @see AbstractTask::checkParams() +     */ +    protected function checkParams() +    { +        parent::checkParams(); + +        if(null === $this->rollbackTag) +        { +            throw new BuildException( +            sprintf( +					'Please specify the tag to rollback to!', +            $this->rollbackTag +            ) +            ); +        } +    } + + +    /** +     * @see Task::main() +     */ +    public function main() +    { +        $this->checkParams(); +        $this->execute('rollback', escapeshellarg($this->rollbackTag)); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseTagTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseTagTask.php new file mode 100755 index 00000000..07b0e72e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseTagTask.php @@ -0,0 +1,75 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to tag the current database state. In case you tag the database multiple + * times without applying a new changelog before, the tags will overwrite each + * other! + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseTagTask extends AbstractLiquibaseTask +{ +    protected $tag; + + +    /** +     * Sets the name of tag which is used to mark the database state for +     * possible future rollback. +     * +     * @param string the name to tag the database with +     */ +    public function setTag($tag) +    { +        $this->tag = $tag; +    } + + +    /** +     * @see AbstractTask::checkParams() +     */ +    protected function checkParams() +    { +        parent::checkParams(); + +        if(null === $this->tag) +        { +            throw new BuildException( +            sprintf( +					'Please specify the tag!', +            $this->tag +            ) +            ); +        } +    } + + +    /** +     * @see Task::main() +     */ +    public function main() +    { +        $this->checkParams(); +        $this->execute('tag', escapeshellarg($this->tag)); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.php new file mode 100755 index 00000000..35162e4d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.php @@ -0,0 +1,39 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to update the database to latest version of the changelog file. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseUpdateTask extends AbstractLiquibaseTask +{ +    /** +     * @see Task::main() +     */ +    public function main() +    { +        $this->checkParams(); +        $this->execute('update'); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php new file mode 100644 index 00000000..53286f46 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php @@ -0,0 +1,109 @@ +<?php +/** + * $Id: f3a492fa25b203d3263e3463c1ab522c61bd0a9c $ + * + * 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/system/io/PhingFile.php'; + +/** + * Analyzer element for the PhpDependTask + * + * @package phing.tasks.ext.pdepend + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: f3a492fa25b203d3263e3463c1ab522c61bd0a9c $ + * @since   2.4.1 + */ +class PhpDependAnalyzerElement +{ +    /** +     * The type of the analyzer +     * +     * @var string +     */ +    protected $_type = ''; + +    /** +     * The value(s) for the analyzer option +     * +     * @var array +     */ +    protected $_value = array(); + +    /** +     * Sets the analyzer type +     * +     * @param string $type Type of the analyzer +     * +     * @return void +     */ +    public function setType($type) +    { +        $this->_type = $type; + +        switch ($this->_type) { +            case 'coderank-mode': +                break; + +            default: +                throw new BuildException( +                    "Analyzer '" . $this->_type . "' not implemented" +                ); +        } +    } + +    /** +     * Get the analyzer type +     * +     * @return string +     */ +    public function getType() +    { +        return $this->_type; +    } + +    /** +     * Sets the value for the analyzer +     * +     * @param string $value Value for the analyzer +     * +     * @return void +     */ +    public function setValue($value) +    { +        $this->_value = array(); + +        $token  = ' ,;'; +        $values = strtok($value, $token); + +        while ($values !== false) { +            $this->_value[] = $values; +            $values = strtok($token); +        } +    } + +    /** +     * Get the analyzer value +     * +     * @return string +     */ +    public function getValue() +    { +        return $this->_value; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php new file mode 100644 index 00000000..619f7377 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php @@ -0,0 +1,105 @@ +<?php +/** + * $Id: 6aa728f12c6a9b89fb93cfd39908918937a6d5f9 $ + * + * 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/system/io/PhingFile.php'; + +/** + * Logger element for the PhpDependTask. + * + * @package phing.tasks.ext.pdepend + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 6aa728f12c6a9b89fb93cfd39908918937a6d5f9 $ + * @since   2.4.1 + */ +class PhpDependLoggerElement +{ +    /** +     * The type of the logger. +     * +     * @var string +     */ +    protected $_type = ''; + +    /** +     * Output file for logger. +     * +     * @var PhingFile +     */ +    protected $_outfile = null; + +    /** +     * Sets the logger type. +     * +     * @param string $type Type of the logger +     * +     * @return void +     */ +    public function setType($type) +    { +        $this->_type = $type; + +        switch ($this->_type) { +            case 'jdepend-chart': +            case 'jdepend-xml': +            case 'overview-pyramid': +            case 'phpunit-xml': +            case 'summary-xml': +                break; + +            default: +                throw new BuildException( +                    "Logger '" . $this->_type . "' not implemented" +                ); +        } +    } + +    /** +     * Get the logger type +     * +     * @return string +     */ +    public function getType() +    { +        return $this->_type; +    } + +    /** +     * Sets the output file for the logger results. +     * +     * @param PhingFile $outfile The output file +     * +     * @return void +     */ +    public function setOutfile(PhingFile $outfile) +    { +        $this->_outfile = $outfile; +    } + +    /** +     * Get the output file. +     * +     * @return PhingFile +     */ +    public function getOutfile() +    { +        return $this->_outfile; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependTask.php b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependTask.php new file mode 100644 index 00000000..c42575b7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependTask.php @@ -0,0 +1,506 @@ +<?php +/** + *  $Id: 572bbfe2e542b864211a85de9990f5cbfe31a4cd $ + * + * 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/Task.php'; + +/** + * Runs the PHP_Depend software analyzer and metric tool. + * Performs static code analysis on a given source base. + * + * @package phing.tasks.ext.pdepend + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 572bbfe2e542b864211a85de9990f5cbfe31a4cd $ + * @since   2.4.1 + */ +class PhpDependTask extends Task +{ +    /** +     * A php source code filename or directory +     * +     * @var PhingFile +     */ +    protected $_file = null; + +    /** +     * All fileset objects assigned to this task +     * +     * @var array<FileSet> +     */ +    protected $_filesets = array(); + +    /** +     * List of allowed file extensions. Default file extensions are <b>php</b> +     * and <p>php5</b>. +     * +     * @var array<string> +     */ +    protected $_allowedFileExtensions = array('php', 'php5'); + +    /** +     * List of exclude directories. Default exclude dirs are <b>.git</b>, +     * <b>.svn</b> and <b>CVS</b>. +     * +     * @var array<string> +     */ +    protected $_excludeDirectories = array('.git', '.svn', 'CVS'); + +    /** +     * List of exclude packages +     * +     * @var array<string> +     */ +    protected $_excludePackages = array(); + +    /** +     * Should the parse ignore doc comment annotations? +     * +     * @var boolean +     */ +    protected $_withoutAnnotations = false; + +    /** +     * Should PHP_Depend treat <b>+global</b> as a regular project package? +     * +     * @var boolean +     */ +    protected $_supportBadDocumentation = false; + +    /** +     * Flag for enable/disable debugging +     * +     * @var boolean +     */ +    protected $_debug = false; + +    /** +     * PHP_Depend configuration file +     * +     * @var PhingFile +     */ +    protected $_configFile = null; + +    /** +     * Logger elements +     * +     * @var array<PhpDependLoggerElement> +     */ +    protected $_loggers = array(); + +    /** +     * Analyzer elements +     * +     * @var array<PhpDependAnalyzerElement> +     */ +    protected $_analyzers = array(); + +    /** +     * Holds the PHP_Depend runner instance +     * +     * @var PHP_Depend_TextUI_Runner +     */ +    protected $_runner = null; + +    /** +     * Flag that determines whether to halt on error +     * +     * @var boolean +     */ +    protected $_haltonerror = false; + +    /** +     * Load the necessary environment for running PHP_Depend +     * +     * @return void +     * @throws BuildException +     */ +    public function init() +    { +        /** +         * Determine PHP_Depend installation +         */ +        @include_once 'PHP/Depend/TextUI/Runner.php'; + +        if (! class_exists('PHP_Depend_TextUI_Runner')) { +            throw new BuildException( +                'PhpDependTask depends on PHP_Depend being installed ' +                . 'and on include_path', +                $this->getLocation() +            ); +        } + +        /** +         * Other dependencies that should only be loaded +         * when class is actually used +         */ +        require_once 'phing/tasks/ext/pdepend/PhpDependLoggerElement.php'; +        require_once 'phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php'; +        require_once 'PHP/Depend/Autoload.php'; +    } + +    /** +     * Set the input source file or directory +     * +     * @param PhingFile $file The input source file or directory +     * +     * @return void +     */ +    public function setFile(PhingFile $file) +    { +        $this->_file = $file; +    } + +    /** +     * Nested creator, adds a set of files (nested fileset attribute) +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() +    { +        $num = array_push($this->_filesets, new FileSet()); +        return $this->_filesets[$num-1]; +    } + +    /** +     * Sets a list of filename extensions for valid php source code files +     * +     * @param string $fileExtensions List of valid file extensions +     * +     * @return void +     */ +    public function setAllowedFileExtensions($fileExtensions) +    { +        $this->_allowedFileExtensions = array(); + +        $token = ' ,;'; +        $ext   = strtok($fileExtensions, $token); + +        while ($ext !== false) { +            $this->_allowedFileExtensions[] = $ext; +            $ext = strtok($token); +        } +    } + +    /** +     * Sets a list of exclude directories +     * +     * @param string $excludeDirectories List of exclude directories +     * +     * @return void +     */ +    public function setExcludeDirectories($excludeDirectories) +    { +        $this->_excludeDirectories = array(); + +        $token   = ' ,;'; +        $pattern = strtok($excludeDirectories, $token); + +        while ($pattern !== false) { +            $this->_excludeDirectories[] = $pattern; +            $pattern = strtok($token); +        } +    } + +    /** +     * Sets a list of exclude packages +     * +     * @param string $excludePackages Exclude packages +     * +     * @return void +     */ +    public function setExcludePackages($excludePackages) +    { +        $this->_excludePackages = array(); + +        $token   = ' ,;'; +        $pattern = strtok($excludePackages, $token); + +        while ($pattern !== false) { +            $this->_excludePackages[] = $pattern; +            $pattern = strtok($token); +        } +    } + +    /** +     * Should the parser ignore doc comment annotations? +     * +     * @param boolean $withoutAnnotations +     * +     * @return void +     */ +    public function setWithoutAnnotations($withoutAnnotations) +    { +        $this->_withoutAnnotations = StringHelper::booleanValue( +            $withoutAnnotations +        ); +    } + +    /** +     * Should PHP_Depend support projects with a bad documentation. If this +     * option is set to <b>true</b>, PHP_Depend will treat the default package +     * <b>+global</b> as a regular project package. +     * +     * @param boolean $supportBadDocumentation +     * +     * @return void +     */ +    public function setSupportBadDocumentation($supportBadDocumentation) +    { +        $this->_supportBadDocumentation = StringHelper::booleanValue( +            $supportBadDocumentation +        ); +    } + +    /** +     * Set debugging On/Off +     * +     * @param boolean $debug +     * +     * @return void +     */ +    public function setDebug($debug) +    { +        $this->_debug = StringHelper::booleanValue($debug); +    } + +    /** +     * Set halt on error +     * +     * @param boolean $haltonerror +     * +     * @return void +     */ +    public function setHaltonerror($haltonerror) +    { +        $this->_haltonerror = StringHelper::booleanValue($haltonerror); +    } + +    /** +     * Set the configuration file +     * +     * @param PhingFile $configFile The configuration file +     * +     * @return void +     */ +    public function setConfigFile(PhingFile $configFile) +    { +        $this->_configFile = $configFile; +    } + +    /** +     * Create object for nested logger element +     * +     * @return PhpDependLoggerElement +     */ +    public function createLogger() +    { +        $num = array_push($this->_loggers, new PhpDependLoggerElement()); +        return $this->_loggers[$num-1]; +    } + +    /** +     * Create object for nested analyzer element +     * +     * @return PhpDependAnalyzerElement +     */ +    public function createAnalyzer() +    { +        $num = array_push($this->_analyzers, new PhpDependAnalyzerElement()); +        return $this->_analyzers[$num-1]; +    } + +    /** +     * Executes PHP_Depend_TextUI_Runner against PhingFile or a FileSet +     * +     * @return void +     * @throws BuildException +     */ +    public function main() +    { +        $autoload = new PHP_Depend_Autoload(); +        $autoload->register(); + +        if (!isset($this->_file) and count($this->_filesets) == 0) { +            throw new BuildException( +                "Missing either a nested fileset or attribute 'file' set" +            ); +        } + +        if (count($this->_loggers) == 0) { +            throw new BuildException("Missing nested 'logger' element"); +        } + +        $this->validateLoggers(); +        $this->validateAnalyzers(); + +        $filesToParse = array(); + +        if ($this->_file instanceof PhingFile) { +            $filesToParse[] = $this->_file->__toString(); +        } else { +            // append any files in filesets +            foreach ($this->_filesets as $fs) { +                $files = $fs->getDirectoryScanner($this->project) +                            ->getIncludedFiles(); + +                foreach ($files as $filename) { +                     $f = new PhingFile($fs->getDir($this->project), $filename); +                     $filesToParse[] = $f->getAbsolutePath(); +                } +            } +        } + +        $this->_runner = new PHP_Depend_TextUI_Runner(); +        $this->_runner->addProcessListener(new PHP_Depend_TextUI_ResultPrinter()); + +        $configurationFactory = new PHP_Depend_Util_Configuration_Factory(); +        $configuration = $configurationFactory->createDefault(); +        $this->_runner->setConfiguration($configuration); + +        $this->_runner->setSourceArguments($filesToParse); + +        foreach ($this->_loggers as $logger) { +            // Register logger +            $this->_runner->addLogger( +                $logger->getType(), +                $logger->getOutfile()->__toString() +            ); +        } + +        foreach ($this->_analyzers as $analyzer) { +            // Register additional analyzer +            $this->_runner->addOption( +                $analyzer->getType(), +                $analyzer->getValue() +            ); +        } + +        // Disable annotation parsing +        if ($this->_withoutAnnotations) { +            $this->_runner->setWithoutAnnotations(); +        } + +        // Enable bad documentation support +        if ($this->_supportBadDocumentation) { +            $this->_runner->setSupportBadDocumentation(); +        } + +        // Check for suffix +        if (count($this->_allowedFileExtensions) > 0) { +            $this->_runner->setFileExtensions($this->_allowedFileExtensions); +        } + +        // Check for ignore directories +        if (count($this->_excludeDirectories) > 0) { +            $this->_runner->setExcludeDirectories($this->_excludeDirectories); +        } + +        // Check for exclude packages +        if (count($this->_excludePackages) > 0) { +            $this->_runner->setExcludePackages($this->_excludePackages); +        } + +        // Check for configuration option +        if ($this->_configFile instanceof PhingFile) { +            if (file_exists($this->_configFile->__toString()) === false) { +                throw new BuildException( +                    'The configuration file "' +                    . $this->_configFile->__toString() . '" doesn\'t exist.' +                ); +            } + +            // Load configuration file +            $config = new PHP_Depend_Util_Configuration( +                $this->_configFile->__toString(), +                null, +                true +            ); + +            // Store in config registry +            PHP_Depend_Util_ConfigurationInstance::set($config); +        } + +        if ($this->_debug) { +            require_once 'PHP/Depend/Util/Log.php'; +            // Enable debug logging +            PHP_Depend_Util_Log::setSeverity(PHP_Depend_Util_Log::DEBUG); +        } + +        $this->_runner->run(); + +        if ($this->_runner->hasParseErrors() === true) { +            $this->log('Following errors occurred:'); + +            foreach ($this->_runner->getParseErrors() as $error) { +                $this->log($error); +            } + +            if ($this->_haltonerror === true) { +                throw new BuildException('Errors occurred during parse process'); +            } +        } +    } + +    /** +     * Validates the available loggers +     * +     * @return void +     * @throws BuildException +     */ +    protected function validateLoggers() +    { +        foreach ($this->_loggers as $logger) { +            if ($logger->getType() === '') { +                throw new BuildException( +                    "Logger missing required 'type' attribute" +                ); +            } + +            if ($logger->getOutfile() === null) { +                throw new BuildException( +                    "Logger requires 'outfile' attribute" +                ); +            } +        } +    } + +    /** +     * Validates the available analyzers +     * +     * @return void +     * @throws BuildException +     */ +    protected function validateAnalyzers() +    { +        foreach ($this->_analyzers as $analyzer) { +            if ($analyzer->getType() === '') { +                throw new BuildException( +                    "Analyzer missing required 'type' attribute" +                ); +            } + +            if (count($analyzer->getValue()) === 0) { +                throw new BuildException( +                    "Analyzer missing required 'value' attribute" +                ); +            } +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php new file mode 100755 index 00000000..41f296f7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php @@ -0,0 +1,151 @@ +<?php + +/** + * 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>. + * + * @version SVN: $Id: dacfd46938db28930888f57a6924be642ec1b3d7 $ + * @package phing.tasks.ext.pdo + */ + +require_once 'phing/tasks/ext/pdo/PDOQuerySplitter.php'; + +/** + * Splits SQL source into queries using simple regular expressions + * + * Extracted from PDOSQLExecTask::runStatements() + *  + * @author  Hans Lellelid <hans@xmpl.org> + * @author  Alexey Borzov <avb@php.net> + * @package phing.tasks.ext.pdo + * @version $Id$ + */ +class DefaultPDOQuerySplitter extends PDOQuerySplitter +{ +   /** +    * Delimiter type, one of PDOSQLExecTask::DELIM_ROW or PDOSQLExecTask::DELIM_NORMAL +    * @var string +    */ +    private $delimiterType; + +   /** +    * Leftover SQL from previous line +    * @var string +    */ +    private $sqlBacklog = ''; + +   /** +    * Constructor, sets the parent task, reader with SQL source and delimiter type  +    * +    * @param PDOSQLExecTask $parent +    * @param Reader $reader +    * @param string $delimiterType +    */ +    public function __construct(PDOSQLExecTask $parent, Reader $reader, $delimiterType = PDOSQLExecTask::DELIM_NORMAL) +    { +        parent::__construct($parent, $reader); +        $this->delimiterType = $delimiterType; +    } + +   /** +    * Returns next query from SQL source, null if no more queries left +    * +    * In case of "row" delimiter type this searches for strings containing only +    * delimiters. In case of "normal" delimiter type, this uses simple regular +    * expression logic to search for delimiters. +    * +    * @return string|null +    */ +    public function nextQuery() +    { +        $sql      = ""; +        $hasQuery = false; + +        while (($line = $this->sqlReader->readLine()) !== null) { +            $delimiter = $this->parent->getDelimiter(); +            $project   = $this->parent->getOwningTarget()->getProject(); +            $line      = ProjectConfigurator::replaceProperties( +                             $project, trim($line), $project->getProperties() +                         ); + +            if (($line != $delimiter) && ( +                StringHelper::startsWith("//", $line) || +                StringHelper::startsWith("--", $line) || +                StringHelper::startsWith("#", $line))) { +                continue; +            } + +            if (strlen($line) > 4 +                    && strtoupper(substr($line,0, 4)) == "REM ") { +                continue; +            } + +            // MySQL supports defining new delimiters +            if (preg_match('/DELIMITER [\'"]?([^\'" $]+)[\'"]?/i', $line, $matches)) { +                $this->parent->setDelimiter($matches[1]); +                continue; +            } + +            if ($this->sqlBacklog !== "") { +                $sql = $this->sqlBacklog; +                $this->sqlBacklog = ""; +            } + +            $sql .= " " . $line . "\n"; + +            // SQL defines "--" as a comment to EOL +            // and in Oracle it may contain a hint +            // so we cannot just remove it, instead we must end it +            if (strpos($line, "--") !== false) { +                $sql .= "\n"; +            } + +            // DELIM_ROW doesn't need this (as far as i can tell) +            if ($this->delimiterType == PDOSQLExecTask::DELIM_NORMAL) { + +                $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter) . ")#"; + +                $sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE); +                $this->sqlBacklog = ""; +                foreach ($sqlParts as $sqlPart) { +                    // we always want to append, even if it's a delim (which will be stripped off later) +                    $this->sqlBacklog .= $sqlPart; + +                    // we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query +                    if ($sqlPart === $delimiter) { +                        $sql = $this->sqlBacklog; +                        $this->sqlBacklog = ""; +                        $hasQuery = true; +                    } +                } +            } + +            if ($hasQuery || ($this->delimiterType == PDOSQLExecTask::DELIM_ROW && $line == $delimiter)) { +                // this assumes there is always a delimter on the end of the SQL statement. +                $sql = StringHelper::substring($sql, 0, strlen($sql) - strlen($delimiter) +                                                        - ($this->delimiterType == PDOSQLExecTask::DELIM_ROW ? 2 : 1)); +                return $sql; +            } +        } + +        // Catch any statements not followed by ; +        if ($sql !== "") { +            return $sql; +        } + +        return null; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOQuerySplitter.php index df17d2d4..60a9d436 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOQuerySplitter.php @@ -1,7 +1,6 @@  <?php +  /** - * $Id: SummaryPHPUnit2ResultFormatter.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 @@ -17,42 +16,48 @@   * This software consists of voluntary contributions made by many individuals   * and is licensed under the LGPL. For more information please see   * <http://phing.info>. + * + * @version $Id: e84ada3cdb7a04da60158c7a352fbb06f17f2ca7 $ + * @package phing.tasks.ext.pdo   */ -  -require_once 'PHPUnit2/Framework/Test.php'; - -require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php';  /** - * Prints short summary output of the test to Phing's logging system. + * Base class for classes that split SQL source into separate queries   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SummaryPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */	 -class SummaryPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter + * @author  Alexey Borzov <avb@php.net> + * @package phing.tasks.ext.pdo + * @version $Id$ + */ +abstract class PDOQuerySplitter  { -	function endTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		parent::endTestSuite($suite); -		 -		$sb = "Tests run: " . $this->getRunCount(); -		$sb.= ", Failures: " . $this->getFailureCount(); -		$sb.= ", Errors: " . $this->getErrorCount(); -		$sb.= ", Time elapsed: " . $this->getElapsedTime(); -		$sb.= " sec\n"; -		 -		if ($this->out != NULL) -		{ -			$this->out->write($sb); -			$this->out->close(); -		} -	} -	 -	function getExtension() -	{ -		return NULL; -	} +   /** +    * Task that uses the splitter +    * @var PDOSQLExecTask +    */ +    protected $parent; + +   /** +    * Reader with SQL source +    * @var BufferedReader +    */ +    protected $sqlReader; + +   /** +    * Constructor, sets the parent task and reader with SQL source +    *  +    * @param PDOSQLExecTask $parent +    * @param Reader $reader +    */ +    public function __construct(PDOSQLExecTask $parent, Reader $reader) +    { +        $this->parent    = $parent; +        $this->sqlReader = new BufferedReader($reader); +    } + +   /** +    * Returns next query from SQL source, null if no more queries left +    * +    * @return string|null +    */ +    abstract public function nextQuery();  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOResultFormatter.php new file mode 100644 index 00000000..82a90ca4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOResultFormatter.php @@ -0,0 +1,84 @@ +<?php +/** + * $Id: a3237522d22494bbfaf0521ebb8f091d448f3614 $ + * + * 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/system/io/PhingFile.php'; + +/** + * Abstract  + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +abstract class PDOResultFormatter +{ +    /** +     * Output writer. +     * +     * @var Writer +     */ +    protected $out; + +    /** +     * Sets the output writer. +     * +     * @param Writer $out +     */ +    public function setOutput(Writer $out) { +        $this->out = $out; +    } + +    /** +     * Gets the output writer. +     * +     * @return Writer +     */ +    public function getOutput() { +        return $this->out; +    } + +    /** +     * Gets the preferred output filename for this formatter. +     * @return string +     */ +    abstract public function getPreferredOutfile(); + +    /** +     * Perform any initialization. +     */ +    public function initialize() { + +    } + +    /** +     * Processes a specific row from PDO result set. +     * +     * @param array $row Row of PDO result set. +     */ +    abstract public function processRow($row); + +    /** +     * Perform any final tasks and Close the writer. +     */ +    public function close() { +        $this->out->close(); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php new file mode 100644 index 00000000..bc657604 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php @@ -0,0 +1,313 @@ +<?php +/** + * $Id: a3ca52c2b277a8cbc0d2802b75f2bea18701b636 $ + * + * 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/system/io/PhingFile.php'; +require_once 'phing/tasks/ext/pdo/PlainPDOResultFormatter.php'; +require_once 'phing/tasks/ext/pdo/XMLPDOResultFormatter.php'; +require_once 'phing/util/LogWriter.php'; + +/** + * A class to represent the nested <formatter> element for PDO SQL results. + *  + * This class is inspired by the similarly-named class in the PHPUnit tasks. + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +class PDOSQLExecFormatterElement +{ +    /** +     * @var PDOResultFormatter +     */ +    private $formatter; + +    /** +     * The type of the formatter (used for built-in formatter classes). +     * @var string +     */ +    private $type = ""; + +    /** +     * Whether to use file (or write output to phing log). +     * @var boolean +     */ +    private $useFile = true; + +    /** +     * Output file for formatter. +     * @var PhingFile +     */ +    private $outfile; + +    /** +     * Print header columns. +     * @var boolean +     */ +    private $showheaders = true; + +    /** +     * Whether to format XML output. +     * @var boolean +     */ +    private $formatoutput = true; + +    /** +     * Encoding for XML output. +     * @var string +     */ +    private $encoding; + +    /** +     * Column delimiter. +     * Defaults to ',' +     * @var string +     */ +    private $coldelimiter = ","; + +    /** +     * Row delimiter. +     * Defaults to PHP_EOL. +     * @var string  +     */ +    private $rowdelimiter = PHP_EOL; + +    /** +     * Append to an existing file or overwrite it? +     * @var boolean +     */ +    private $append = false; + +    /** +     * Parameters for a custom formatter. +     * @var array Parameter[] +     */ +    private $formatterParams = array(); + +    /** +     * @var PDOSQLExecTask  +     */ +    private $parentTask; + +    /** +     * Construct a new PDOSQLExecFormatterElement with parent task. +     * @param  PDOSQLExecTask $parentTask +     */ +    public function __construct(PDOSQLExecTask $parentTask) +    { +        $this->parentTask = $parentTask; +    } + +    /** +     * Supports nested <param> element (for custom formatter classes). +     * @return Parameter +     */ +    public function createParam() { +        $num = array_push($this->parameters, new Parameter()); +        return $this->parameters[$num-1]; +    } + +    /** +     * Gets a configured output writer. +     * @return Writer +     */ +    private function getOutputWriter() +    { +        if ($this->useFile) { +            $of = $this->getOutfile(); +            if (!$of) { +                $of = new PhingFile($this->formatter->getPreferredOutfile()); +            } +            return new FileWriter($of, $this->append); +        } else { +            return $this->getDefaultOutput(); +        } +    } + +    /** +     * Configures wrapped formatter class with any attributes on this element. +     */ +    public function prepare() { + +        if (!$this->formatter) { +            throw new BuildException("No formatter specified (use type or classname attribute)", $this->getLocation()); +        } + +        $out = $this->getOutputWriter(); + +        $this->parentTask->log("Setting output writer to: " . get_class($out), Project::MSG_VERBOSE); +        $this->formatter->setOutput($out); + +        if ($this->formatter instanceof PlainPDOResultFormatter) { +            // set any options that apply to the plain formatter +            $this->formatter->setShowheaders($this->showheaders); +            $this->formatter->setRowdelim($this->rowdelimiter); +            $this->formatter->setColdelim($this->coldelimiter); +        } elseif ($this->formatter instanceof XMLPDOResultFormatter) { +            // set any options that apply to the xml formatter +            $this->formatter->setEncoding($this->encoding); +            $this->formatter->setFormatOutput($this->formatoutput); +        } + +        foreach($this->formatterParams as $param) { +            $param = new Parameter(); +            $method = 'set' . $param->getName(); +            if (!method_exists($this->formatter, $param->getName())) { +                throw new BuildException("Formatter " . get_class($this->formatter) . " does not have a $method method.", $this->getLocation()); +            } +            call_user_func(array($this->formatter, $method), $param->getValue()); +        } +    } + +    /** +     * Sets the formatter type. +     * @param string $type +     */ +    function setType($type) { +        $this->type = $type; +        if ($this->type == "xml") { +            $this->formatter = new XMLPDOResultFormatter(); +        } elseif ($this->type == "plain") { +            $this->formatter = new PlainPDOResultFormatter(); +        } else { +            throw new BuildException("Formatter '" . $this->type . "' not implemented"); +        } +    } + +    /** +     * Set classname for a custom formatter (must extend PDOResultFormatter). +     * @param string $className +     */ +    function setClassName($className) { +        $classNameNoDot = Phing::import($className); +        $this->formatter = new $classNameNoDot(); +    } + +    /** +     * Set whether to write formatter results to file. +     * @param boolean $useFile +     */ +    function setUseFile($useFile) { +        $this->useFile = (boolean) $useFile; +    } + +    /** +     * Return whether to write formatter results to file. +     * @return boolean +     */ +    function getUseFile() { +        return $this->useFile; +    } + +    /** +     * Sets the output file for the formatter results. +     * @param PhingFile $outFile +     */ +    function setOutfile(PhingFile $outfile) { +        $this->outfile = $outfile; +    } + +    /** +     * Get the output file. +     * @return PhingFile +     */ +    function getOutfile() { +        return $this->outfile; +        /* +        } else { +            return new PhingFile($this->formatter->getPreferredOutfile()); +        }*/ +    } +     +    /** +     * whether output should be appended to or overwrite +     * an existing file.  Defaults to false. +     * @param boolean $append +     */ +    public function setAppend($append) { +        $this->append = (boolean) $append; +    } +     +    /** +     * Whether output should be appended to file. +     * @return boolean +     */ +    public function getAppend() { +        return $this->append; +    } +     +    /** +     * Print headers for result sets from the  +     * statements; optional, default true. +     * @param boolean $showheaders +     */ +    public function setShowheaders($showheaders) { +        $this->showheaders = (boolean) $showheaders; +    } +     +    /** +     * Sets the column delimiter. +     * @param string $v +     */ +    public function setColdelim($v) { +        $this->coldelimiter = $v; +    } +     +    /** +     * Sets the row delimiter. +     * @param string $v +     */ +    public function setRowdelim($v) { +        $this->rowdelimiter = $v; +    } +     +    /** +     * Set the DOM document encoding. +     * @param string $v +     */ +    public function setEncoding($v) { +        $this->encoding = $v; +    } +     +    /** +     * @param boolean $v +     */ +    public function setFormatOutput($v) { +        $this->formatOutput = (boolean) $v; +    } +     +    /** +     * Gets a default output writer for this task. +     * @return Writer +     */ +    private function getDefaultOutput() +    { +        return new LogWriter($this->parentTask); +    } +     +    /** +     * Gets the formatter that has been configured based on this element. +     * @return PDOResultFormatter +     */ +    function getFormatter() { +        return $this->formatter; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecTask.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecTask.php new file mode 100755 index 00000000..3837d7ff --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecTask.php @@ -0,0 +1,606 @@ +<?php +/* + *  $Id: 8b5a8e4f80b46f8a797b058dbb9a240a1185c12b $ + * + * 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/ext/pdo/PDOTask.php'; +include_once 'phing/system/io/StringReader.php'; +include_once 'phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php'; + +/** + * Executes a series of SQL statements on a database using PDO. + * + * <p>Statements can + * either be read in from a text file using the <i>src</i> attribute or from  + * between the enclosing SQL tags.</p> + *  + * <p>Multiple statements can be provided, separated by semicolons (or the  + * defined <i>delimiter</i>). Individual lines within the statements can be  + * commented using either --, // or REM at the start of the line.</p> + *  + * <p>The <i>autocommit</i> attribute specifies whether auto-commit should be  + * turned on or off whilst executing the statements. If auto-commit is turned  + * on each statement will be executed and committed. If it is turned off the  + * statements will all be executed as one transaction.</p> + *  + * <p>The <i>onerror</i> attribute specifies how to proceed when an error occurs  + * during the execution of one of the statements.  + * The possible values are: <b>continue</b> execution, only show the error; + * <b>stop</b> execution and commit transaction; + * and <b>abort</b> execution and transaction and fail task.</p> + * + * @author    Hans Lellelid <hans@xmpl.org> (Phing) + * @author    Jeff Martin <jeff@custommonkey.org> (Ant) + * @author    Michael McCallum <gholam@xtra.co.nz> (Ant) + * @author    Tim Stephenson <tim.stephenson@sybase.com> (Ant) + * @package   phing.tasks.ext.pdo + * @version   $Id: 8b5a8e4f80b46f8a797b058dbb9a240a1185c12b $ + */ +class PDOSQLExecTask extends PDOTask { + +    /** +     * Count of how many statements were executed successfully. +     * @var int +     */ +    private $goodSql = 0; + +    /** +     * Count of total number of SQL statements. +     * @var int +     */ +    private $totalSql = 0; + +    const DELIM_ROW = "row"; +    const DELIM_NORMAL = "normal"; + +    /** +     * Database connection +     * @var PDO +     */ +    private $conn = null; + +    /** +     * Files to load +     * @var array FileSet[] +     */ +    private $filesets = array(); + +    /** +     * Files to load +     * @var array FileList[] +     */ +    private $filelists = array(); +     +    /** +     * Formatter elements. +     * @var array PDOSQLExecFormatterElement[] +     */ +    private $formatters = array(); + +    /** +     * SQL statement +     * @var PDOStatement +     */ +    private $statement; + +    /** +     * SQL input file +     * @var PhingFile +     */ +    private $srcFile; + +    /** +     * SQL input command +     * @var string +     */ +    private $sqlCommand = ""; + +    /** +     * SQL transactions to perform +     */ +    private $transactions = array(); + +    /** +     * SQL Statement delimiter (for parsing files) +     * @var string +     */ +    private $delimiter = ";"; + +    /** +     * The delimiter type indicating whether the delimiter will +     * only be recognized on a line by itself +     */ +    private $delimiterType = "normal"; // can't use constant just defined + +    /** +     * Action to perform if an error is found +     **/ +    private $onError = "abort"; + +    /** +     * Encoding to use when reading SQL statements from a file +     */ +    private $encoding = null; + +    /** +     * Fetch mode for PDO select queries. +     * @var int +     */ +    private $fetchMode; + +    /** +     * Set the name of the SQL file to be run. +     * Required unless statements are enclosed in the build file +     */ +    public function setSrc(PhingFile $srcFile) { +        $this->srcFile = $srcFile; +    } + +    /** +     * Set an inline SQL command to execute.  +     * NB: Properties are not expanded in this text. +     */ +    public function addText($sql) { +        $this->sqlCommand .= $sql; +    } + +    /** +     * Adds a set of files (nested fileset attribute). +     */ +    public function addFileset(FileSet $set) { +        $this->filesets[] = $set; +    } + +    /** +     * Adds a set of files (nested filelist attribute). +     */ +    public function addFilelist(FileList $list) { +        $this->filelists[] = $list; +    } +     +    /** +     * Creates a new PDOSQLExecFormatterElement for <formatter> element. +     * @return PDOSQLExecFormatterElement +     */ +    public function createFormatter() +    { +        $fe = new PDOSQLExecFormatterElement($this); +        $this->formatters[] = $fe; +        return $fe; +    } + +    /** +     * Add a SQL transaction to execute +     */ +    public function createTransaction() { +        $t = new PDOSQLExecTransaction($this); +        $this->transactions[] = $t; +        return $t; +    } + +    /** +     * Set the file encoding to use on the SQL files read in +     * +     * @param encoding the encoding to use on the files +     */ +    public function setEncoding($encoding) { +        $this->encoding = $encoding; +    } + +    /** +     * Set the statement delimiter. +     * +     * <p>For example, set this to "go" and delimitertype to "ROW" for +     * Sybase ASE or MS SQL Server.</p> +     * +     * @param delimiter +     */ +    public function setDelimiter($delimiter) +    { +        $this->delimiter = $delimiter; +    } + +   /** +    * Get the statement delimiter. +    * +    * @return string +    */ +    public function getDelimiter() +    { +        return $this->delimiter; +    } + +    /** +     * Set the Delimiter type for this sql task. The delimiter type takes two +     * values - normal and row. Normal means that any occurence of the delimiter +     * terminate the SQL command whereas with row, only a line containing just +     * the delimiter is recognized as the end of the command. +     * +     * @param string $delimiterType +     */ +    public function setDelimiterType($delimiterType) +    { +        $this->delimiterType = $delimiterType; +    } + +    /** +     * Action to perform when statement fails: continue, stop, or abort +     * optional; default "abort" +     */ +    public function setOnerror($action) { +        $this->onError = $action; +    } + +    /** +     * Sets the fetch mode to use for the PDO resultset. +     * @param mixed $mode The PDO fetchmode integer or constant name. +     */ +    public function setFetchmode($mode) { +        if (is_numeric($mode)) { +            $this->fetchMode = (int) $mode; +        } else { +            if (defined($mode)) { +                $this->fetchMode = constant($mode); +            } else { +                throw new BuildException("Invalid PDO fetch mode specified: " . $mode, $this->getLocation()); +            } +        } +    } + +    /** +     * Gets a default output writer for this task. +     * @return Writer +     */ +    private function getDefaultOutput() +    { +        return new LogWriter($this); +    } + +    /** +     * Load the sql file and then execute it +     * @throws BuildException +     */ +    public function main()  { + +        // Set a default fetchmode if none was specified +        // (We're doing that here to prevent errors loading the class is PDO is not available.) +        if ($this->fetchMode === null) { +            $this->fetchMode = PDO::FETCH_ASSOC; +        } + +        // Initialize the formatters here.  This ensures that any parameters passed to the formatter +        // element get passed along to the actual formatter object +        foreach($this->formatters as $fe) { +            $fe->prepare(); +        } + +        $savedTransaction = array(); +        for($i=0,$size=count($this->transactions); $i < $size; $i++) { +            $savedTransaction[] = clone $this->transactions[$i]; +        } + +        $savedSqlCommand = $this->sqlCommand; + +        $this->sqlCommand = trim($this->sqlCommand); + +        try { +            if ($this->srcFile === null && $this->sqlCommand === "" +                && empty($this->filesets) && empty($this->filelists)  +                && count($this->transactions) === 0) { +                    throw new BuildException("Source file or fileset/filelist, " +                    . "transactions or sql statement " +                    . "must be set!", $this->location); +            } + +            if ($this->srcFile !== null && !$this->srcFile->exists()) { +                throw new BuildException("Source file does not exist!", $this->location); +            } + +            // deal with the filesets +            foreach($this->filesets as $fs) { +                $ds = $fs->getDirectoryScanner($this->project); +                $srcDir = $fs->getDir($this->project); +                $srcFiles = $ds->getIncludedFiles(); +                // Make a transaction for each file +                foreach($srcFiles as $srcFile) { +                    $t = $this->createTransaction(); +                    $t->setSrc(new PhingFile($srcDir, $srcFile)); +                } +            } +             +            // process filelists +            foreach($this->filelists as $fl) { +                $srcDir  = $fl->getDir($this->project); +                $srcFiles = $fl->getFiles($this->project);                 +                // Make a transaction for each file +                foreach($srcFiles as $srcFile) { +                    $t = $this->createTransaction(); +                    $t->setSrc(new PhingFile($srcDir, $srcFile)); +                } +            } + +            // Make a transaction group for the outer command +            $t = $this->createTransaction(); +            if ($this->srcFile) $t->setSrc($this->srcFile); +            $t->addText($this->sqlCommand); +            $this->conn = $this->getConnection(); + +            try { + +                $this->statement = null; + +                // Initialize the formatters. +                $this->initFormatters(); + +                try { + +                    // Process all transactions +                    for ($i=0,$size=count($this->transactions); $i < $size; $i++) { +                        if (!$this->isAutocommit()) { +                            $this->log("Beginning transaction", Project::MSG_VERBOSE); +                            $this->conn->beginTransaction(); +                        } +                        $this->transactions[$i]->runTransaction(); +                        if (!$this->isAutocommit()) { +                            $this->log("Commiting transaction", Project::MSG_VERBOSE); +                            $this->conn->commit(); +                        } +                    } +                } catch (Exception $e) { +                    $this->closeConnection(); +                    throw $e; +                } +            } catch (IOException $e) { +                if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") { +                    try { +                        $this->conn->rollback(); +                    } catch (PDOException $ex) {} +                } +                $this->closeConnection(); +                throw new BuildException($e->getMessage(), $this->location); +            } catch (PDOException $e){ +                if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") { +                    try { +                        $this->conn->rollback(); +                    } catch (PDOException $ex) {} +                } +                $this->closeConnection(); +                throw new BuildException($e->getMessage(), $this->location); +            } +                 +            // Close the formatters. +            $this->closeFormatters(); + +            $this->log($this->goodSql . " of " . $this->totalSql . +                " SQL statements executed successfully"); + +        } catch (Exception $e) { +            $this->transactions = $savedTransaction; +            $this->sqlCommand = $savedSqlCommand; +            $this->closeConnection(); +            throw $e; +        } +        // finally { +        $this->transactions = $savedTransaction; +        $this->sqlCommand = $savedSqlCommand; +        $this->closeConnection(); +    } + + +    /** +     * read in lines and execute them +     * @throws PDOException, IOException  +     */ +    public function runStatements(Reader $reader) { + +        if (self::DELIM_NORMAL == $this->delimiterType && 0 === strpos($this->getUrl(), 'pgsql:')) { +            require_once 'phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php'; +            $splitter = new PgsqlPDOQuerySplitter($this, $reader); +        } else { +            require_once 'phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php'; +            $splitter = new DefaultPDOQuerySplitter($this, $reader, $this->delimiterType); +        } + +        try { +            while (null !== ($query = $splitter->nextQuery())) { +                $this->log("SQL: " . $query, Project::MSG_VERBOSE); +                $this->execSQL($query); +            } + +        } catch (PDOException $e) { +            throw $e; +        } +    } + +    /** +     * Whether the passed-in SQL statement is a SELECT statement. +     * This does a pretty simple match, checking to see if statement starts with +     * 'select' (but not 'select into'). +     *  +     * @param string $sql +     * @return boolean Whether specified SQL looks like a SELECT query. +     */ +    protected function isSelectSql($sql) +    { +        $sql = trim($sql); +        return (stripos($sql, 'select') === 0 && stripos($sql, 'select into ') !== 0); +    } + +    /** +     * Exec the sql statement. +     * @throws PDOException  +     */ +    protected function execSQL($sql) { + +        // Check and ignore empty statements +        if (trim($sql) == "") { +            return; +        } + +        try { +            $this->totalSql++; + +            $this->statement = $this->conn->prepare($sql); +            $this->statement->execute(); +            $this->log($this->statement->rowCount() . " rows affected", Project::MSG_VERBOSE); + +            // only call processResults() for statements that return actual data (such as 'select') +            if ($this->statement->columnCount() > 0) +            { +                $this->processResults(); +            } + +            $this->statement->closeCursor(); +            $this->statement = null; + +            $this->goodSql++; + +        } catch (PDOException $e) { +            $this->log("Failed to execute: " . $sql, Project::MSG_ERR); +            if ($this->onError != "continue") { +                throw new BuildException("Failed to execute SQL", $e); +            } +            $this->log($e->getMessage(), Project::MSG_ERR); +        } +    } + +    /** +     * Returns configured PDOResultFormatter objects (which were created from PDOSQLExecFormatterElement objects). +     * @return array PDOResultFormatter[] +     */ +    protected function getConfiguredFormatters() +    { +        $formatters = array(); +        foreach ($this->formatters as $fe) { +            $formatters[] = $fe->getFormatter(); +        } +        return $formatters; +    } + +    /** +     * Initialize the formatters. +     */ +    protected function initFormatters() { +        $formatters = $this->getConfiguredFormatters(); +        foreach ($formatters as $formatter) { +            $formatter->initialize(); +        } + +    } + +    /** +     * Run cleanup and close formatters. +     */ +    protected function closeFormatters() { +        $formatters = $this->getConfiguredFormatters(); +        foreach ($formatters as $formatter) { +            $formatter->close(); +        } +    } + +    /** +     * Passes results from query to any formatters. +     * @throws PDOException +     */ +    protected function processResults() { + +        try { + +            $this->log("Processing new result set.", Project::MSG_VERBOSE); + +            $formatters = $this->getConfiguredFormatters(); + +            while ($row = $this->statement->fetch($this->fetchMode)) { +                foreach ($formatters as $formatter) { +                    $formatter->processRow($row); +                } +            } + +        } catch (Exception $x) { +            $this->log("Error processing reults: " . $x->getMessage(), Project::MSG_ERR); +            foreach ($formatters as $formatter) { +                $formatter->close(); +            } +            throw $x; +        } + +    } + +    /** +     * Closes current connection +     */ +    protected function closeConnection() +    { +        if ($this->conn) { +            unset($this->conn); +        } +    } +} + +/** + * "Inner" class that contains the definition of a new transaction element. + * Transactions allow several files or blocks of statements + * to be executed using the same JDBC connection and commit + * operation in between. + * + * @package   phing.tasks.ext.pdo + */ +class PDOSQLExecTransaction { + +    private $tSrcFile = null; +    private $tSqlCommand = ""; +    private $parent; + +    function __construct($parent) +    { +        // Parent is required so that we can log things ... +        $this->parent = $parent; +    } + +    public function setSrc(PhingFile $src) +    { +        $this->tSrcFile = $src; +    } + +    public function addText($sql) +    { +        $this->tSqlCommand .= $sql; +    } + +    /** +     * @throws IOException, PDOException +     */ +    public function runTransaction() +    { +        if (!empty($this->tSqlCommand)) { +            $this->parent->log("Executing commands", Project::MSG_INFO); +            $this->parent->runStatements(new StringReader($this->tSqlCommand)); +        } + +        if ($this->tSrcFile !== null) { +            $this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(), +            Project::MSG_INFO); +            $reader = new FileReader($this->tSrcFile); +            $this->parent->runStatements($reader); +            $reader->close(); +        } +    } +} + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOTask.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOTask.php new file mode 100755 index 00000000..93feaa6d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOTask.php @@ -0,0 +1,215 @@ +<?php + +/* + *  $Id: de478f3e51714db7d9163b6bbc3fa64de27549cb $ + * + * 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/Task.php'; +include_once 'phing/types/Reference.php'; + +/** + * Handles PDO configuration needed by SQL type tasks. + * + * @author    Hans Lellelid <hans@xmpl.org> (Phing) + * @author    Nick Chalko <nick@chalko.com> (Ant) + * @author    Jeff Martin <jeff@custommonkey.org> (Ant) + * @author    Michael McCallum <gholam@xtra.co.nz> (Ant) + * @author    Tim Stephenson <tim.stephenson@sybase.com> (Ant) + * @version   $Id$ + * @package   phing.tasks.system + */ +abstract class PDOTask extends Task { + +    private $caching = true; + +    /** +     * Autocommit flag. Default value is false +     */ +    private $autocommit = false; +     +    /** +     * DB url. +     */ +    private $url; + +    /** +     * User name. +     */ +    private $userId; + +    /** +     * Password +     */ +    private $password; + +    /** +     * RDBMS Product needed for this SQL. +     **/ +    private $rdbms; +    +      /** +     * Initialize CreoleTask. +     * This method includes any necessary Creole libraries and triggers +     * appropriate error if they cannot be found.  This is not done in header +     * because we may want this class to be loaded w/o triggering an error. +     */ +    function init() { +        if (!class_exists('PDO')) { +            throw new Exception("PDOTask depends on PDO feature being included in PHP."); +        } +    } + +    /** +     * Caching loaders / driver. This is to avoid +     * getting an OutOfMemoryError when calling this task +     * multiple times in a row; default: true +     * @param $enable +     */ +    public function setCaching($enable) { +        $this->caching = $enable; +    } + +    /** +     * Sets the database connection URL; required. +     * @param url The url to set +     */ +    public function setUrl($url) { +        $this->url = $url; +    } +         +    /** +     * Sets the password; required. +     * @param password The password to set +     */ +    public function setPassword($password) { +        $this->password = $password; +    } + +    /** +     * Auto commit flag for database connection; +     * optional, default false. +     * @param autocommit The autocommit to set +     */ +    public function setAutocommit($autocommit) { +        $this->autocommit = $autocommit; +    } + +    /** +     * Sets the version string, execute task only if  +     * rdbms version match; optional. +     * @param version The version to set +     */ +    public function setVersion($version) { +        $this->version = $version; +    } +        +    protected function getLoaderMap() { +        return self::$loaderMap; +    } + + +    /** +     * Creates a new Connection as using the driver, url, userid and password specified. +     * The calling method is responsible for closing the connection. +     * @return Connection the newly created connection. +     * @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load. +     */ +    protected function getConnection() { +             +        if ($this->url === null) { +            throw new BuildException("Url attribute must be set!", $this->location); +        } +                 +        try { + +            $this->log("Connecting to " . $this->getUrl(), Project::MSG_VERBOSE); +             +            $user = null; +            $pass = null; +                 +            if ($this->userId) { +                $user = $this->getUserId(); +            } +             +            if ($this->password) { +                $pass = $this->getPassword(); +            }             +             +            $conn = new PDO($this->getUrl(), $user, $pass); +            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +             +            try { +                $conn->setAttribute(PDO::ATTR_AUTOCOMMIT, $this->autocommit); +            } catch (PDOException $pe) { +                $this->log("Unable to enable auto-commit for this database: " . $pe->getMessage(), Project::MSG_VERBOSE);  +            } +             +            return $conn; +             +        } catch (SQLException $e) { +            throw new BuildException($e->getMessage(), $this->location); +        } + +    } + +    public function isCaching($value) { +        $this->caching = $value; +    } + +    /** +     * Gets the autocommit. +     * @return Returns a boolean +     */ +    public function isAutocommit() { +        return $this->autocommit; +    } + +    /** +     * Gets the url. +     * @return Returns a String +     */ +    public function getUrl() { +        return $this->url; +    } + +    /** +     * Gets the userId. +     * @return Returns a String +     */ +    public function getUserId() { +        return $this->userId; +    } + +    /** +     * Set the user name for the connection; required. +     * @param userId The userId to set +     */ +    public function setUserid($userId) { +        $this->userId = $userId; +    } + +    /** +     * Gets the password. +     * @return Returns a String +     */ +    public function getPassword() { +        return $this->password; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php new file mode 100755 index 00000000..b99ac624 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php @@ -0,0 +1,291 @@ +<?php + +/** + * 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>. + * + * @version SVN: $Id: 0e3570c0e594f4396d833d77e841294855b297d9 $ + * @package phing.tasks.ext.pdo + */ + +require_once 'phing/tasks/ext/pdo/PDOQuerySplitter.php'; + +/** + * Splits PostgreSQL's dialect of SQL into separate queries + * + * Unlike DefaultPDOQuerySplitter this uses a lexer instead of regular + * expressions. This allows handling complex constructs like C-style comments + * (including nested ones) and dollar-quoted strings. + * + * @author  Alexey Borzov <avb@php.net> + * @package phing.tasks.ext.pdo + * @version $Id: 0e3570c0e594f4396d833d77e841294855b297d9 $ + * @link    http://www.phing.info/trac/ticket/499 + * @link    http://www.postgresql.org/docs/current/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING + */ +class PgsqlPDOQuerySplitter extends PDOQuerySplitter +{ +   /**#@+ +    * Lexer states +    */ +    const STATE_NORMAL            = 0; +    const STATE_SINGLE_QUOTED     = 1; +    const STATE_DOUBLE_QUOTED     = 2; +    const STATE_DOLLAR_QUOTED     = 3; +    const STATE_COMMENT_LINEEND   = 4; +    const STATE_COMMENT_MULTILINE = 5; +    const STATE_BACKSLASH         = 6; +   /**#@-*/ + +   /** +    * Nesting depth of current multiline comment +    * @var int +    */ +    protected $commentDepth = 0; + +   /** +    * Current dollar-quoting "tag" +    * @var string +    */ +    protected $quotingTag = ''; + +   /** +    * Current lexer state, one of STATE_* constants +    * @var int +    */ +    protected $state = self::STATE_NORMAL; + +   /** +    * Whether a backslash was just encountered in quoted string +    * @var bool +    */ +    protected $escape = false; + +   /** +    * Current source line being examined +    * @var string +    */ +    protected $line = ''; + +   /** +    * Position in current source line +    * @var int +    */ +    protected $inputIndex; + +   /** +    * Gets next symbol from the input, false if at end +    * +    * @return string|bool +    */ +    public function getc() +    { +        if (!strlen($this->line) || $this->inputIndex >= strlen($this->line)) { +            if (null === ($line = $this->sqlReader->readLine())) { +                return false; +            } +            $project    = $this->parent->getOwningTarget()->getProject(); +            $this->line = ProjectConfigurator::replaceProperties( +                             $project, $line, $project->getProperties() +                          ) . "\n"; +            $this->inputIndex = 0; +        } +        return $this->line[$this->inputIndex++]; +    } + +   /** +    * Bactracks one symbol on the input +    * +    * NB: we don't need ungetc() at the start of the line, so this case is +    * not handled. +    */ +    public function ungetc() +    { +        $this->inputIndex--; +    } + +   /** +    * Checks whether symbols after $ are a valid dollar-quoting tag +    * +    * @return string|bool   Dollar-quoting "tag" if it is present, false otherwise +    */ +    protected function checkDollarQuote() +    { +        $ch = $this->getc(); +        if ('$' == $ch) { +            // empty tag +            return ''; + +        } elseif (!ctype_alpha($ch) && '_' != $ch) { +            // not a delimiter +            $this->ungetc(); +            return false; + +        } else { +            $tag = $ch; +            while (false !== ($ch = $this->getc())) { +                if ('$' == $ch) { +                    return $tag; + +                } elseif (ctype_alnum($ch) || '_' == $ch) { +                    $tag .= $ch; + +                } else { +                    for ($i = 0; $i < strlen($tag); $i++) { +                        $this->ungetc(); +                    } +                    return false; +                } +            } +        } +    } + +    public function nextQuery() +    { +        $sql        = ''; +        $delimiter  = $this->parent->getDelimiter(); +        $openParens = 0; + +        while (false !== ($ch = $this->getc())) { +            switch ($this->state) { +            case self::STATE_NORMAL: +                switch ($ch) { +                case '-': +                    if ('-' == $this->getc()) { +                        $this->state = self::STATE_COMMENT_LINEEND; +                    } else { +                        $this->ungetc(); +                    } +                    break; +                case '"': +                    $this->state = self::STATE_DOUBLE_QUOTED; +                    break; +                case "'": +                    $this->state = self::STATE_SINGLE_QUOTED; +                    break; +                case '/': +                    if ('*' == $this->getc()) { +                        $this->state        = self::STATE_COMMENT_MULTILINE; +                        $this->commentDepth = 1; +                    } else { +                        $this->ungetc(); +                    } +                    break; +                case '$': +                    if (false !== ($tag = $this->checkDollarQuote())) { +                        $this->state       = self::STATE_DOLLAR_QUOTED; +                        $this->quotingTag  = $tag; +                        $sql              .= '$' . $tag . '$'; +                        continue 3; +                    } +                    break; +                case '(': +                    $openParens++; +                    break; +                case ')': +                    $openParens--; +                    break; +                // technically we can use e.g. psql's \g command as delimiter +                case $delimiter[0]: +                    // special case to allow "create rule" statements +                    // http://www.postgresql.org/docs/current/interactive/sql-createrule.html +                    if (';' == $delimiter && 0 < $openParens) { +                        break; +                    } +                    $hasQuery = true; +                    for ($i = 1; $i < strlen($delimiter); $i++) { +                        if ($delimiter[$i] != $this->getc()) { +                            $hasQuery = false; +                        } +                    } +                    if ($hasQuery) { +                        return $sql; +                    } else { +                        for ($j = 1; $j < $i; $j++) { +                            $this->ungetc(); +                        } +                    } +                } +                break; + +            case self::STATE_COMMENT_LINEEND: +                if ("\n" == $ch) { +                    $this->state = self::STATE_NORMAL; +                } +                break; + +            case self::STATE_COMMENT_MULTILINE: +                switch ($ch) { +                case '/': +                    if ('*' != $this->getc()) { +                        $this->ungetc(); +                    } else { +                        $this->commentDepth++; +                    } +                    break; + +                case '*': +                    if ('/' != $this->getc()) { +                        $this->ungetc(); +                    } else { +                        $this->commentDepth--; +                        if (0 == $this->commentDepth) { +                            $this->state = self::STATE_NORMAL; +                            continue 3; +                        } +                    } +                } + +            case self::STATE_SINGLE_QUOTED: +            case self::STATE_DOUBLE_QUOTED: +                if ($this->escape) { +                    $this->escape = false; +                    break; +                } +                $quote = $this->state == self::STATE_SINGLE_QUOTED ? "'" : '"'; +                switch ($ch) { +                    case '\\': +                        $this->escape = true; +                        break; +                    case $quote: +                        if ($quote == $this->getc()) { +                            $sql .= $quote; +                        } else { +                            $this->ungetc(); +                            $this->state = self::STATE_NORMAL; +                        } +                } + +            case self::STATE_DOLLAR_QUOTED: +                if ('$' == $ch && false !== ($tag = $this->checkDollarQuote())) { +                    if ($tag == $this->quotingTag) { +                        $this->state = self::STATE_NORMAL; +                    } +                    $sql .= '$' . $tag . '$'; +                    continue 2; +                } +            } + +            if ($this->state != self::STATE_COMMENT_LINEEND && $this->state != self::STATE_COMMENT_MULTILINE) { +                $sql .= $ch; +            } +        } +        if ('' !== $sql) { +            return $sql; +        } +        return null; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php new file mode 100644 index 00000000..3aad8ec8 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php @@ -0,0 +1,130 @@ +<?php +/** + * $Id: 0b899576769e68651a8847db8db8941aa4d784a2 $ + * + * 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/system/io/PhingFile.php'; +require_once 'phing/tasks/ext/pdo/PDOResultFormatter.php'; + +/** + * Plain text formatter for PDO results.  + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +class PlainPDOResultFormatter extends PDOResultFormatter +{ +    /** +     * Have column headers been printed? +     * @var boolean +     */ +    private $colsprinted = false; + +    /** +     * Whether to show headers. +     * @var boolean +     */ +    private $showheaders = true; + +    /** +     * Column delimiter. +     * Defaults to ',' +     * @var string +     */ +    private $coldelimiter = ","; + +    /** +     * Row delimiter. +     * Defaults to PHP_EOL. +     * @var string  +     */ +    private $rowdelimiter = PHP_EOL; + +    /** +     * Set the showheaders attribute. +     * @param boolean $v +     */ +    public function setShowheaders($v) { +        $this->showheaders = StringHelper::booleanValue($v); +    } + +    /** +     * Sets the column delimiter. +     * @param string $v +     */ +    public function setColdelim($v) { +        $this->coldelimiter = $v; +    } + +    /** +     * Sets the row delimiter. +     * @param string $v +     */ +    public function setRowdelim($v) { +        $this->rowdelimiter = $v; +    } + +    /** +     * Processes a specific row from PDO result set. +     * +     * @param array $row Row of PDO result set. +     */ +    public function processRow($row) { + +        if (!$this->colsprinted && $this->showheaders) { +            $first = true; +            foreach($row as $fieldName => $ignore) { +                if ($first) $first = false; else $line .= ","; +                $line .= $fieldName; +            } + +            $this->out->write($line); +            $this->out->write(PHP_EOL); + +            $line = ""; +            $colsprinted = true; +        } // if show headers + +        $first = true; +        foreach($row as $columnValue) { + +            if ($columnValue != null) { +                $columnValue = trim($columnValue); +            } + +            if ($first) { +                $first = false; +            } else { +                $line .= $this->coldelimiter; +            } +            $line .= $columnValue; +        } +         +        $this->out->write($line); +        $this->out->write($this->rowdelimiter); + +    } + +    public function getPreferredOutfile() +    { +        return new PhingFile('results.txt'); +    } +     +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php new file mode 100644 index 00000000..435ae6e7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php @@ -0,0 +1,141 @@ +<?php +/** + * $Id: e5c24c7ac3cd665f7877d66f64218be584429581 $ + * + * 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/system/io/PhingFile.php'; +require_once 'phing/tasks/ext/pdo/PDOResultFormatter.php'; + +/** + * XML formatter for PDO results. + *  + * This class reprsents the output of a query using a simple XML schema. + *  + * <results> + *  <row> + *   <col name="id">value</col> + *   <col name="name">value2</col> + *  </row> + *  <row> + *   <col name="id">value</col> + *   <col name="name">value2</col> + *  </row> + * </results> + * + * The actual names of the colums will depend on the fetchmode that was used + * with PDO. + *  + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +class XMLPDOResultFormatter extends PDOResultFormatter { + +    /** +     * The XML document being created. +     * @var DOMDocument +     */ +    private $doc; + +    /** +     * @var DOMElement +     */ +    private $rootNode; + +    /** +     * XML document encoding +     * +     * @var string +     */ +    private $encoding; + +    /** +     * @var boolean +     */ +    private $formatOutput = true; +     +    /** +     * Set the DOM document encoding. +     * @param string $v +     */ +    public function setEncoding($v) { +        $this->encoding = $v; +    } +     +    /** +     * @param boolean $v +     */ +    public function setFormatOutput($v) { +        $this->formatOutput = (boolean) $v; +    } + +    public function initialize() { +        $this->doc = new DOMDocument("1.0", $this->encoding); +        $this->rootNode = $this->doc->createElement('results'); +        $this->doc->appendChild($this->rootNode); +        $this->doc->formatOutput = $this->formatOutput; +    } +     +    /** +     * Processes a specific row from PDO result set. +     * +     * @param array $row Row of PDO result set. +     */ +    public function processRow($row) { +         +        $rowNode = $this->doc->createElement('row'); +        $this->rootNode->appendChild($rowNode); + +        foreach($row as $columnName => $columnValue) { +             +            $colNode = $this->doc->createElement('column'); +            $colNode->setAttribute('name', $columnName); +             +            if ($columnValue != null) { +                $columnValue = trim($columnValue); +                $colNode->nodeValue = $columnValue; +            } +            $rowNode->appendChild($colNode); +        } +         +    } +     +    /** +     * Gets a preferred filename for an output file. +     *  +     * If no filename is specified, this is where the results will be placed +     * (unless usefile=false). +     *  +     * @return string +     */ +    public function getPreferredOutfile() +    { +        return new PhingFile('results.xml'); +    } +     +    /** +     * Write XML to file and free the DOM objects. +     */ +    public function close() { +        $this->out->write($this->doc->saveXML()); +        $this->rootNode = null; +        $this->doc = null; +        parent::close(); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php b/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php index 12bd4e55..23a0e4c6 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php +++ b/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Fileset.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 7016dea93483cc99ad17a638e30f5ff57c37c78b $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -30,17 +30,11 @@ include_once 'phing/system/io/PhingFile.php';   * @author   Greg Beaver    * @author   Hans Lellelid <hans@xmpl.org>   * @package  phing.tasks.ext.pearpackage - * @version  $Revision: 1.7 $ + * @version  $Id$   */  class PEAR_PackageFileManager_Fileset {      /** -     * @access private -     * @var PEAR_PackageFileManager -     */ -    private $parent; -     -    /**       * Curent Phing Project.       * @var Project       */ @@ -60,9 +54,12 @@ class PEAR_PackageFileManager_Fileset {       * @param PEAR_PackageFileManager       * @param array       */ -    function __construct($parent, $options) +    function __construct($options)      { -        $this->parent = $parent; +        if (!is_array($options)) { +            $options = $options->getOptions(); +        } +                  $this->project = $options['phing_project'];          $this->filesets = $options['phing_filesets'];      } @@ -109,7 +106,7 @@ class PEAR_PackageFileManager_Fileset {                      $path = '/'; // for array index                  } -				$parts = explode('.', basename($file)); +                $parts = explode('.', basename($file));                  $ext = array_pop($parts);                  if (strlen($ext) == strlen($file)) {                      $ext = ''; @@ -228,4 +225,4 @@ class PEAR_PackageFileManager_Fileset {          return strnatcasecmp($a,$b);      }  } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadata.php b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadata.php new file mode 100644 index 00000000..1f7a263c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadata.php @@ -0,0 +1,55 @@ +<?php +/* + * $Id: fae81ee47ae75fc98d7848a22da93bfd4afb7a1b $ + * + * 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/ext/phar/PharMetadataElement.php'; + +/** + * @package phing.tasks.ext.phar + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + */ +class PharMetadata +{ +    /** +     * @var array +     */ +    protected $elements = array(); +    /** +     * @return PharMetadataElement +     */ +    public function createElement() +    { +        return ($this->elements[] = new PharMetadataElement()); +    } +    /** +     * @return array +     */ +    public function toArray() +    { +        $metadata = array(); + +        foreach ($this->elements as $element) { +            $metadata[$element->getName()] = $element->toArray(); +        } + +        return $metadata; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadataElement.php b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadataElement.php new file mode 100644 index 00000000..c40f68f1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadataElement.php @@ -0,0 +1,80 @@ +<?php +/* + * $Id: 4c70deae6a6f273d55f504077a3941ad926ad325 $ + * + * 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/ext/phar/PharMetadata.php'; + +/** + * @package phing.tasks.ext.phar + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + */ +class PharMetadataElement +    extends PharMetadata +{ +    /** +     * @var string +     */ +    private $name; +    /** +     * @var string +     */ +    private $value; +    /** +     * @param string $value +     */ +    public function setValue($value) +    { +        $this->value = $value; +    } +    /** +     * @param string $name +     */ +    public function setName($name) +    { +        $this->name = $name; +    } +    /** +     * @return string +     */ +    public function getName() +    { +        return $this->name; +    } +    /** +     * Return array of +     * +     * @return string|array +     */ +    public function getValue() +    { +        /* +         * Elements first! +         */ +        return (empty($this->elements) ? $this->value : $this->elements); +    } +    /** +     * @return string|array +     */ +    public function toArray() +    { +        return (empty($this->elements) ? $this->value : parent::toArray()); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phar/PharPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/phar/PharPackageTask.php new file mode 100644 index 00000000..76a4215a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phar/PharPackageTask.php @@ -0,0 +1,362 @@ +<?php +/* + * $Id: 0396ab9c461e7d7655f12c9ed3a613fe6e69f973 $ + * + * 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'; +require_once 'phing/types/IterableFileSet.php'; +require_once 'phing/tasks/ext/phar/PharMetadata.php'; + +/** + * Package task for {@link http://ru.php.net/manual/en/book.phar.php Phar technology}. + * + * @package phing.tasks.ext + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + */ +class PharPackageTask +    extends MatchingTask +{ +    /** +     * @var PhingFile +     */ +    private $destinationFile; +    /** +     * @var int +     */ +    private $compression = Phar::NONE; +    /** +     * Base directory, from where local package paths will be calculated. +     * +     * @var PhingFile +     */ +    private $baseDirectory; +    /** +     * @var PhingFile +     */ +    private $cliStubFile; +    /** +     * @var PhingFile +     */ +    private $webStubFile; +    /** +     * @var string +     */ +    private $stubPath; +    /** +     * Private key the Phar will be signed with. +     *  +     * @var PhingFile  +     */ +    private $key; +    /** +     * Password for the private key. +     *  +     * @var string  +     */ +    private $keyPassword = ''; +    /** +     * @var int +     */ +    private $signatureAlgorithm = Phar::SHA1; +    /** +     * @var array +     */ +    private $filesets = array(); +    /** +     * @var PharMetadata +     */ +    private $metadata = null; +    /** +     * @var string +     */ +    private $alias; +    /** +     * @return PharMetadata +     */ +    public function createMetadata() +    { +        return ($this->metadata = new PharMetadata()); +    } +    /** +     * @return FileSet +     */ +    public function createFileSet() +    { +        $this->fileset      = new IterableFileSet(); +        $this->filesets[]   = $this->fileset; +        return $this->fileset; +    } +    /** +     * @param string $algorithm +     */ +    public function setSignature($algorithm) +    { +        /* +         * If we don't support passed algprithm, leave old one. +         */ +        switch ($algorithm) { +            case 'md5': +                $this->signatureAlgorithm = Phar::MD5; +                break; +            case 'sha1': +                $this->signatureAlgorithm = Phar::SHA1; +                break; +            case 'sha256': +                $this->signatureAlgorithm = Phar::SHA256; +                break; +            case 'sha512': +                $this->signatureAlgorithm = Phar::SHA512; +                break; +            case 'openssl': +                $this->signatureAlgorithm = Phar::OPENSSL; +                break; +            default: +                break; +        } +    } +    /** +     * @param string $compression +     */ +    public function setCompression($compression) +    { +        /* +         * If we don't support passed compression, leave old one. +         */ +        switch ($compression) { +            case 'gzip': +                $this->compression = Phar::GZ; +                break; +            case 'bzip2': +                $this->compression = Phar::BZ2; +                break; +            default: +                break; +        } +    } +    /** +     * @param PhingFile $destinationFile +     */ +    public function setDestFile(PhingFile $destinationFile) +    { +        $this->destinationFile = $destinationFile; +    } +    /** +     * @param PhingFile $baseDirectory +     */ +    public function setBaseDir(PhingFile $baseDirectory) +    { +        $this->baseDirectory = $baseDirectory; +    } +    /** +     * @param PhingFile $stubFile +     */ +    public function setCliStub(PhingFile $stubFile) +    { +        $this->cliStubFile = $stubFile; +    } +    /** +     * @param PhingFile $stubFile +     */ +    public function setWebStub(PhingFile $stubFile) +    { +        $this->webStubFile = $stubFile; +    } +    /** +     * @param string $stubPath +     */ +    public function setStub($stubPath) +    { +        $this->stubPath = $stubPath; +    } +    /** +     * @param $alias +     */ +    public function setAlias($alias) +    { +        $this->alias = $alias; +    } +    /** +     * Sets the private key to use to sign the Phar with. +     *  +     * @param PhingFile $key Private key to sign the Phar with. +     */ +    public function setKey(PhingFile $key) +    { +        $this->key = $key; +    } +    /** +     * Password for the private key. +     *  +     * @param string $keyPassword  +     */ +    public function setKeyPassword($keyPassword) +    { +        $this->keyPassword = $keyPassword; +    } +    /** +     * @throws BuildException +     */ +    public function main() +    { +        $this->checkPreconditions(); + +        try { +            $this->log( +                'Building package: '.$this->destinationFile->__toString(), +                Project::MSG_INFO +            ); + +            /* +             * Delete old package, if exists. +             */ +            if ($this->destinationFile->exists()) { +                /* +                 * TODO Check operation for errors... +                 */ +                $this->destinationFile->delete(); +            } + +            $phar = $this->buildPhar(); +            $phar->startBuffering(); + +            $baseDirectory = realpath($this->baseDirectory->getPath()); + +            foreach ($this->filesets as $fileset) { +                $this->log( +                    'Adding specified files in ' . $fileset->getDir($this->project) . ' to package', +                    Project::MSG_VERBOSE +                ); +                 +                $phar->buildFromIterator($fileset, $baseDirectory); +            } + +            $phar->stopBuffering(); + +            /* +             * File compression, if needed. +             */ +            if (Phar::NONE != $this->compression) { +                $phar->compressFiles($this->compression); +            } +        } catch (Exception $e) { +            throw new BuildException( +                'Problem creating package: '.$e->getMessage(), +                $e, +                $this->getLocation() +            ); +        } +    } +    /** +     * @throws BuildException +     */ +    private function checkPreconditions() +    { +        if (is_null($this->destinationFile)) { +            throw new BuildException("destfile attribute must be set!", $this->getLocation()); +        } + +        if ($this->destinationFile->exists() && $this->destinationFile->isDirectory()) { +            throw new BuildException("destfile is a directory!", $this->getLocation()); +        } + +        if (!$this->destinationFile->canWrite()) { +            throw new BuildException("Can not write to the specified destfile!", $this->getLocation()); +        } +        if (!is_null($this->baseDirectory)) { +            if (!$this->baseDirectory->exists()) { +                throw new BuildException("basedir '" . (string) $this->baseDirectory . "' does not exist!", $this->getLocation()); +            } +        } +        if ($this->signatureAlgorithm == Phar::OPENSSL) { +             +            if (!extension_loaded('openssl')) { +                throw new BuildException("PHP OpenSSL extension is required for OpenSSL signing of Phars!", $this->getLocation()); +            } +             +            if (is_null($this->key)) { +                throw new BuildException("key attribute must be set for OpenSSL signing!", $this->getLocation()); +            } +             +            if (!$this->key->exists()) { +                throw new BuildException("key '" . (string) $this->key . "' does not exist!", $this->getLocation()); +            } +             +            if (!$this->key->canRead()) { +                throw new BuildException("key '" . (string) $this->key . "' cannot be read!", $this->getLocation()); +            } +        } +    } +    /** +     * Build and configure Phar object. +     * +     * @return Phar +     */ +    private function buildPhar() +    { +        $phar = new Phar($this->destinationFile); +         +        if ($this->signatureAlgorithm == Phar::OPENSSL) { +             +            // Load up the contents of the key +            $keyContents = file_get_contents($this->key); +             +            // Setup an OpenSSL resource using the private key and tell the Phar +            // to sign it using that key. +            $private = openssl_pkey_get_private($keyContents, $this->keyPassword); +            $phar->setSignatureAlgorithm(Phar::OPENSSL, $private); +             +            // Get the details so we can get the public key and write that out +            // alongside the phar. +            $details = openssl_pkey_get_details($private); +            file_put_contents($this->destinationFile . '.pubkey', $details['key']); +             +        } else { +            $phar->setSignatureAlgorithm($this->signatureAlgorithm); +        } + +        if (isset($this->stubPath)) { +            $phar->setStub(file_get_contents($this->stubPath)); +        } else { +            if (!empty($this->cliStubFile)) { +                $cliStubFile = $this->cliStubFile->getPathWithoutBase($this->baseDirectory); +            } else { +                $cliStubFile = null; +            } + +            if (!empty($this->webStubFile)) { +                $webStubFile = $this->webStubFile->getPathWithoutBase($this->baseDirectory); +            } else { +                $webStubFile = null; +            } +             +            $phar->setDefaultStub($cliStubFile, $webStubFile); +        } + +        if ($metadata = $this->metadata->toArray()) { +            $phar->setMetadata($metadata); +        } + +        if(!empty($this->alias)){ +            $phar->setAlias($this->alias); +        } + +        return $phar; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageTask.php new file mode 100644 index 00000000..80da93fa --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageTask.php @@ -0,0 +1,248 @@ +<?php +/** + * $Id: 5029881915d6a9e95320ba6e7f463f38af66cd93 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/phk/PhkPackageWebAccess.php'; + +/** + * See {@link http://phk.tekwire.net/} for more information about PHK. + * + * @author Alexey Shockov <alexey@shockov.com> + * @package phing.tasks.ext.phk + */ +class PhkPackageTask extends Task +{ +    /** +     * @var string +     */ +    private $outputFile; +    /** +     * @var string +     */ +    private $inputDirectory; +    /** +     * @var string +     */ +    private $phkCreatorPath; +    /** +     * @var PhkPackageWebAccess +     */ +    private $webAccess; +    /** +     * @var array +     */ +    private $modifiers = array(); +    /** +     * @var array +     */ +    private $options = array(); +    /** +     * @return PhkPackageWebAccess +     */ +    public function createWebAccess() +    { +        return ($this->webAccess = new PhkPackageWebAccess()); +    } +    /** +     * @param string $crcCheck +     */ +    public function setCrcCheck($crcCheck) +    { +        $this->options['crc_check'] = ('true' == $crcCheck ? true : false); +    } +    /** +     * @param string $webRunScript +     */ +    public function setWebRunScript($webRunScript) +    { +        $this->options['web_run_script'] = $webRunScript; +    } +    /** +     * @param string $cliRunScript +     */ +    public function setCliRunScript($cliRunScript) +    { +        $this->options['cli_run_script'] = $cliRunScript; +    } +    /** +     * @param string $libRunScript +     */ +    public function setLibRunScript($libRunScript) +    { +        $this->options['lib_run_script'] = $libRunScript; +    } +    /** +     * @param string $name +     */ +    public function setName($name) +    { +        $this->options['name'] =  $name; +    } +    /** +     * @param string $webMainRedirect +     */ +    public function setWebMainRedirect($webMainRedirect) +    { +        $this->options['web_main_redirect'] = ('true' == $webMainRedirect ? true : false); +    } +    /** +     * @param string $pluginClass +     */ +    public function setPluginClass($pluginClass) +    { +        $this->options['plugin_class'] = $pluginClass; +    } +    /** +     * @param string $version +     */ +    public function setVersion($version) +    { +        $this->options['version'] = $version; +    } +    /** +     * @param string $summary +     */ +    public function setSummary($summary) +    { +        $this->options['summary'] = $summary; +    } +    /** +     * @param string $inputDirectory +     */ +    public function setInputDirectory($inputDirectory) +    { +        $this->inputDirectory = $inputDirectory; +    } +    /** +     * @param string $outputFile +     */ +    public function setOutputFile($outputFile) +    { +        $this->outputFile = $outputFile; +    } +    /** +     * May be none, gzip or bzip2. +     * +     * @param string $compress +     */ +    public function setCompress($compress) +    { +        $this->modifiers['compress'] = $compress; +    } +    /** +     * True or false. +     * +     * @param srting $strip +     */ +    public function setStrip($strip) +    { +        $this->modifiers['strip'] = $strip; +    } +    /** +     * Path to PHK_Creator.phk file. +     * +     * @param srting $path +     */ +    public function setPhkCreatorPath($path) +    { +        $this->phkCreatorPath = $path; +    } +    /** +     * +     */ +    public function init() +    { + +    } +    /** +     * Main method... +     */ +    public function main() +    { +        /* +         * Check for empty first - speed ;) +         */ +        if (!is_file($this->phkCreatorPath)) { +            throw new BuildException('You must specify the "phkcreatorpath" attribute for PHK task.'); +        } +        if (empty($this->inputDirectory)) { +            throw new BuildException('You must specify the "inputdirectory" attribute for PHK task.'); +        } +        if (empty($this->outputFile)) { +            throw new BuildException('You must specify the "outputfile" attribute for PHK task.'); +        } + +        require_once $this->phkCreatorPath; + +        $mountPoint = PHK_Mgr::mount($this->outputFile, PHK::F_CREATOR); +        $phkManager = PHK_Mgr::instance($mountPoint); + +        /* +         * Add files. +         */ +        $phkManager->ftree()->merge_file_tree('/', $this->inputDirectory, $this->modifiers); + +        /* +         * Add web_access to options, if present. +         */ +        if (!is_null($this->webAccess)) { +            $webAccessPaths = $this->webAccess->getPaths(); +            if (!empty($webAccessPaths)) { +                $this->options['web_access'] = $webAccessPaths; +            } +        } + +        $phkManager->set_options($this->options); + +        /* +         * Intercept output (in PHP we can't intercept stream). +         */ +        ob_start(); +        /* +         * Create file... +         */ +        $phkManager->dump(); +        /* +         * Print with Phing log... +         */ +        $output = trim(ob_get_clean()); +        $output = explode("\n", $output); +        foreach ($output as $line) { +            /* +             * Delete all '--- *' lines. Bluh! +             */ +            /* +             * TODO Change preg_math to more faster alternative. +             */ +            if (preg_match('/^---/', $line)) { +                continue; +            } + +            $this->log($line); +        } + +        /* +         * Set rights for generated file... Don't use umask() - see +         * notes in official documentation for this function. +         */ +        chmod($this->outputFile, 0644); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccess.php b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccess.php new file mode 100644 index 00000000..9634d899 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccess.php @@ -0,0 +1,57 @@ +<?php +/** + * $Id: b6ea3e7df3c43498e8c6e105bedfd0b6e99e055a $ + * + * 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/ext/phk/PhkPackageWebAccessPath.php'; + +/** + * @author Alexey Shockov <alexey@shockov.com> + * @package phing.tasks.ext.phk + */ +class PhkPackageWebAccess +{ +    /** +     * @var array +     */ +    private $paths = array(); +    /** +     * @return PhkPackageWebAccessPath +     */ +    public function createPath() +    { +        return ($this->paths[] = new PhkPackageWebAccessPath()); +    } +    /** +     * @return array +     */ +    public function getPaths() +    { +        /* +         * Get real paths... +         */ +        $paths = array(); + +        foreach ($this->paths as $path) { +            $paths[] = $path->getPath(); +        } + +        return $paths; +    } +} diff --git a/buildscripts/phing/classes/phing/system/io/TokenReader.php b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccessPath.php index a57d994c..730a8929 100644 --- a/buildscripts/phing/classes/phing/system/io/TokenReader.php +++ b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccessPath.php @@ -1,6 +1,6 @@  <?php -/* - *  $Id: TokenReader.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $ +/** + * $Id: 755aeaf34726af2eb30c989914faad8d7aebd126 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -17,35 +17,30 @@   * This software consists of voluntary contributions made by many individuals   * and is licensed under the LGPL. For more information please see   * <http://phing.info>. -*/ - -include_once 'phing/system/io/Reader.php'; -include_once 'phing/filters/ReplaceTokens.php'; // for class Token + */  /** - * Abstract class for reading Tokens from a resource - * - * @author    Manuel Holtgewe - * @version   $Revision: 1.3 $ - * @access    public - * @package   phing.system.io + * @author Alexey Shockov <alexey@shockov.com> + * @package phing.tasks.ext.phk   */ -class TokenReader extends Reader { - +class PhkPackageWebAccessPath +{      /** -     * Constructor +     * @var string       */ -    function __construct() { +    private $path; +    /** +     * @param string $path +     */ +    public function addText($path) +    { +        $this->path = trim($path);      } -      /** -     * Reads a token from the resource and returns it as a -     * Token object. -     * -     * @access  public +     * @return string       */ -    function readToken() { +    public function getPath() +    { +        return $this->path;      }  } - -?> diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php new file mode 100644 index 00000000..e650ca72 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php @@ -0,0 +1,177 @@ +<?php +/** + * $Id: dece05e79e883b4d5e95f2215e36ce4f2f72ed2e $ + * + * 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/system/io/PhingFile.php'; + +/** + * A wrapper for the implementations of PHPCPDResultFormatter. + * + * @package phing.tasks.ext.phpcpd + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: dece05e79e883b4d5e95f2215e36ce4f2f72ed2e $ + */ +class PHPCPDFormatterElement +{ +    /** +     * The report result formatter. +     * +     * @var PHPCPDResultFormatter +     */ +    protected $_formatter = null; + +    /** +     * The type of the formatter. +     * +     * @var string +     */ +    protected $_type = ''; + +    /** +     * Whether to use file (or write output to phing log). +     * +     * @var boolean +     */ +    protected $_useFile = true; + +    /** +     * Output file for formatter. +     * +     * @var PhingFile +     */ +    protected $_outfile = null; + +    /** +     * The parent task +     * +     * @var PHPCPDTask +     */ +    private $_parentTask; + +    /** +     * Construct a new PHPCPDFormatterElement with parent task. +     * @param PHPCPDTask $parentTask +     */ +    public function __construct(PHPCPDTask $parentTask) +    { +        $this->_parentTask = $parentTask; +    } + +    /** +     * Sets the formatter type. +     * +     * @param string $type Type of the formatter +     * +     * @return void +     */ +    public function setType($type) +    { +        $this->_type = $type; + +        switch ($this->_type) { +            case 'pmd': +                if ($this->_useFile === false) { +                    throw new BuildException( +                        "Formatter '" . $this->_type +                        . "' can only print the result to an file" +                    ); +                } + +                include_once 'phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php'; +                $this->_formatter = new PMDPHPCPDResultFormatter(); +                break; + +            case 'default': +                include_once 'phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php'; +                $this->_formatter = new DefaultPHPCPDResultFormatter(); +                break; + +            default: +                throw new BuildException( +                    "Formatter '" . $this->_type . "' not implemented" +                ); +        } +    } + +    /** +     * Get the formatter type +     * +     * @return string +     */ +    public function getType() +    { +        return $this->_type; +    } + +    /** +     * Set whether to write formatter results to file or not. +     * +     * @param boolean $useFile True or false. +     * +     * @return void +     */ +    public function setUseFile($useFile) +    { +        $this->_useFile = StringHelper::booleanValue($useFile); +    } + +    /** +     * Return whether to write formatter results to file or not. +     * +     * @return boolean +     */ +    public function getUseFile() +    { +        return $this->_useFile; +    } + +    /** +     * Sets the output file for the formatter results. +     * +     * @param PhingFile $outfile The output file +     * +     * @return void +     */ +    public function setOutfile(PhingFile $outfile) +    { +        $this->_outfile = $outfile; +    } + +    /** +     * Get the output file. +     * +     * @return PhingFile +     */ +    public function getOutfile() +    { +        return $this->_outfile; +    } + +    /** +     * Returns the report formatter. +     * +     * @throws BuildException When the specified renderer does not exist. +     * @return PHPCPDResultFormatter +     */ +    public function getFormatter() +    { +        return $this->_formatter; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php new file mode 100644 index 00000000..31f76154 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php @@ -0,0 +1,312 @@ +<?php +/** + *  $Id: 8fbff39b2ca68e97afd59d5dc6d5a37c3678624e $ + * + * 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/Task.php'; + +/** + * Runs PHP Copy & Paste Detector. Checking PHP files for duplicated code. + * Refactored original PhpCpdTask provided by + * Timo Haberkern <timo.haberkern@fantastic-bits.de> + * + * @package phing.tasks.ext.phpcpd + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 8fbff39b2ca68e97afd59d5dc6d5a37c3678624e $ + */ +class PHPCPDTask extends Task +{ +    /** +     * A php source code filename or directory +     * +     * @var PhingFile +     */ +    protected $_file = null; + +    /** +     * All fileset objects assigned to this task +     * +     * @var array<FileSet> +     */ +    protected $_filesets = array(); + +    /** +     * Minimum number of identical lines. +     * +     * @var integer +     */ +    protected $_minLines = 5; + +    /** +     * Minimum number of identical tokens. +     * +     * @var integer +     */ +    protected $_minTokens = 70; + +    /** +     * List of valid file extensions for analyzed files. +     * +     * @var array +     */ +    protected $_allowedFileExtensions = array('php'); + +    /** +     * List of exclude directory patterns. +     * +     * @var array +     */ +    protected $_ignorePatterns = array('.git', '.svn', 'CVS', '.bzr', '.hg'); + +    /** +     * The format for the report +     * +     * @var string +     */ +    protected $_format = 'default'; + +    /** +     * Formatter elements. +     * +     * @var array<PHPCPDFormatterElement> +     */ +    protected $_formatters = array(); + +    /** +     * Load the necessary environment for running PHPCPD. +     * +     * @throws BuildException - if the phpcpd classes can't be loaded. +     */ +    public function init() +    { +        /** +         * Determine PHPCPD installation +         */ +        @include_once 'PHPCPD/Autoload.php'; + +        if (! class_exists('PHPCPD_TextUI_Command')) { +            throw new BuildException( +                'PHPCPDTask depends on PHPCPD being installed ' +                . 'and on include_path.', +                $this->getLocation() +            ); +        } + +        // Other dependencies that should only be loaded +        // when class is actually used +        require_once 'phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php'; +    } + +    /** +     * Set the input source file or directory. +     * +     * @param PhingFile $file The input source file or directory. +     * +     * @return void +     */ +    public function setFile(PhingFile $file) +    { +        $this->_file = $file; +    } + +    /** +     * Nested creator, adds a set of files (nested fileset attribute). +     * +     * @param FileSet $fs List of files to scan +     * +     * @return void +     */ +    public function addFileSet(FileSet $fs) +    { +        $this->_filesets[] = $fs; +    } + +    /** +     * Sets the minimum number of identical lines (default: 5). +     * +     * @param integer $minLines Minimum number of identical lines +     * +     * @return void +     */ +    public function setMinLines($minLines) +    { +        $this->_minLines = $minLines; +    } + +    /** +     * Sets the minimum number of identical tokens (default: 70). +     * +     * @param integer $minTokens Minimum number of identical tokens +     */ +    public function setMinTokens($minTokens) +    { +        $this->_minTokens = $minTokens; +    } + +    /** +     * Sets a list of filename extensions for valid php source code files. +     * +     * @param string $fileExtensions List of valid file extensions. +     * +     * @return void +     */ +    public function setAllowedFileExtensions($fileExtensions) +    { +        $this->_allowedFileExtensions = array(); + +        $token = ' ,;'; +        $ext   = strtok($fileExtensions, $token); + +        while ($ext !== false) { +            $this->_allowedFileExtensions[] = $ext; +            $ext = strtok($token); +        } +    } + +    /** +     * Sets a list of ignore patterns that is used to exclude directories from +     * the source analysis. +     * +     * @param string $ignorePatterns List of ignore patterns. +     * +     * @return void +     */ +    public function setIgnorePatterns($ignorePatterns) +    { +        $this->_ignorePatterns = array(); + +        $token   = ' ,;'; +        $pattern = strtok($ignorePatterns, $token); + +        while ($pattern !== false) { +            $this->_ignorePatterns[] = $pattern; +            $pattern = strtok($token); +        } +    } + +    /** +     * Sets the output format +     * +     * @param string $format Format of the report +     */ +    public function setFormat($format) +    { +        $this->_format = $format; +    } + +    /** +     * Create object for nested formatter element. +     * +     * @return PHPCPDFormatterElement +     */ +    public function createFormatter() +    { +        $num = array_push( +            $this->_formatters, +            new PHPCPDFormatterElement($this) +        ); +        return $this->_formatters[$num-1]; +    } + +    /** +     * Executes PHPCPD against PhingFile or a FileSet +     * +     * @return void +     */ +    public function main() +    { +        if (!isset($this->_file) and count($this->_filesets) == 0) { +            throw new BuildException( +                "Missing either a nested fileset or attribute 'file' set" +            ); +        } + +        if (count($this->_formatters) == 0) { +            // turn legacy format attribute into formatter +            $fmt = new PHPCPDFormatterElement($this); +            $fmt->setType($this->_format); +            $fmt->setUseFile(false); +            $this->_formatters[] = $fmt; +        } + +        $this->validateFormatters(); + +        $filesToParse = array(); + +        if ($this->_file instanceof PhingFile) { +            $filesToParse[] = $this->_file->getPath(); +        } else { +            // append any files in filesets +            foreach ($this->_filesets as $fs) { +                $files = $fs->getDirectoryScanner($this->project) +                            ->getIncludedFiles(); + +                foreach ($files as $filename) { +                     $f = new PhingFile($fs->getDir($this->project), $filename); +                     $filesToParse[] = $f->getAbsolutePath(); +                } +            } +        } + +        $this->log('Processing files...'); + +        $detector = new PHPCPD_Detector(new PHPCPD_Detector_Strategy_Default()); +        $clones   = $detector->copyPasteDetection( +            $filesToParse, +            $this->_minLines, +            $this->_minTokens +        ); + +        $this->log('Finished copy/paste detection'); + +        foreach ($this->_formatters as $fe) { +            $formatter = $fe->getFormatter(); +            $formatter->processClones( +                $clones, +                $this->project, +                $fe->getUseFile(), +                $fe->getOutfile() +                ); +        } +    } + +    /** +     * Validates the available formatters +     * +     * @throws BuildException +     * @return void +     */ +    protected function validateFormatters() +    { +        foreach ($this->_formatters as $fe) { +            if ($fe->getType() == '') { +                throw new BuildException( +                    "Formatter missing required 'type' attribute." +                ); +            } + +            if ($fe->getUsefile() && $fe->getOutfile() === null) { +                throw new BuildException( +                    "Formatter requires 'outfile' attribute " +                    . "when 'useFile' is true." +                ); +            } +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php new file mode 100644 index 00000000..b84da547 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php @@ -0,0 +1,58 @@ +<?php +/** + * $Id: a4825de14746285d97af9d435215ec8400406fa7 $ + * + * 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 'PHPCPD/TextUI/ResultPrinter.php'; +require_once 'phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php'; + +/** + * Prints plain text output of phpcpd run + * + * @package phing.tasks.ext.phpcpd.formatter + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: a4825de14746285d97af9d435215ec8400406fa7 $ + */ +class DefaultPHPCPDResultFormatter extends PHPCPDResultFormatter +{ + +    /** +     * Processes a list of clones. +     * +     * @param PHPCPD_CloneMap $clones +     * @param Project $project +     * @param boolean $useFile +     * @param PhingFile|null $outfile +     */ +    public function processClones(PHPCPD_CloneMap $clones, Project $project, $useFile = false, $outFile = null) +    { +        $logger = new PHPCPD_TextUI_ResultPrinter(); +        // default format goes to logs, no buffering +        ob_start(); +        $logger->printResult($clones, $project->getBaseDir(), true); +        $output = ob_get_contents(); +        ob_end_clean(); + +        if (!$useFile || empty($outFile)) { +            echo $output; +        } else { +            file_put_contents($outFile->getPath(), $output); +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php new file mode 100644 index 00000000..0cdab194 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php @@ -0,0 +1,40 @@ +<?php +/** + * $Id: 478d7a823945aa4706befb0059b2fab28743fb07 $ + * + * 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>. + */ + +/** + * This abstract class describes classes that format the results of a PHPCPD run. + * + * @package phing.tasks.ext.phpcpd.formatter + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 478d7a823945aa4706befb0059b2fab28743fb07 $ + */ +abstract class PHPCPDResultFormatter +{ +    /** +     * Processes a list of clones. +     * +     * @param PHPCPD_CloneMap $clones +     * @param Project $project +     * @param boolean $useFile +     * @param PhingFile|null $outfile +     */ +    abstract public function processClones(PHPCPD_CloneMap $clones, Project $project, $useFile = false, $outFile = null); +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php new file mode 100644 index 00000000..33c24407 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php @@ -0,0 +1,51 @@ +<?php +/** + * $Id: a336822b8c54702ba2b0590e5a812c779e5c221b $ + * + * 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 'PHPCPD/Log/XML/PMD.php'; +require_once 'phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php'; + +/** + * Prints PMD-XML output of phpcpd run + * + * @package phing.tasks.ext.phpcpd.formatter + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: a336822b8c54702ba2b0590e5a812c779e5c221b $ + */ +class PMDPHPCPDResultFormatter extends PHPCPDResultFormatter +{ +    /** +     * Processes a list of clones. +     * +     * @param PHPCPD_CloneMap $clones +     * @param Project $project +     * @param boolean $useFile +     * @param PhingFile|null $outfile +     */ +    public function processClones(PHPCPD_CloneMap $clones, Project $project, $useFile = false, $outFile = null) +    { +        if (!$useFile || empty($outFile)) { +            throw new BuildException("Output filename required for this formatter"); +        } +         +    	$logger = new PHPCPD_Log_XML_PMD($outFile); +    	$logger->processClones($clones); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php deleted file mode 100644 index 2fefc4e5..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -	/** -	 * $Id: PHPDocumentorTask.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/Task.php'; - -	/** -	 * Task to run phpDocumentor. -	 * -	 * @author Michiel Rook <michiel@trendserver.nl> -	 * @version $Id: PHPDocumentorTask.php 59 2006-04-28 14:49:47Z mrook $ -	 * @package phing.tasks.ext.phpdoc -	 */	 -	class PHPDocumentorTask extends Task -	{ -		/** -		 * The name of the executable for phpDocumentor -		 */ -		const PHPDOC = 'phpdoc'; -		 -		private $title = "Default Title"; -				 -		private $destdir = "."; -				 -		private $sourcepath = NULL; -				 -		private $output = ""; -				 -		private $linksource = false; -		 -		private $parseprivate = false; - -		/** -		 * Set the title for the generated documentation -		 */ -		function setTitle($title) -		{ -			$this->title = $title; -		} -		 -		/** -		 * Set the destination directory for the generated documentation -		 */ -		function setDestdir($destdir) -		{ -			$this->destdir = $destdir; -		} -		 -		/** -		 * Set the source path -		 */ -		function setSourcepath(Path $sourcepath) -		{ -			if ($this->sourcepath === NULL) -			{ -				$this->sourcepath = $sourcepath; -			} -			else -			{ -				$this->sourcepath->append($sourcepath); -			} -		} -		 -		/** -		 * Set the output type -		 */		 -		function setOutput($output) -		{ -			$this->output = $output; -		} -		 -		/** -		 * Should sources be linked in the generated documentation -		 */ -		function setLinksource($linksource) -		{ -			$this->linksource = $linksource; -		} -		 -		/** -		 * Should private members/classes be documented -		 */ -		function setParseprivate($parseprivate) -		{ -			$this->parseprivate = $parseprivate; -		} -		 -		/** -		 * Main entrypoint of the task -		 */ -		function main() -		{ -			$arguments = $this->constructArguments(); -			 -			exec(self::PHPDOC . " " . $arguments, $output, $retval); -		} -		 -		/** -		 * Constructs an argument string for phpDocumentor -		 */ -		private function constructArguments() -		{ -			$arguments = "-q "; -			 -			if ($this->title) -			{ -				$arguments.= "-ti \"" . $this->title . "\" "; -			} -			 -			if ($this->destdir) -			{ -				$arguments.= "-t " . $this->destdir . " "; -			} -			 -			if ($this->sourcepath !== NULL) -			{ -				$arguments.= "-d " . $this->sourcepath->__toString() . " "; -			} -			 -			if ($this->output) -			{ -				$arguments.= "-o " . $this->output . " "; -			} -			 -			if ($this->linksource) -			{ -				$arguments.= "-s "; -			} -			 -			if ($this->parseprivate) -			{ -				$arguments.= "-pp "; -			} -						 -			return $arguments; -		} -	}; - -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php new file mode 100644 index 00000000..462b1d99 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php @@ -0,0 +1,98 @@ +<?php +/** + * $Id: 73c919ab2044bf6582f52bd7ccb0184019d52f53 $ + * + * 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 'PhpDocumentor/phpDocumentor/Errors.inc'; + +/** + * Phing subclass of the ErrorTracker class provided with PhpDocumentor to work around limitations in PhpDocumentor API. + *  + * This class is necessary because PhpDocumentor does directly output errors and + * warnings occured during testing for undocumented elements to stdout. + * This class is injected globally to force PhpDocumentor to use phing's logging + * mechanism. + *  + * Obviously this is far from ideal, but there's also no solution given the inflexibility of the + * PhpDocumentor design.  + *  + * @author Timo A. Hummel <privat@timohummel.com> @author felicitus + * @version $Id: 73c919ab2044bf6582f52bd7ccb0184019d52f53 $ + * @package phing.tasks.ext.phpdoc + */  +class PhingPhpDocumentorErrorTracker extends ErrorTracker { +	 +	/* +	 * @var object	Reference to the task we're called with +	 */ +	private $task; +	 +	/** +	 * Outputs a warning. This is an almost 1:1 copy from PhpDocumentor, +	 * we're just processing the warning text and send it to phing's logger. +	 *  +	 * @param $num integer	Number of parameters +	 * @return nothing +	 */ +	function addWarning ($num) { +        $a = array('', '', '', ''); +        if (func_num_args()>1) { +            for ($i=1;$i<func_num_args();$i++) { +                $a[$i - 1] = func_get_arg($i); +            } +        } +         +       $message = sprintf($GLOBALS['phpDocumentor_warning_descrip'][$num], $a[0], $a[1], $a[2], $a[3]); +       $this->task->log($message, Project::MSG_WARN); +		 +	} +	 +	/** +	 * Outputs an error. This is an almost 1:1 copy from PhpDocumentor, +	 * we're just processing the error text and send it to phing's logger. +	 *  +	 * @param $num integer	Number of parameters +	 * @return nothing +	 */ +	 +	function addError ($num) { +        $a = array('', '', '', ''); +        if (func_num_args()>1) { +            for ($i=1;$i<func_num_args();$i++) { +                $a[$i - 1] = func_get_arg($i); +            } +        } +         +       $message = sprintf($GLOBALS['phpDocumentor_error_descrip'][$num], $a[0], $a[1], $a[2], $a[3]); +       $this->task->log($message, Project::MSG_ERR); +		 +	} +	 +	/** +	 * Sets the task we're working with. This is necessary since we need to be +	 * able to call the method "log". +	 *  +	 * @param object $task	The task we're working with +	 * @return nothing +	 */ +	public function setTask ($task) { +		$this->task = $task; +	} +	 +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php new file mode 100644 index 00000000..62662b0b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php @@ -0,0 +1,230 @@ +<?php +/** + * $Id: cde99d501839daf8c9dd9df61ee6cce7caad6b3e $ + * + * 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 'PhpDocumentor/phpDocumentor/Setup.inc.php'; + +/** + * Phing subclass of the phpDocumentor_setup class provided with PhpDocumentor to work around limitations in PhpDocumentor API. + *  + * This class is necessary because phpDocumentor_setup does not expose a complete API for setting configuration options.  Because + * this class must directly modify some "private" GLOBAL(!) configuration variables, it is liable to break if the PhpDocumentor + * internal implementation changes.  Obviously this is far from ideal, but there's also no solution given the inflexibility of the + * PhpDocumentor design.  + *  + * @author Hans Lellelid <hans@xmpl.org>@author hans + * @version $Id: cde99d501839daf8c9dd9df61ee6cce7caad6b3e $ + * @package phing.tasks.ext.phpdoc + */ +class PhingPhpDocumentorSetup extends phpDocumentor_setup { +     +    /** +     * Constructs a new PhingPhpDocumentorSetup. +     * +     * @param string $configDir Directory in which to look for configuration files. +     * @param object $task		The task we're working with, so we can pass it on to the ErrorTracker +     */ +    public function __construct($configdir = null, $task) { +        global $_phpDocumentor_cvsphpfile_exts, $_phpDocumentor_setting, $_phpDocumentor_phpfile_exts; +         +        $this->setup = new Io(); +        $this->render = new phpDocumentor_IntermediateParser("Default Title"); +         +        $GLOBALS['_phpDocumentor_install_dir'] = $configdir; +        $this->parseIni(); +         +        // These redundant-looking lines seem to actually make a difference. +        // See: http://phing.info/trac/ticket/150 +        $_phpDocumentor_phpfile_exts = $GLOBALS['_phpDocumentor_phpfile_exts']; +        $_phpDocumentor_cvsphpfile_exts = $GLOBALS['_phpDocumentor_cvsphpfile_exts']; + +        if (tokenizer_ext) { +            $this->parse = new phpDocumentorTParser(); +        } else { +            $this->parse = new Parser(); +        } +         +        $this->setMemoryLimit(); +         +        include_once 'phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php'; +         +        // Inject our own error tracker to PhpDocumentor +        $GLOBALS['phpDocumentor_errors'] = new PhingPhpDocumentorErrorTracker; +        $GLOBALS['phpDocumentor_errors']->setTask($task); +         +    } +     +    /** +     * Set whether to generate sourcecode for each file parsed. +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param bool $b +     */ +    public function setGenerateSourcecode($b) { +        global $_phpDocumentor_setting; +        $_phpDocumentor_setting['sourcecode'] = (boolean) $b; +    } +     +    /** +     * Set an array of README/INSTALL/CHANGELOG file paths.  +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param array $files Absolute paths to files. +     */ +    public function setRicFiles($files) { +        global $_phpDocumentor_RIC_files; +        $_phpDocumentor_RIC_files = $files; +    } +     +    /** +     * Set comma-separated list of tags to ignore. +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param string $tags +     */ +    public function setIgnoreTags($tags) { +        global $_phpDocumentor_setting;  +        $ignoretags = explode(',', $tags); +        $ignoretags = array_map('trim', $ignoretags); +        $tags = array(); +        foreach($ignoretags as $tag) { +            if (!in_array($tag,array('@global', '@access', '@package', '@ignore', '@name', '@param', '@return', '@staticvar', '@var'))) +                $tags[] = $tag; +        } +        $_phpDocumentor_setting['ignoretags'] = $tags; +    } +     +    /** +     * Set whether to parse dirs as PEAR repos.  +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param bool $b +     */ +    public function setPear($b) { +        global $_phpDocumentor_setting; +        $_phpDocumentor_setting['pear'] = (boolean) $b; +    } +     +    /** +     * Set fullpath to directory to look in for examples.  +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param string $dir +     */ +    public function setExamplesDir($dir) { +        global $_phpDocumentor_setting; +        $_phpDocumentor_setting['examplesdir'] = $dir; +    } +     +    /** +     * Sets the default package name. +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param string $name +     */ +    public function setDefaultPackageName($name) { +        $GLOBALS['phpDocumentor_DefaultPackageName'] = trim($name); +    } +     +    /** +     * Sets the default category name. +     * +     * This method exists as a hack because there is no API exposed for this in PhpDocumentor. +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     * @param string $name +     */ +    public function setDefaultCategoryName($name) { +        $GLOBALS['phpDocumentor_DefaultCategoryName'] = trim($name); +    } +     +    /** +     * Enables quiet mode. +     * +     * This method exists as a hack because the API exposed for this method in PhpDocumentor +     * doesn't work correctly. +     *  +     * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this +     * is subject to break if PhpDocumentor internals changes.   +     *  +     */ +    public function setQuietMode() { +        global $_phpDocumentor_setting; +        $_phpDocumentor_setting['quiet'] = true; +        parent::setQuietMode(); +    } + +    /** +     * Control whether or not warnings will be shown for undocumented elements. +     * Useful for identifying classes and methods that haven't yet been +     * documented. +     *  +     * @param  bool  $bEnable  +     */ +    public function setUndocumentedelements($bEnable) { +        $this->render->setUndocumentedElementWarningsMode($bEnable); +    } + +    /** +     * custom tags, will be recognized and put in tags[] instead of +     * unknowntags[] +     * +     * This method exists as a hack because the API exposed for this method in +     * PhpDocumentor doesn't work correctly. +     *  +     * Note that because we are setting a "private" GLOBAL(!!) config var with +     * this value, this is subject to break if PhpDocumentor internals changes. +     *  +     * @param  string  $sCustomtags  +     */ +    public function setCustomtags($sCustomtags) { +        global $_phpDocumentor_setting; +        $_phpDocumentor_setting['customtags'] = $sCustomtags; +    } +     +    /** +     * Files to ignore +     * +     * @param  string  $sIgnore +     */ +    public function setIgnore($sIgnore) { +        global $_phpDocumentor_setting; +        $_phpDocumentor_setting['ignore'] = $sIgnore; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.php new file mode 100755 index 00000000..70fcc9e2 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.php @@ -0,0 +1,224 @@ +<?php +/* + *  $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * + * 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/Task.php'; +require_once 'phing/system/io/FileOutputStream.php'; + +/** + * PhpDocumentor2 Task (http://www.phpdoc.org) + * Based on the DocBlox Task + * + * @author    Michiel Rook <mrook@php.net> + * @version   $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * @since     2.4.10 + * @package   phing.tasks.ext.phpdoc + */ +class PhpDocumentor2Task extends Task +{ +    /** +     * List of filesets +     * @var FileSet[] +     */ +    private $filesets = array(); +     +    /** +     * Destination/target directory +     * @var PhingFile +     */ +    private $destDir = null; + +    /** +     * name of the template to use +     * @var string +     */ +    private $template = "responsive"; +     +    /** +     * Title of the project +     * @var string +     */ +    private $title = ""; +     +    /** +     * Force phpDocumentor to be quiet +     * @var boolean +     */ +    private $quiet = true; +     +    /** +     * Nested creator, adds a set of files (nested fileset attribute). +     *  +     * @return FileSet +     */ +    public function createFileSet() +    { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } +     +    /** +     * Sets destination/target directory +     * @param PhingFile $destDir +     */ +    public function setDestDir(PhingFile $destDir) +    { +        $this->destDir = $destDir; +    } + +    /** +     * Convenience setter (@see setDestDir) +     * @param PhingFile $output +     */ +    public function setOutput(PhingFile $output) +    { +        $this->destDir = $output; +    } + +    /** +     * Sets the template to use +     * @param strings $template +     */ +    public function setTemplate($template) +    { +        $this->template = (string) $template; +    } +     +    /** +     * Sets the title of the project +     * @param strings $title +     */ +    public function setTitle($title) +    { +        $this->title = (string) $title; +    } +     +    /** +     * Forces phpDocumentor to be quiet +     * @param boolean $quiet +     */ +    public function setQuiet($quiet) +    { +        $this->quiet = (boolean) $quiet; +    } +     +    /** +     * Finds and initializes the phpDocumentor installation +     */ +    private function initializePhpDocumentor() +    { +        $phpDocumentorPath = null; +         +        foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) { +            $testPhpDocumentorPath = $path . DIRECTORY_SEPARATOR . 'phpDocumentor' . DIRECTORY_SEPARATOR . 'src'; + +            if (file_exists($testPhpDocumentorPath)) { +                $phpDocumentorPath = $testPhpDocumentorPath; +            } +        } + +        if (empty($phpDocumentorPath)) { +            throw new BuildException("Please make sure PhpDocumentor 2 is installed and on the include_path.", $this->getLocation()); +        } +         +        set_include_path($phpDocumentorPath . PATH_SEPARATOR . get_include_path()); +         +        require_once $phpDocumentorPath . '/phpDocumentor/Bootstrap.php'; +             +        $bootstrap = phpDocumentor_Bootstrap::createInstance(); +             +        $autoloader = $bootstrap->registerAutoloader(); +             +        if ($this->quiet) { +            phpDocumentor_Core_Abstract::config()->logging->level = 'quiet'; +        } else { +            phpDocumentor_Core_Abstract::config()->logging->level = 'debug'; +        } +             +        $bootstrap->registerPlugins($autoloader); +    } +     +    /** +     * Build a list of files (from the fileset elements) +     * and call the phpDocumentor parser +     * +     * @return string +     */ +    private function parseFiles() +    { +        $parser = new phpDocumentor_Parser(); +         +        //Only initialize the dispatcher when not already done +        if (is_null(phpDocumentor_Parser_Abstract::$event_dispatcher)) { +            phpDocumentor_Parser_Abstract::$event_dispatcher = new sfEventDispatcher(); +        } +        $parser->setTitle($this->title); +         +        $paths = array(); +         +        // filesets +        foreach ($this->filesets as $fs) { +            $ds    = $fs->getDirectoryScanner($this->project); +            $dir   = $fs->getDir($this->project); +            $srcFiles = $ds->getIncludedFiles(); +             +            foreach ($srcFiles as $file) { +                $paths[] = $dir . FileSystem::getFileSystem()->getSeparator() . $file; +            } +        } +         +        $this->log("Will parse " . count($paths) . " file(s)", Project::MSG_VERBOSE); +         +        $files = new phpDocumentor_Parser_Files(); +        $files->addFiles($paths); +         +        $parser->setPath($files->getProjectRoot()); +         +        return $parser->parseFiles($files); +    } + +    /** +     * Task entry point +     * @see Task::main() +     */ +    public function main() +    { +        if (empty($this->destDir)) { +            throw new BuildException("You must supply the 'destdir' attribute", $this->getLocation()); +        } +         +        if (empty($this->filesets)) { +            throw new BuildException("You have not specified any files to include (<fileset>)", $this->getLocation()); +        } +         +        $this->initializePhpDocumentor(); +         +        $xml = $this->parseFiles(); +         +        $this->log("Transforming...", Project::MSG_VERBOSE); +         +        $transformer = new phpDocumentor_Transformer(); +        $transformer->setTemplatesPath(phpDocumentor_Core_Abstract::config()->paths->templates); +        $transformer->setTemplates($this->template); +        $transformer->setSource($xml); +        $transformer->setTarget($this->destDir->getAbsolutePath()); +        $transformer->execute(); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php new file mode 100755 index 00000000..fb2a0b2b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php @@ -0,0 +1,265 @@ +<?php + +/** + * $Id: 6a6c740651bb91c9854fcdf0cb1d7e768b84f805 $ + * + * 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/ext/phpdoc/PhpDocumentorTask.php'; + +/** + * Task to run phpDocumentor with an external process + *  + * This classes uses the commandline phpdoc script to build documentation. + * Use this task instead of the PhpDocumentorTask when you've a clash with the + * Smarty libraries. + * + * @author Michiel Rook <mrook@php.net> + * @author Markus Fischer <markus@fischer.name> + * @version $Id: 6a6c740651bb91c9854fcdf0cb1d7e768b84f805 $ + * @package phing.tasks.ext.phpdoc + */  +class PhpDocumentorExternalTask extends PhpDocumentorTask +{ +    /** +     * The path to the executable for phpDocumentor +     */ +    protected $programPath = 'phpdoc'; + +    protected $sourcepath = NULL; + +    /** +     * @var bool  ignore symlinks to other files or directories +     */ +    protected $ignoresymlinks = false; + +    /** +     * Sets the path to the phpDocumentor executable +     */ +    public function setProgramPath($programPath) +    { +        $this->programPath = $programPath; +    } + +    /** +     * Returns the path to the phpDocumentor executable +     */ +    public function getProgramPath() +    { +        return $this->programPath; +    } + +    /** +     * Set the source path. A directory or a comma separate list of directories. +     */ +    public function setSourcepath($sourcepath) +    { +        $this->sourcepath = $sourcepath; +    } + +    /** +     * Ignore symlinks to other files or directories. +     *  +     * @param  bool  $bSet  +     */ +    public function setIgnoresymlinks($bSet) { +        $this->ignoresymlinks = $bSet; +    } + +    /** +     * Main entrypoint of the task +     */ +    public function main() +    { +        $this->validate(); +        $arguments = join(' ', $this->constructArguments()); + +        $this->log("Running phpDocumentor..."); + +        exec($this->programPath . " " . $arguments, $output, $return); + +        if ($return != 0) +        { +            throw new BuildException("Could not execute phpDocumentor: " . implode(' ', $output)); +        } +         +        foreach($output as $line) +        { +            if(strpos($line, 'ERROR') !== false) +            { +                $this->log($line, Project::MSG_ERR); +                continue; +            } +             +            $this->log($line, Project::MSG_VERBOSE); +        } +    } + +    /** +     * Constructs an argument string for phpDocumentor +     * @return  array +     */ +    protected function constructArguments() +    { +        $aArgs = array(); +        if ($this->title) +        { +            $aArgs[] = '--title "' . $this->title . '"'; +        } + +        if ($this->destdir) +        { +            $aArgs[] = '--target "' . $this->destdir->getAbsolutePath() . '"'; +        } + +        if ($this->sourcepath) +        { +            $aArgs[] = '--directory "' . $this->sourcepath . '"'; +        } + +        if ($this->output) +        { +            $aArgs[] = '--output ' . $this->output; +        } + +        if ($this->linksource) +        { +            $aArgs[] = '--sourcecode on'; +        } + +        if ($this->parseprivate) +        { +            $aArgs[] = '--parseprivate on'; +        } +         +        if ($this->ignore) +        { +            $aArgs[] = '--ignore ' . $this->ignore; +        } + +        // append any files in filesets +        $filesToParse = array(); +        foreach($this->filesets as $fs) {            +            $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); +            foreach($files as $filename) { +                 $f = new PhingFile($fs->getDir($this->project), $filename); +                 $filesToParse[] = $f->getAbsolutePath(); +            } +        } +        if (count($filesToParse) > 0) { +            $aArgs[] = '--filename "' . join(',', $filesToParse) . '"'; +        } + +        // append any files in filesets +        $ricFiles = array(); +        foreach($this->projDocFilesets as $fs) {             +            $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); +            foreach($files as $filename) { +                 $f = new PhingFile($fs->getDir($this->project), $filename); +                 $ricFiles[] = $f->getAbsolutePath(); +            } +        } +        if (count($ricFiles) > 0) { +            $aArgs[] = '--readmeinstallchangelog "' . +                join(',', $ricFiles) . '"'; +        } + +        if ($this->javadocDesc) { +            $aArgs[] = '--javadocdesc on'; +        } + +        if ($this->quiet) { +            $aArgs[] = '--quiet on'; +        } + +        if ($this->packages) { +            $aArgs[] = '--packageoutput "' . $this->packages . '"'; +        } + +        if ($this->ignoreTags) { +            $aArgs[] = '--ignore-tags "' . $this->ignoreTags . '"'; +        } + +        if ($this->defaultCategoryName) { +            $aArgs[] = '--defaultcategoryname "' . $this->defaultCategoryName . +                '"'; +        } + +        if ($this->examplesDir) { +            $aArgs[] = '--examplesdir "' . $this->examplesDir->getAbsolutePath() +                . '"'; +        } + +        if ($this->templateBase) { +            $aArgs[] = '--templatebase "' . $this->templateBase->getAbsolutePath() +                . '"'; +        } + +        if ($this->pear) { +            $aArgs[] = '--pear on'; +        } + +        if ($this->undocumentedelements) { +            $aArgs[] = '--undocumentedelements on'; +        } + +        if ($this->customtags) { +            $aArgs[] = '--customtags "' . $this->customtags . '"'; +        } + +        if ($this->ignoresymlinks) { +            $aArgs[] = '--ignoresymlinks on'; +        } + +        return $aArgs; +    } + +    /** +     * Override PhpDocumentorTask::init() because they're specific to the phpdoc +     * API which we don't use. +     */ +    public function init() { +    } + +    /** +     * Validates that necessary minimum options have been set. Based on +     * PhpDocumentorTask::validate(). +     */ +    protected function validate() { +        if (!$this->destdir) { +            throw new BuildException("You must specify a destdir for phpdoc.", +                $this->getLocation()); +        } +        if (!$this->output) { +            throw new BuildException("You must specify an output format for " . +                "phpdoc (e.g. HTML:frames:default).", $this->getLocation()); +        } +        if (empty($this->filesets) && !$this->sourcepath) { +            throw new BuildException("You have not specified any files to " . +                "include (<fileset> or sourcepath attribute) for phpdoc.", +                    $this->getLocation()); +        } +        if ($this->configdir) { +            $this->log('Ignoring unsupported configdir-Attribute', +                Project::MSG_VERBOSE); +        } +    } +}; + + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php new file mode 100755 index 00000000..e4ae363a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php @@ -0,0 +1,480 @@ +<?php + +/** + * $Id: 23a04ddae9cad46198e15081a0fb44354135b1c8 $ + * + * 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/Task.php'; + +/** + * Task to run PhpDocumentor. + * + * @author Hans Lellelid <hans@xmpl.org> + * @author Michiel Rook <mrook@php.net> + * @version $Id: 23a04ddae9cad46198e15081a0fb44354135b1c8 $ + * @package phing.tasks.ext.phpdoc + */  +class PhpDocumentorTask extends Task +{ +     +    /** +     * @var string Title for browser window / package index. +     */ +    protected $title; +     +    /** +     * @var PhingFile The target directory for output files. +     */ +    protected $destdir; + +    /** +     * @var array FileSet[] Filesets for files to parse. +     */ +    protected $filesets = array(); +     +    /** +     * @var array FileSet[] Project documentation (README/INSTALL/CHANGELOG) files. +     */ +    protected $projDocFilesets = array(); +     +    /** +     * @var string Package output format.  +     */ +    protected $output; + +    /** +     * @var boolean Whether to generate sourcecode for each file parsed. +     */ +    protected $linksource = false; +     +    /** +     * @var boolean Whether to parse private members. +     */ +    protected $parsePrivate = false; +     +    /** +     * @var boolean Whether to use javadoc descriptions (more primitive). +     */ +    protected $javadocDesc = false; +     +    /** +     * @var PhingFile Base directory for locating template files. +     */ +    protected $templateBase; +     +    /** +     * @var boolean Wheter to suppress output. +     */ +    protected $quiet = false; +     +    /** +     * @var string Comma-separated list of packages to output. +     */ +    protected $packages; +     +    /**  +     * @var string Comma-separated list of tags to ignore. +     */ +    protected $ignoreTags; +     +    /**  +     * @var string Default package name. +     */ +    protected $defaultPackageName; +     +    /** +     * @var string Default category name. +     */ +    protected $defaultCategoryName; +     +    /** +     * @var PhingFile Directory in which to look for examples. +     */ +    protected $examplesDir; +     +    /** +     * @var PhingFile Directory in which to look for configuration files. +     */ +    protected $configDir; +     +    /** +     * @var boolean Whether to parse as a PEAR repository. +     */ +    protected $pear = false; + +    /** +     * @var boolean Control whether or not warnings will be shown for +     *              undocumented elements. Useful for identifying classes and +     *              methods that haven't yet been documented. +     */ +    protected $undocumentedelements = false; + +    /** +     * @var string  custom tags, will be recognized and put in tags[] instead of +     *              unknowntags[]. +     */ +    protected $customtags = ''; +     +    /** +     * @var string  files to ignore +     */ +    protected $ignore = ''; +     +    /** +     * Set the title for the generated documentation +     */ +    public function setTitle($title) { +        $this->title = $title; +    } + +    /** +     * Set the destination directory for the generated documentation +     */ +    public function setDestdir(PhingFile $destdir) { +        $this->destdir = $destdir; +    } +     +    /** +     * Alias for {@link setDestdir()}. +     * @see setDestdir() +     */ +    public function setTarget(PhingFile $destdir) { +        $this->setDestdir($destdir); +    } + +    /** +     * Set the output format (e.g. HTML:Smarty:PHP). +     * @param string $output +     */      +    public function setOutput($output) { +        $this->output = $output; +    } + +    /** +     * Set whether to generate sourcecode for each file parsed +     * @param boolean +     */ +    public function setSourcecode($b) { +        $this->setLinksource($b); +    } + +   /** +     * Set whether to generate sourcecode for each file parsed +     * @param boolean +     */ +    public function setLinksource($b) { +        $this->linksource = $b; +    } +     +    /** +     * Set whether to suppress output. +     * @param boolean $b +     */ +    public function setQuiet($b) { +        $this->quiet = $b; +    } +     +    /** +     * Should private members/classes be documented +     * @param boolean +     */ +    public function setParseprivate($parseprivate) { +        $this->parsePrivate = $parseprivate; +    } +     +    /** +     * Whether to use javadoc descriptions (more primitive). +     * @param boolean +     */ +    public function setJavadocdesc($javadoc) { +        $this->javadocDesc = $javadoc; +    } +     +    /** +     * Set (comma-separated) list of packages to output. +     * +     * @param string $packages +     */ +    public function setPackageoutput($packages) { +        $this->packages = $packages; +    } +     +    /** +     * Set (comma-separated) list of tags to ignore. +     * +     * @param string $tags +     */ +    public function setIgnoretags($tags) { +        $this->ignoreTags = $tags; +    } +     +    /** +     * Set a directory to search for examples in. +     * @param PhingFile $d +     */ +    public function setExamplesdir(PhingFile $d) { +        $this->examplesDir = $d; +    } +     +    /** +     * Set a directory to search for configuration files in. +     * @param PhingFile $d +     */ +    public function setConfigdir(PhingFile $d) { +        $this->configDir = $d; +    } +     +    /** +     * Sets the default package name. +     * @param string $name +     */ +    public function setDefaultpackagename($name) { +        $this->defaultPackageName = $name; +    } +     +    /** +     * Sets the default category name. +     * @param string $name +     */ +    public function setDefaultcategoryname($name) { +        $this->defaultCategoryName = $name; +    } +     +    /** +     * Set whether to parse as PEAR repository. +     * @param boolean $b +     */ +    public function setPear($b) { +        $this->pear = $b; +    } +     +    /** +     * Creates a FileSet. +     * @return FileSet +     */ +    public function createFileset() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } +     +    /** +     * Creates a readme/install/changelog fileset. +     * @return FileSet +     */ +    public function createProjdocfileset() { +        $num = array_push($this->projDocFilesets, new FileSet()); +        return $this->projDocFilesets[$num-1]; +    } +     +    /** +     * Control whether or not warnings will be shown for undocumented elements. +     * Useful for identifying classes and methods that haven't yet been +     * documented. +     * @param boolean $b +     */ +    public function setUndocumentedelements($b) { +        $this->undocumentedelements = $b; +    } + +    /** +     * custom tags, will be recognized and put in tags[] instead of +     * unknowntags[]. +     *  +     * @param  string  $sCustomtags  +     */ +    public function setCustomtags($sCustomtags) { +        $this->customtags = $sCustomtags; +    } + +    /** +     * Set base location of all templates for this parse. +     *  +     * @param  PhingFile  $destdir  +     */ +    public function setTemplateBase(PhingFile $oTemplateBase) { +        $this->templateBase = $oTemplateBase; +    } +     +    /** +     * Set files to ignore +     * @param  string  $sIgnore +     */ +    public function setIgnore($sIgnore) { +        $this->ignore = $sIgnore; +    } + +    /** +     * Searches include_path for PhpDocumentor install and adjusts include_path appropriately. +     * @throws BuildException - if unable to find PhpDocumentor on include_path +     */ +    protected function findPhpDocumentorInstall() +    { +        $found = null; +        foreach(explode(PATH_SEPARATOR, get_include_path()) as $path) { +            $testpath = $path . DIRECTORY_SEPARATOR . 'PhpDocumentor'; +            if (file_exists($testpath)) { +                $found = $testpath; +                break; +            } +        } +        if (!$found) { +            throw new BuildException("PhpDocumentor task depends on PhpDocumentor being installed and on include_path.", $this->getLocation()); +        } +        // otherwise, adjust the include_path to path to include the PhpDocumentor directory ...  +        set_include_path(get_include_path() . PATH_SEPARATOR . $found); +        include_once ("phpDocumentor/Setup.inc.php"); +        if (!class_exists('phpDocumentor_setup')) { +            throw new BuildException("Error including PhpDocumentor setup class file."); +        } +    } +     +    /** +     * Main entrypoint of the task +     * Loads the necessary environment for running PhpDoc, then runs PhpDoc +     *  +     * @throws BuildException - if the phpdoc classes can't be loaded. +     */ +    function main() +    { +        $this->findPhpDocumentorInstall(); +        include_once 'phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php'; +         +        $this->validate(); +        $configdir = $this->configDir ? $this->configDir->getAbsolutePath() : null; +        $phpdoc = new PhingPhpDocumentorSetup($configdir, $this); +        $this->setPhpDocumentorOptions($phpdoc); +        //$phpdoc->readCommandLineSettings(); +        $phpdoc->setupConverters($this->output); +        $phpdoc->createDocs();       +    } +     +    /** +     * Validates that necessary minimum options have been set. +     * @throws BuildException if validation doesn't pass +     */ +    protected function validate() +    { +        if (!$this->destdir) { +            throw new BuildException("You must specify a destdir for phpdoc.", $this->getLocation()); +        } +        if (!$this->output) { +            throw new BuildException("You must specify an output format for phpdoc (e.g. HTML:frames:default).", $this->getLocation()); +        } +        if (empty($this->filesets)) { +            throw new BuildException("You have not specified any files to include (<fileset>) for phpdoc.", $this->getLocation()); +        } +    } +     +    /** +     * Sets the options on the passed-in phpdoc setup object. +     * @param PhingPhpDocumentorSetup $phpdoc +     */ +    protected function setPhpDocumentorOptions(PhingPhpDocumentorSetup $phpdoc) +    { +         +        // Title MUST be set first ... (because it re-initializes the internal state of the PhpDocu renderer) +        if ($this->title) { +            $phpdoc->setTitle($this->title); +        } +         +        if ($this->parsePrivate) { +            $phpdoc->setParsePrivate(); +        } +         +        if ($this->javadocDesc) { +            $phpdoc->setJavadocDesc(); +        } +         +        if ($this->quiet) { +            $phpdoc->setQuietMode(); +        } +         +        if ($this->destdir) { +            $phpdoc->setTargetDir($this->destdir->getAbsolutePath()); +        } +                 +        if ($this->packages) { +            $phpdoc->setPackageOutput($this->packages); +        } +         +        if ($this->templateBase) { +            $phpdoc->setTemplateBase($this->templateBase->getAbsolutePath()); +        } +         +        if ($this->linksource) { +            $phpdoc->setGenerateSourcecode($this->linksource); +        } +         +        if ($this->examplesDir) { +            $phpdoc->setExamplesDir($this->examplesDir->getAbsolutePath()); +        } +         +        if ($this->ignoreTags) { +            $phpdoc->setIgnoreTags($this->ignoreTags); +        } +         +        if ($this->defaultPackageName) { +            $phpdoc->setDefaultPackageName($this->defaultPackageName); +        } +         +        if ($this->defaultCategoryName) { +            $phpdoc->setDefaultCategoryName($this->defaultCategoryName); +        } +         +        if ($this->pear) { +            $phpdoc->setPear($this->pear); +        } +         +        if ($this->ignore) { +            $phpdoc->setIgnore($this->ignore); +        } +         +        // append any files in filesets +        $filesToParse = array(); +        foreach($this->filesets as $fs) {            +            $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); +            foreach($files as $filename) { +                 $f = new PhingFile($fs->getDir($this->project), $filename); +                 $filesToParse[] = $f->getAbsolutePath(); +            } +        } +        //print_r(implode(",", $filesToParse)); +        $phpdoc->setFilesToParse(implode(",", $filesToParse)); +         +         +        // append any files in filesets +        $ricFiles = array(); +        foreach($this->projDocFilesets as $fs) {             +            $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); +            foreach($files as $filename) { +                 $f = new PhingFile($fs->getDir($this->project), $filename); +                 $ricFiles[] = $f->getName(); +            } +        } +        $phpdoc->setRicFiles($ricFiles); + +        if ($this->undocumentedelements) { +            $phpdoc->setUndocumentedelements($this->undocumentedelements); +        } + +        if ($this->customtags) { +            $phpdoc->setCustomtags($this->customtags); +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php new file mode 100644 index 00000000..c327e331 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php @@ -0,0 +1,181 @@ +<?php +/** + * $Id: 69fc758899446b96312ac12f26b461969eb41b6e $ + * + * 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/system/io/PhingFile.php'; + +/** + * A wrapper for the implementations of PHPMDResultFormatter. + * + * @package phing.tasks.ext.phpmd + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 69fc758899446b96312ac12f26b461969eb41b6e $ + * @since   2.4.1 + */ +class PHPMDFormatterElement +{ +    /** +     * @var PHPMDResultFormatter +     */ +    protected $formatter = null; + +    /** +     * The type of the formatter. +     * +     * @var string +     */ +    protected $type = ""; + +    /** +     * Whether to use file (or write output to phing log). +     * +     * @var boolean +     */ +    protected $useFile = true; + +    /** +     * Output file for formatter. +     * +     * @var PhingFile +     */ +    protected $outfile = null; + +    /** +     * Sets the formatter type. +     * +     * @param string $type Type of the formatter +     * +     * @return void +     */ +    public function setType($type) +    { +        $this->type = $type; + +        switch ($this->type) { +        case 'xml': +            include_once 'PHP/PMD/Renderer/XMLRenderer.php'; +            break; + +        case 'html': +            include_once 'PHP/PMD/Renderer/HTMLRenderer.php'; +            break; + +        case 'text': +            include_once 'PHP/PMD/Renderer/TextRenderer.php'; +            break; + +        default: +            throw new BuildException("Formatter '" . $this->type . "' not implemented"); +        } +    } + +    /** +     * Get the formatter type +     * +     * @return string +     */ +    public function getType() +    { +        return $this->type; +    } + +    /** +     * Set whether to write formatter results to file or not. +     * +     * @param boolean $useFile True or false. +     * +     * @return void +     */ +    public function setUseFile($useFile) +    { +        $this->useFile = (boolean) $useFile; +    } + +    /** +     * Return whether to write formatter results to file or not. +     * +     * @return boolean +     */ +    public function getUseFile() +    { +        return $this->useFile; +    } + +    /** +     * Sets the output file for the formatter results. +     * +     * @param PhingFile $outfile The output file +     * +     * @return void +     */ +    public function setOutfile(PhingFile $outfile) +    { +        $this->outfile = $outfile; +    } + +    /** +     * Get the output file. +     * +     * @return PhingFile +     */ +    public function getOutfile() +    { +        return $this->outfile; +    } + +    /** +     * Creates a report renderer instance based on the formatter type. +     * +     * @return PHP_PMD_AbstractRenderer +     * @throws BuildException When the specified renderer does not exist. +     */ +    public function getRenderer() +    { +        switch ($this->type) { +        case 'xml': +            $renderer = new PHP_PMD_Renderer_XMLRenderer(); +            break; + +        case 'html': +            $renderer = new PHP_PMD_Renderer_HTMLRenderer(); +            break; + +        case 'text': +            $renderer = new PHP_PMD_Renderer_TextRenderer(); +            break; + +        default: +            throw new BuildException("PHP_MD renderer '" . $this->type . "' not implemented"); +        } + +        // Create a report stream +        if ($this->getUseFile() === false || $this->getOutfile() === null) { +            $stream = STDOUT; +        } else { +            $stream = fopen($this->getOutfile()->getAbsoluteFile(), 'wb'); +        } + +        require_once 'PHP/PMD/Writer/Stream.php'; +         +        $renderer->setWriter(new PHP_PMD_Writer_Stream($stream)); + +        return $renderer; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDTask.php new file mode 100644 index 00000000..1c4d34bf --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDTask.php @@ -0,0 +1,284 @@ +<?php +/** + *  $Id: 35668c2c6fbf1ca87fab21c26fd55ef630458fc7 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/phpmd/PHPMDFormatterElement.php'; + +/** + * Runs PHP Mess Detector. Checking PHP files for several potential problems + * based on rulesets. + * + * @package phing.tasks.ext.phpmd + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 35668c2c6fbf1ca87fab21c26fd55ef630458fc7 $ + * @since   2.4.1 + */ +class PHPMDTask extends Task +{ +    /** +     * A php source code filename or directory +     * +     * @var PhingFile +     */ +    protected $file = null; + +    /** +     * All fileset objects assigned to this task +     * +     * @var array<FileSet> +     */ +    protected $filesets = array(); + +    /** +     * The rule-set filenames or identifier. +     * +     * @var string +     */ +    protected $rulesets = 'codesize,unusedcode'; + +    /** +     * The minimum priority for rules to load. +     * +     * @var integer +     */ +    protected $minimumPriority = 0; + +    /** +     * List of valid file extensions for analyzed files. +     * +     * @var array +     */ +    protected $allowedFileExtensions = array('php'); + +    /** +     * List of exclude directory patterns. +     * +     * @var array +     */ +    protected $ignorePatterns = array('.git', '.svn', 'CVS', '.bzr', '.hg'); + +    /** +     * The format for the report +     * +     * @var string +     */ +    protected $format = 'text'; + +    /** +     * Formatter elements. +     * +     * @var array<PHPMDFormatterElement> +     */ +    protected $formatters = array(); + +    /** +     * Set the input source file or directory. +     * +     * @param PhingFile $file The input source file or directory. +     * +     * @return void +     */ +    public function setFile(PhingFile $file) +    { +        $this->file = $file; +    } + +    /** +     * Nested creator, adds a set of files (nested fileset attribute). +     * +     * @return FileSet The created fileset object +     */ +    public function createFileSet() +    { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    /** +     * Sets the minimum rule priority. +     * +     * @param integer $minimumPriority Minimum rule priority. +     * +     * @return void +     */ +    public function setMinimumPriority($minimumPriority) +    { +        $this->minimumPriority = $minimumPriority; +    } + +    /** +     * Sets the rule-sets. +     * +     * @param string $ruleSetFileNames Comma-separated string of rule-set filenames +     *                                 or identifier. +     * +     * @return void +     */ +    public function setRulesets($ruleSetFileNames) +    { +        $this->rulesets = $ruleSetFileNames; +    } + +    /** +     * Sets a list of filename extensions for valid php source code files. +     * +     * @param string $fileExtensions List of valid file extensions without leading dot. +     * +     * @return void +     */ +    public function setAllowedFileExtensions($fileExtensions) +    { +        $this->allowedFileExtensions = array(); + +        $token = ' ,;'; +        $ext   = strtok($fileExtensions, $token); + +        while ($ext !== false) { +            $this->allowedFileExtensions[] = $ext; +            $ext = strtok($token); +        } +    } + +    /** +     * Sets a list of ignore patterns that is used to exclude directories from +     * the source analysis. +     * +     * @param string $ignorePatterns List of ignore patterns. +     * +     * @return void +     */ +    public function setIgnorePatterns($ignorePatterns) +    { +        $this->ignorePatterns = array(); + +        $token   = ' ,;'; +        $pattern = strtok($ignorePatterns, $token); + +        while ($pattern !== false) { +            $this->ignorePatterns[] = $pattern; +            $pattern = strtok($token); +        } +    } + +    /** +     * Create object for nested formatter element. +     * +     * @return PHPMDFormatterElement +     */ +    public function createFormatter() +    { +        $num = array_push($this->formatters, new PHPMDFormatterElement()); +        return $this->formatters[$num-1]; +    } + +    /** +     * Executes PHPMD against PhingFile or a FileSet +     * +     * @throws BuildException - if the phpmd classes can't be loaded. +     * @return void +     */ +    public function main() +    { +        /** +         * Find PHPMD +         */ +        @include_once 'PHP/PMD.php'; + +        if (! class_exists('PHP_PMD')) { +            throw new BuildException( +                'PHPMDTask depends on PHPMD being installed and on include_path.', +                $this->getLocation() +            ); +        } +         +        require_once 'PHP/PMD/AbstractRule.php'; + +        if (!$this->minimumPriority) { +            $this->minimumPriority = PHP_PMD_AbstractRule::LOWEST_PRIORITY; +        } +         +        if (!isset($this->file) and count($this->filesets) == 0) { +            throw new BuildException("Missing either a nested fileset or attribute 'file' set"); +        } + +        if (count($this->formatters) == 0) { +            // turn legacy format attribute into formatter +            $fmt = new PHPMDFormatterElement(); +            $fmt->setType($this->format); +            $fmt->setUseFile(false); +            $this->formatters[] = $fmt; +        } + +        $reportRenderers = array(); + +        foreach ($this->formatters as $fe) { +            if ($fe->getType() == '') { +                throw new BuildException("Formatter missing required 'type' attribute."); +            } +            if ($fe->getUsefile() && $fe->getOutfile() === null) { +                throw new BuildException("Formatter requires 'outfile' attribute when 'useFile' is true."); +            } + +            $reportRenderers[] = $fe->getRenderer(); +        } + +        // Create a rule set factory +        $ruleSetFactory = new PHP_PMD_RuleSetFactory(); +        $ruleSetFactory->setMinimumPriority($this->minimumPriority); + +        $phpmd = new PHP_PMD(); + +        $phpmd->setFileExtensions($this->allowedFileExtensions); +        $phpmd->setIgnorePattern($this->ignorePatterns); + +        $filesToParse = array(); + +        if ($this->file instanceof PhingFile) { +            $filesToParse[] = $this->file->getPath(); +        } else { +            // append any files in filesets +            foreach ($this->filesets as $fs) { +                $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); +                foreach ($files as $filename) { +                     $f = new PhingFile($fs->getDir($this->project), $filename); +                     $filesToParse[] = $f->getAbsolutePath(); +                } +            } +        } +         +        if (count($filesToParse) > 0) { +            $inputPath = implode(',', $filesToParse); +     +            $this->log('Processing files...'); +     +            $phpmd->processFiles( +                $inputPath, +                $this->rulesets, +                $reportRenderers, +                $ruleSetFactory +            ); +     +            $this->log('Finished processing files'); +        } else { +            $this->log('No files to process'); +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/BatchTest.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/BatchTest.php new file mode 100755 index 00000000..6a6cec24 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/BatchTest.php @@ -0,0 +1,230 @@ +<?php +/** + * $Id: 4067d915614ff7a864c31f19549bcf6a96c0f92d $ + * + * 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/ext/phpunit/PHPUnitUtil.php'; +require_once 'phing/types/FileSet.php'; + +/** + * Scans a list of files given by the fileset attribute, extracts valid test cases + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 4067d915614ff7a864c31f19549bcf6a96c0f92d $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class BatchTest +{ +    /** the list of filesets containing the testcase filename rules */ +    private $filesets = array(); + +    /** the reference to the project */ +    private $project = NULL; + +    /** the classpath to use with Phing::__import() calls */ +    private $classpath = NULL; +     +    /** names of classes to exclude */ +    private $excludeClasses = array(); +     +    /** name of the batchtest/suite */ +    protected $name = "Phing Batchtest"; +     +    /** +     * Create a new batchtest instance +     * +     * @param Project the project it depends on. +     */ +    public function __construct(Project $project) +    { +        $this->project = $project; +    } +     +    /** +     * Sets the name of the batchtest/suite +     */ +    public function setName($name) +    { +        $this->name = $name; +    } +     +    /** +     * Sets the classes to exclude +     */ +    public function setExclude($exclude) +    { +        $this->excludeClasses = explode(" ", $exclude); +    } + +    /** +     * Sets the classpath +     */ +    public function setClasspath(Path $classpath) +    { +        if ($this->classpath === null) +        { +            $this->classpath = $classpath; +        } +        else +        { +            $this->classpath->append($classpath); +        } +    } + +    /** +     * Creates a new Path object +     */ +    public function createClasspath() +    { +        $this->classpath = new Path(); +        return $this->classpath; +    } + +    /** +     * Returns the classpath +     */ +    public function getClasspath() +    { +        return $this->classpath; +    } + +    /** +     * Add a new fileset containing the XML results to aggregate +     * +     * @param FileSet the new fileset containing XML results. +     */ +    public function addFileSet(FileSet $fileset) +    { +        $this->filesets[] = $fileset; +    } + +    /** +     * Iterate over all filesets and return the filename of all files. +     * +     * @return array an array of filenames +     */ +    private function getFilenames() +    { +        $filenames = array(); + +        foreach ($this->filesets as $fileset) +        { +            $ds = $fileset->getDirectoryScanner($this->project); +            $ds->scan(); + +            $files = $ds->getIncludedFiles(); + +            foreach ($files as $file) +            { +                $filenames[] = $ds->getBaseDir() . "/" . $file; +            } +        } + +        return $filenames; +    } +     +    /** +     * Checks wheter $input is a PHPUnit Test +     */ +    private function isTestCase($input) +    {    +        return is_subclass_of($input, 'PHPUnit_Framework_TestCase') || is_subclass_of($input, 'PHPUnit_Framework_TestSuite'); +    } +     +    /** +     * Filters an array of classes, removes all classes that are not test cases or test suites, +     * or classes that are declared abstract +     */ +    private function filterTests($input) +    { +        $reflect = new ReflectionClass($input); +         +        return $this->isTestCase($input) && (!$reflect->isAbstract()); +    } + +    /** +     * Returns an array of test cases and test suites that are declared +     * by the files included by the filesets +     * +     * @return array an array of tests. +     */ +    protected function elements() +    { +        $filenames = $this->getFilenames(); +         +        $declaredClasses = array();      + +        foreach ($filenames as $filename) +        { +            $definedClasses = PHPUnitUtil::getDefinedClasses($filename, $this->classpath); +             +            foreach($definedClasses as $definedClass) { +                $this->project->log("(PHPUnit) Adding $definedClass (from $filename) to tests.", Project::MSG_DEBUG); +            } +             +            $declaredClasses = array_merge($declaredClasses, $definedClasses); +        } +         +        $elements = array_filter($declaredClasses, array($this, "filterTests")); + +        return $elements; +    } +     +    /** +     * Returns a testsuite containing all the tests in this batch +     * +     * @deprecated +     * @return PHPUnit_Framework_TestSuite +     */ +    public function getTestSuite() +    { +        $suite = new PHPUnit_Framework_TestSuite($this->name); +         +        foreach ($this->elements() as $test) +        { +            $testClass = new $test(); +            if (!($testClass instanceof PHPUnit_Framework_TestSuite)) +            { +              $testClass = new ReflectionClass($test); +            } +             +            $suite->addTestSuite($testClass); +        } +         +        return $suite; +    } +     +    /** +     * Add the tests in this batchtest to a test suite +     * @param PHPUnit_Framework_TestSuite $suite +     */ +    public function addToTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        foreach ($this->elements() as $element) { +            $testClass = new $element(); +            if (!($testClass instanceof PHPUnit_Framework_TestSuite)) +            { +                $testClass = new ReflectionClass($element); +            } +            $suite->addTestSuite($testClass); +        } +    } +     +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/FormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/FormatterElement.php new file mode 100755 index 00000000..c220b79d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/FormatterElement.php @@ -0,0 +1,178 @@ +<?php +/** + * $Id: 296214ebac3a12e51bffed3dcc2c0bb93fb0754e $ + * + * 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/system/io/PhingFile.php'; + +/** + * A wrapper for the implementations of PHPUnit2ResultFormatter. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 296214ebac3a12e51bffed3dcc2c0bb93fb0754e $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class FormatterElement +{ +    protected $formatter = NULL; +     +    protected $type = ""; +     +    protected $useFile = true; +     +    protected $toDir = "."; +     +    protected $outfile = ""; +     +    protected $parent = NULL; +     +    /** +     * Sets parent task +     * @param Task $parent Calling Task +     */ +    public function setParent($parent) +    { +        $this->parent = $parent; +    } + +    /** +     * Loads a specific formatter type +     * @param string $type +     */ +    public function setType($type) +    { +        $this->type = $type; +         +        if ($this->type == "summary") +        { +            require_once 'phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php'; +            $this->formatter = new SummaryPHPUnitResultFormatter($this->parent); +        } +        else +        if ($this->type == "clover") +        { +            require_once 'phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php'; +            $this->formatter = new CloverPHPUnitResultFormatter($this->parent); +        } +        else +        if ($this->type == "xml") +        { +            require_once 'phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php'; +            $this->formatter = new XMLPHPUnitResultFormatter($this->parent); +        } +        else +        if ($this->type == "plain") +        { +            require_once 'phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php'; +            $this->formatter = new PlainPHPUnitResultFormatter($this->parent); +        } +        else +        { +            throw new BuildException("Formatter '" . $this->type . "' not implemented"); +        } +    } + +    /** +     * Loads a specific formatter class +     */ +    public function setClassName($className) +    { +        $classNameNoDot = Phing::import($className); + +        $this->formatter = new $classNameNoDot(); +    } + +    /** +     * Sets whether to store formatting results in a file +     */ +    public function setUseFile($useFile) +    { +        $this->useFile = $useFile; +    } +     +    /** +     * Returns whether to store formatting results in a file +     */ +    public function getUseFile() +    { +        return $this->useFile; +    } +     +    /** +     * Sets output directory +     * @param string $toDir +     */ +    public function setToDir($toDir) +    { +        $this->toDir = $toDir; +    } +     +    /** +     * Returns output directory +     * @return string +     */ +    public function getToDir() +    { +        return $this->toDir; +    } + +    /** +     * Sets output filename +     * @param string $outfile +     */ +    public function setOutfile($outfile) +    { +        $this->outfile = $outfile; +    } +     +    /** +     * Returns output filename +     * @return string +     */ +    public function getOutfile() +    { +        if ($this->outfile) +        { +            return $this->outfile; +        } +        else +        { +            return $this->formatter->getPreferredOutfile() . $this->getExtension(); +        } +    } +     +    /** +     * Returns extension +     * @return string +     */ +    public function getExtension() +    { +        return $this->formatter->getExtension(); +    } + +    /** +     * Returns formatter object +     * @return PHPUnitResultFormatter +     */ +    public function getFormatter() +    { +        return $this->formatter; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php new file mode 100755 index 00000000..87338da7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php @@ -0,0 +1,248 @@ +<?php +/** + * $Id: b88d6fa4ca4717177b562a0475c81d92c161d9b4 $ + * + * 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/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/FileWriter.php'; +require_once 'phing/util/ExtendedFileStream.php'; + +/** + * Transform a PHPUnit xml report using XSLT. + * This transformation generates an html report in either framed or non-framed + * style. The non-framed style is convenient to have a concise report via mail,  + * the framed report is much more convenient if you want to browse into  + * different packages or testcases since it is a Javadoc like report. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: b88d6fa4ca4717177b562a0475c81d92c161d9b4 $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class PHPUnitReportTask extends Task +{ +    private $format = "noframes"; +    private $styleDir = ""; +    private $toDir = ""; +     +    /** +     * Whether to use the sorttable JavaScript library, defaults to false +     * See {@link http://www.kryogenix.org/code/browser/sorttable/)} +     * +     * @var boolean +     */ +    private $useSortTable = false; + +    /** the directory where the results XML can be found */ +    private $inFile = "testsuites.xml"; + +    /** +     * Set the filename of the XML results file to use. +     */ +    public function setInFile(PhingFile $inFile) +    { +        $this->inFile = $inFile; +    } + +    /** +     * Set the format of the generated report. Must be noframes or frames. +     */ +    public function setFormat($format) +    { +        $this->format = $format; +    } + +    /** +     * Set the directory where the stylesheets are located. +     */ +    public function setStyleDir($styleDir) +    { +        $this->styleDir = $styleDir; +    } + +    /** +     * Set the directory where the files resulting from the  +     * transformation should be written to. +     */ +    public function setToDir(PhingFile $toDir) +    { +        $this->toDir = $toDir; +    } +     +    /** +     * Sets whether to use the sorttable JavaScript library, defaults to false +     * See {@link http://www.kryogenix.org/code/browser/sorttable/)} +     * +     * @param boolean $useSortTable +     */ +    public function setUseSortTable($useSortTable) +    { +        $this->useSortTable = (boolean) $useSortTable; +    } +     +    /** +     * Returns the path to the XSL stylesheet +     */ +    protected function getStyleSheet() +    { +        $xslname = "phpunit-" . $this->format . ".xsl"; +         +        if ($this->styleDir) +        { +            $file = new PhingFile($this->styleDir, $xslname); +        } +        else +        { +            $path = Phing::getResourcePath("phing/etc/$xslname"); +             +            if ($path === NULL) +            { +                $path = Phing::getResourcePath("etc/$xslname"); + +                if ($path === NULL) +                { +                    throw new BuildException("Could not find $xslname in resource path"); +                } +            } +             +            $file = new PhingFile($path); +        } + +        if (!$file->exists()) +        { +            throw new BuildException("Could not find file " . $file->getPath()); +        } + +        return $file; +    } +     +    /** +     * Transforms the DOM document +     */ +    protected function transform(DOMDocument $document) +    { +        if (!$this->toDir->exists()) +        { +            throw new BuildException("Directory '" . $this->toDir . "' does not exist"); +        } +         +        $xslfile = $this->getStyleSheet(); + +        $xsl = new DOMDocument(); +        $xsl->load($xslfile->getAbsolutePath()); + +        $proc = new XSLTProcessor(); +        if (defined('XSL_SECPREF_WRITE_FILE')) +        { +            if (version_compare(PHP_VERSION,'5.4',"<")) +            { +                ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); +            } +            else +            { +                $proc->setSecurityPrefs(XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); +            } +        } +         +        $proc->importStyleSheet($xsl); +        $proc->setParameter('', 'output.sorttable', $this->useSortTable); + +        if ($this->format == "noframes") +        { +            $writer = new FileWriter(new PhingFile($this->toDir, "phpunit-noframes.html")); +            $writer->write($proc->transformToXML($document)); +            $writer->close(); +        } +        else +        { +            ExtendedFileStream::registerStream(); +             +            $toDir = (string) $this->toDir; +             +            // urlencode() the path if we're on Windows +            if (FileSystem::getFileSystem()->getSeparator() == '\\') { +                $toDir = urlencode($toDir); +            } + +            // no output for the framed report +            // it's all done by extension... +            $proc->setParameter('', 'output.dir', $toDir); +            $proc->transformToXML($document); +             +            ExtendedFileStream::unregisterStream(); +        } +    } +     +    /** +     * Fixes DOM document tree: +     *   - adds package="default" to 'testsuite' elements without +     *     package attribute +     *   - removes outer 'testsuite' container(s) +     */ +    protected function fixDocument(DOMDocument $document) +    { +        $rootElement = $document->firstChild; +         +        $xp = new DOMXPath($document); +         +        $nodes = $xp->query("/testsuites/testsuite"); +         +        foreach ($nodes as $node) { +            $children = $xp->query("./testsuite", $node); +             +            if ($children->length) { +                foreach ($children as $child) { +                    if (!$child->hasAttribute('package')) +                    { +                        $child->setAttribute('package', 'default'); +                    } +                    $rootElement->appendChild($child); +                } +                 +                $rootElement->removeChild($node); +            } +        } +    } +     +    /** +     * Initialize the task +     */ +    public function init() +    { +        if (!class_exists('XSLTProcessor')) { +            throw new BuildException("PHPUnitReportTask requires the XSL extension"); +        } +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    public function main() +    { +        $testSuitesDoc = new DOMDocument(); +        $testSuitesDoc->load((string) $this->inFile); +         +        $this->fixDocument($testSuitesDoc); +         +        $this->transform($testSuitesDoc); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php new file mode 100755 index 00000000..5b842b95 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php @@ -0,0 +1,378 @@ +<?php +/** + * $Id: 4554fdd642b6ef7774cbb89c537ccba90f3ca972 $ + * + * 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/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/Writer.php'; +require_once 'phing/util/LogWriter.php'; + +/** + * Runs PHPUnit tests. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 4554fdd642b6ef7774cbb89c537ccba90f3ca972 $ + * @package phing.tasks.ext.phpunit + * @see BatchTest + * @since 2.1.0 + */ +class PHPUnitTask extends Task +{ +    private $batchtests = array(); +    private $formatters = array(); +    private $bootstrap = ""; +    private $haltonerror = false; +    private $haltonfailure = false; +    private $haltonincomplete = false; +    private $haltonskipped = false; +    private $errorproperty; +    private $failureproperty; +    private $incompleteproperty; +    private $skippedproperty; +    private $printsummary = false; +    private $testfailed = false; +    private $testfailuremessage = ""; +    private $codecoverage = null; +    private $groups = array(); +    private $excludeGroups = array(); +    private $processIsolation = false; +    private $usecustomerrorhandler = true; + +    /** +     * Initialize Task. +     * This method includes any necessary PHPUnit libraries and triggers +     * appropriate error if they cannot be found.  This is not done in header +     * because we may want this class to be loaded w/o triggering an error. +     */ +    public function init() { +        /** +         * Determine PHPUnit version number +         */ +        @include_once 'PHPUnit/Runner/Version.php'; +         +        if (!class_exists('PHPUnit_Runner_Version')) { +            throw new BuildException("PHPUnitTask requires PHPUnit to be installed", $this->getLocation()); +        } + +        $version = PHPUnit_Runner_Version::id(); + +        if (version_compare($version, '3.6.0') < 0) +        { +            throw new BuildException("PHPUnitTask requires PHPUnit version >= 3.6.0", $this->getLocation()); +        } +             +        /** +         * Other dependencies that should only be loaded when class is actually used. +         */ +        require_once 'phing/tasks/ext/phpunit/PHPUnitTestRunner.php'; +        require_once 'phing/tasks/ext/phpunit/BatchTest.php'; +        require_once 'phing/tasks/ext/phpunit/FormatterElement.php'; + +        /** +         * point PHPUnit_MAIN_METHOD define to non-existing method +         */ +        if (!defined('PHPUnit_MAIN_METHOD')) +        { +            define('PHPUnit_MAIN_METHOD', 'PHPUnitTask::undefined'); +        } +    } +     +    /** +     * Sets the name of a bootstrap file that is run before +     * executing the tests +     * +     * @param string $bootstrap the name of the bootstrap file +     */ +    public function setBootstrap($bootstrap) +    { +        $this->bootstrap = $bootstrap; +    } +     +    public function setErrorproperty($value) +    { +        $this->errorproperty = $value; +    } +     +    public function setFailureproperty($value) +    { +        $this->failureproperty = $value; +    } +     +    public function setIncompleteproperty($value) +    { +        $this->incompleteproperty = $value; +    } +     +    public function setSkippedproperty($value) +    { +        $this->skippedproperty = $value; +    } +     +    public function setHaltonerror($value) +    { +        $this->haltonerror = $value; +    } + +    public function setHaltonfailure($value) +    { +        $this->haltonfailure = $value; +    } +     +    public function getHaltonfailure() +    { +        return $this->haltonfailure; +    } + +    public function setHaltonincomplete($value) +    { +        $this->haltonincomplete = $value; +    } +     +    public function getHaltonincomplete() +    { +        return $this->haltonincomplete; +    } + +    public function setHaltonskipped($value) +    { +        $this->haltonskipped = $value; +    } +     +    public function getHaltonskipped() +    { +        return $this->haltonskipped; +    } + +    public function setPrintsummary($printsummary) +    { +        $this->printsummary = $printsummary; +    } +     +    public function setCodecoverage($codecoverage) +    { +        $this->codecoverage = $codecoverage; +    } + +    public function setProcessIsolation($processIsolation) +    { +        $this->processIsolation = $processIsolation; +    } + +    public function setUseCustomErrorHandler($usecustomerrorhandler) +    { +        $this->usecustomerrorhandler = $usecustomerrorhandler; +    } + +    public function setGroups($groups) +    { +        $token = ' ,;'; +        $this->groups = array(); +        $tok = strtok($groups, $token); +        while ($tok !== false) { +            $this->groups[] = $tok; +            $tok = strtok($token); +        } +    } + +    public function setExcludeGroups($excludeGroups) +    { +        $token = ' ,;'; +        $this->excludeGroups = array(); +        $tok = strtok($excludeGroups, $token); +        while ($tok !== false) { +            $this->excludeGroups[] = $tok; +            $tok = strtok($token); +        } +    } + +    /** +     * Add a new formatter to all tests of this task. +     * +     * @param FormatterElement formatter element +     */ +    public function addFormatter(FormatterElement $fe) +    { +        $fe->setParent($this); +        $this->formatters[] = $fe; +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    public function main() +    { +        if ($this->codecoverage && !extension_loaded('xdebug')) +        { +            throw new Exception("PHPUnitTask depends on Xdebug being installed to gather code coverage information."); +        } + +        if ($this->printsummary) +        { +            $fe = new FormatterElement(); +            $fe->setParent($this); +            $fe->setType("summary"); +            $fe->setUseFile(false); +            $this->formatters[] = $fe; +        } +         +        $autoloadSave = spl_autoload_functions(); +         +        if ($this->bootstrap) +        { +            require_once $this->bootstrap; +        } +         +        $suite = new PHPUnit_Framework_TestSuite('AllTests'); +         +        foreach ($this->batchtests as $batchtest) +        { +            $batchtest->addToTestSuite($suite); +        } +         +        $this->execute($suite); +         +        if ($this->testfailed) +        { +            throw new BuildException($this->testfailuremessage); +        } +         +        $autoloadNew = spl_autoload_functions(); +        foreach ($autoloadNew as $autoload) { +            spl_autoload_unregister($autoload); +        } +         +        foreach ($autoloadSave as $autoload) { +            spl_autoload_register($autoload); +        } +    } + +    /** +     * @throws BuildException +     */ +    protected function execute($suite) +    { +        $runner = new PHPUnitTestRunner($this->project, $this->groups, $this->excludeGroups, $this->processIsolation); +         +        if ($this->codecoverage) { +            /** +             * Add some defaults to the PHPUnit filter +             */ +            $pwd = dirname(__FILE__); +            $path = realpath($pwd . '/../../../'); +             +            $filter = new PHP_CodeCoverage_Filter(); +            $filter->addDirectoryToBlacklist($path); +            $runner->setCodecoverage(new PHP_CodeCoverage(null, $filter)); +        } +         +        $runner->setUseCustomErrorHandler($this->usecustomerrorhandler); + +        foreach ($this->formatters as $fe) +        { +            $formatter = $fe->getFormatter(); + +            if ($fe->getUseFile()) +            { +                $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); +                 +                $writer = new FileWriter($destFile->getAbsolutePath()); + +                $formatter->setOutput($writer); +            } +            else +            { +                $formatter->setOutput($this->getDefaultOutput()); +            } + +            $runner->addFormatter($formatter); + +            $formatter->startTestRun(); +        } +         +        $runner->run($suite); + +        foreach ($this->formatters as $fe) +        { +            $formatter = $fe->getFormatter(); +            $formatter->endTestRun(); +        } +         +        $retcode = $runner->getRetCode(); +         +        if ($retcode == PHPUnitTestRunner::ERRORS) { +            if ($this->errorproperty) { +                $this->project->setNewProperty($this->errorproperty, true); +            } +            if ($this->haltonerror) { +                $this->testfailed = true; +                $this->testfailuremessage = $runner->getLastErrorMessage(); +            } +        } elseif ($retcode == PHPUnitTestRunner::FAILURES) { +            if ($this->failureproperty) { +                $this->project->setNewProperty($this->failureproperty, true); +            } +             +            if ($this->haltonfailure) { +                $this->testfailed = true; +                $this->testfailuremessage = $runner->getLastFailureMessage(); +            } +        } elseif ($retcode == PHPUnitTestRunner::INCOMPLETES) { +            if ($this->incompleteproperty) { +                $this->project->setNewProperty($this->incompleteproperty, true); +            } +             +            if ($this->haltonincomplete) { +                $this->testfailed = true; +                $this->testfailuremessage = $runner->getLastIncompleteMessage(); +            } +        } elseif ($retcode == PHPUnitTestRunner::SKIPPED) { +            if ($this->skippedproperty) { +                $this->project->setNewProperty($this->skippedproperty, true); +            } +             +            if ($this->haltonskipped) { +                $this->testfailed = true; +                $this->testfailuremessage = $runner->getLastSkippedMessage(); +            } +        } +    } + +    protected function getDefaultOutput() +    { +        return new LogWriter($this); +    } + +    /** +     * Adds a set of tests based on pattern matching. +     * +     * @return BatchTest a new instance of a batch test. +     */ +    public function createBatchTest() +    { +        $batchtest = new BatchTest($this->getProject()); + +        $this->batchtests[] = $batchtest; + +        return $batchtest; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.php new file mode 100755 index 00000000..6c7e5e68 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.php @@ -0,0 +1,312 @@ +<?php +/** + * $Id: 5926dfc1177ec0c52ec275a8e542979c8deb6e6f $ + * + * 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 'PHPUnit/Autoload.php'; +require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; +require_once 'phing/system/util/Timer.php'; + +/** + * Simple Testrunner for PHPUnit that runs all tests of a testsuite. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 5926dfc1177ec0c52ec275a8e542979c8deb6e6f $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class PHPUnitTestRunner extends PHPUnit_Runner_BaseTestRunner implements PHPUnit_Framework_TestListener +{ +    const SUCCESS = 0; +    const FAILURES = 1; +    const ERRORS = 2; +    const INCOMPLETES = 3; +    const SKIPPED = 4; + +    private $retCode = 0; +    private $lastErrorMessage = ''; +    private $lastFailureMessage = ''; +    private $lastIncompleteMessage = ''; +    private $lastSkippedMessage = ''; +    private $formatters = array(); +     +    private $codecoverage = null; +     +    private $project = NULL; + +    private $groups = array(); +    private $excludeGroups = array(); +     +    private $processIsolation = false; +     +    private $useCustomErrorHandler = true; + +    public function __construct(Project $project, $groups = array(), $excludeGroups = array(), $processIsolation = false) +    { +        $this->project = $project; +        $this->groups = $groups; +        $this->excludeGroups = $excludeGroups; +        $this->processIsolation = $processIsolation; +        $this->retCode = self::SUCCESS; +    } +     +    public function setCodecoverage($codecoverage) +    { +        $this->codecoverage = $codecoverage; +    } + +    public function setUseCustomErrorHandler($useCustomErrorHandler) +    { +        $this->useCustomErrorHandler = $useCustomErrorHandler; +    } + +    public function addFormatter($formatter) +    { +        $this->formatters[] = $formatter; +    } +     +    public function handleError($level, $message, $file, $line) +    { +        return PHPUnit_Util_ErrorHandler::handleError($level, $message, $file, $line); +    } +     +    /** +     * Run a test +     */ +    public function run(PHPUnit_Framework_TestSuite $suite) +    { +        $res = new PHPUnit_Framework_TestResult(); + +        if ($this->codecoverage) +        { +            $whitelist = CoverageMerger::getWhiteList($this->project); +             +            $this->codecoverage->filter()->addFilesToWhiteList($whitelist); +             +            $res->setCodeCoverage($this->codecoverage); +        } +         +        $res->addListener($this); + +        foreach ($this->formatters as $formatter) +        { +            $res->addListener($formatter); +        } +         +        /* Set PHPUnit error handler */ +        if ($this->useCustomErrorHandler) +        { +            $oldErrorHandler = set_error_handler(array($this, 'handleError'), E_ALL | E_STRICT); +        } +         +        $suite->run($res, false, $this->groups, $this->excludeGroups, $this->processIsolation); +         +        foreach ($this->formatters as $formatter) +        { +            $formatter->processResult($res); +        } +         +        /* Restore Phing error handler */ +        if ($this->useCustomErrorHandler) +        { +            restore_error_handler(); +        } +         +        if ($this->codecoverage) +        { +            CoverageMerger::merge($this->project, $this->codecoverage->getData()); +        } +         +        if ($res->errorCount() != 0) +        { +            $this->retCode = self::ERRORS; +        } +        else if ($res->failureCount() != 0) +        { +            $this->retCode = self::FAILURES; +        } +        else if ($res->notImplementedCount() != 0) +        { +            $this->retCode = self::INCOMPLETES; +        } +        else if ($res->skippedCount() != 0) +        { +            $this->retCode = self::SKIPPED; +        } +    } + +    public function getRetCode() +    { +        return $this->retCode; +    } +     +    public function getLastErrorMessage() +    { +        return $this->lastErrorMessage; +    } +     +    public function getLastFailureMessage() +    { +        return $this->lastFailureMessage; +    } +     +    public function getLastIncompleteMessage() +    { +        return $this->lastIncompleteMessage; +    } +     +    public function getLastSkippedMessage() +    { +        return $this->lastSkippedMessage; +    } +     +    protected function composeMessage($message, PHPUnit_Framework_Test $test, Exception $e) +    { +        return "Test $message (" . $test->getName() . " in class " . get_class($test) . "): " . $e->getMessage(); +    } + +    /** +     * An error occurred. +     * +     * @param  PHPUnit_Framework_Test $test +     * @param  Exception              $e +     * @param  float                  $time +     */ +    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        $this->lastErrorMessage = $this->composeMessage("ERROR", $test, $e); +    } + +    /** +     * A failure occurred. +     * +     * @param  PHPUnit_Framework_Test                 $test +     * @param  PHPUnit_Framework_AssertionFailedError $e +     * @param  float                                  $time +     */ +    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) +    { +        $this->lastFailureMessage = $this->composeMessage("FAILURE", $test, $e); +    } + +    /** +     * Incomplete test. +     * +     * @param  PHPUnit_Framework_Test $test +     * @param  Exception              $e +     * @param  float                  $time +     */ +    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        $this->lastIncompleteMessage = $this->composeMessage("INCOMPLETE", $test, $e); +    } + +    /** +     * Skipped test. +     * +     * @param  PHPUnit_Framework_Test $test +     * @param  Exception              $e +     * @param  float                  $time +     * @since  Method available since Release 3.0.0 +     */ +    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        $this->lastSkippedMessage = $this->composeMessage("SKIPPED", $test, $e); +    } + +    /** +     * A test started. +     * +     * @param  string  $testName +     */ +    public function testStarted($testName) +    { +    } + +    /** +     * A test ended. +     * +     * @param  string  $testName +     */ +    public function testEnded($testName) +    { +    } + +    /** +     * A test failed. +     * +     * @param  integer                                 $status +     * @param  PHPUnit_Framework_Test                 $test +     * @param  PHPUnit_Framework_AssertionFailedError $e +     */ +    public function testFailed($status, PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e) +    { +    } + +    /** +     * Override to define how to handle a failed loading of +     * a test suite. +     * +     * @param  string  $message +     */ +    protected function runFailed($message) +    { +        throw new BuildException($message); +    } + +    /** +     * A test suite started. +     * +     * @param  PHPUnit_Framework_TestSuite $suite +     * @since  Method available since Release 2.2.0 +     */ +    public function startTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +    } + +    /** +     * A test suite ended. +     * +     * @param  PHPUnit_Framework_TestSuite $suite +     * @since  Method available since Release 2.2.0 +     */ +    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +    } + +    /** +     * A test started. +     * +     * @param  PHPUnit_Framework_Test $test +     */ +    public function startTest(PHPUnit_Framework_Test $test) +    { +    } + +    /** +     * A test ended. +     * +     * @param  PHPUnit_Framework_Test $test +     * @param  float                  $time +     */ +    public function endTest(PHPUnit_Framework_Test $test, $time) +    { +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php new file mode 100755 index 00000000..25a85f4c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php @@ -0,0 +1,141 @@ +<?php +/** + * $Id: c569f96e625ed8f9c6ae5add2b2f4a0a6c3e5a54 $ + * + * 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>. + */ + +/** + * Various utility functions + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: c569f96e625ed8f9c6ae5add2b2f4a0a6c3e5a54 $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class PHPUnitUtil +{ +    protected static $definedClasses = array(); +     +    /** +     * Returns the package of a class as defined in the docblock of the class using @package +     * +     * @param string the name of the class +     * @return string the name of the package +     */ +    static function getPackageName($classname) +    { +        $reflect = new ReflectionClass($classname); + +        if (preg_match('/@package[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches)) +        { +            return $matches[1]; +        } +        else +        { +            return "default"; +        } +    } +     +    /** +     * Returns the subpackage of a class as defined in the docblock of the class +     * using @subpackage +     * +     * @param string $classname the name of the class +     * +     * @author Benjamin Schultz <bschultz@proqrent.de> +     * @return string|null the name of the subpackage +     */ +    public static function getSubpackageName($classname) +    { +        $reflect = new ReflectionClass($classname); + +        if (preg_match('/@subpackage[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches)) { +            return $matches[1]; +        } else { +            return null; +        } +    } + +    /** +     * Derives the classname from a filename. +     * Assumes that there is only one class defined in that particular file, and that +     * the naming follows the dot-path (Java) notation scheme. +     * +     * @param string the filename +     * @return string the name fo the class +     */ +    public static function getClassFromFileName($filename) +    { +        $filename = basename($filename); +         +        $rpos = strrpos($filename, '.'); +         +        if ($rpos != -1) +        { +            $filename = substr($filename, 0, $rpos); +        } +         +        return $filename; +    } + +    /** +     * @param string the filename +     * @param Path optional classpath +     * @return array list of classes defined in the file +     */ +    public static function getDefinedClasses($filename, $classpath = NULL) +    { +        $filename = realpath($filename); +         +        if (!file_exists($filename)) +        { +            throw new Exception("File '" . $filename . "' does not exist"); +        } +         +        if (isset(self::$definedClasses[$filename])) +        { +            return self::$definedClasses[$filename]; +        } +         +        Phing::__import($filename, $classpath); + +        $declaredClasses = get_declared_classes(); +         +        foreach ($declaredClasses as $classname) +        { +            $reflect = new ReflectionClass($classname); +             +            self::$definedClasses[$reflect->getFilename()][] = $classname; +             +            if (is_array(self::$definedClasses[$reflect->getFilename()])) +            {            +                self::$definedClasses[$reflect->getFilename()] = array_unique(self::$definedClasses[$reflect->getFilename()]); +            } +        } +         +        if (isset(self::$definedClasses[$filename])) +        { +            return self::$definedClasses[$filename]; +        } +        else +        { +            return array(); +        } +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php new file mode 100755 index 00000000..4d03078d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php @@ -0,0 +1,87 @@ +<?php +/** + * $Id: 97f504caad678a6c7d231fe298c27d1281008e48 $ + * + * 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/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints Clover XML output of the test + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 97f504caad678a6c7d231fe298c27d1281008e48 $ + * @package phing.tasks.ext.formatter + * @since 2.4.0 + */ +class CloverPHPUnitResultFormatter extends PHPUnitResultFormatter +{ +    /** +     * @var PHPUnit_Framework_TestResult +     */ +    private $result = NULL; +     +    /** +     * PHPUnit version +     * @var string +     */ +    private $version = NULL; + +    public function __construct(PHPUnitTask $parentTask) +    { +        parent::__construct($parentTask); +         +        $this->version = PHPUnit_Runner_Version::id(); +    } + +    public function getExtension() +    { +        return ".xml"; +    } + +    public function getPreferredOutfile() +    { +        return "clover-coverage"; +    } + +    public function processResult(PHPUnit_Framework_TestResult $result) +    { +        $this->result = $result; +    } + +    public function endTestRun() +    { +        require_once 'PHP/CodeCoverage/Report/Clover.php'; +         +        $coverage = $this->result->getCodeCoverage(); +         +        if (!empty($coverage)) { +            $clover = new PHP_CodeCoverage_Report_Clover(); +             +            $contents = $clover->process($coverage); +     +            if ($this->out) +            { +                $this->out->write($contents); +                $this->out->close(); +            } +        } +         +        parent::endTestRun(); +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php new file mode 100755 index 00000000..1b09dbc1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php @@ -0,0 +1,203 @@ +<?php +/** + * $Id: cbf356a8395e116cd6ecddb7f5a822d4b6edf01c $ + * + * 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 'PHPUnit/Framework/TestListener.php'; + +require_once 'phing/system/io/Writer.php'; + +/** + * This abstract class describes classes that format the results of a PHPUnit testrun. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: cbf356a8395e116cd6ecddb7f5a822d4b6edf01c $ + * @package phing.tasks.ext.phpunit.formatter + * @since 2.1.0 + */ +abstract class PHPUnitResultFormatter implements PHPUnit_Framework_TestListener +{ +    protected $out = NULL; +     +    protected $project = NULL; +     +    private $timers = false; +     +    private $runCounts = false; +     +    private $failureCounts = false; +     +    private $errorCounts = false; +     +    private $incompleteCounts = false; +     +    private $skipCounts = false; +     +    /** +     * Constructor +     * @param PHPUnitTask $parentTask Calling Task +     */ +    public function __construct(PHPUnitTask $parentTask) +    { +        $this->project = $parentTask->getProject(); +    } +     +    /** +     * Sets the writer the formatter is supposed to write its results to. +     */ +    public function setOutput(Writer $out) +    { +        $this->out = $out;   +    } + +    /** +     * Returns the extension used for this formatter +     * +     * @return string the extension +     */ +    public function getExtension() +    { +        return ""; +    } + +    public function getPreferredOutfile() +    { +        return ""; +    } +     +    public function processResult(PHPUnit_Framework_TestResult $result) +    { +    } +     +    public function startTestRun() +    { +        $this->timers = array($this->getMicrotime()); +        $this->runCounts = array(0); +        $this->failureCounts = array(0); +        $this->errorCounts = array(0); +        $this->incompleteCounts = array(0); +        $this->skipCounts = array(0); +    } +     +    public function endTestRun() +    { +    } +     +    public function startTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        $this->timers[] = $this->getMicrotime(); +        $this->runCounts[] = 0; +        $this->failureCounts[] = 0; +        $this->errorCounts[] = 0; +        $this->incompleteCounts[] = 0; +        $this->skipCounts[] = 0; +    } +     +    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        $lastRunCount = array_pop($this->runCounts); +        $this->runCounts[count($this->runCounts) - 1] += $lastRunCount; +         +        $lastFailureCount = array_pop($this->failureCounts); +        $this->failureCounts[count($this->failureCounts) - 1] += $lastFailureCount; +         +        $lastErrorCount = array_pop($this->errorCounts); +        $this->errorCounts[count($this->errorCounts) - 1] += $lastErrorCount; +         +        $lastIncompleteCount = array_pop($this->incompleteCounts); +        $this->incompleteCounts[count($this->incompleteCounts) - 1] += $lastIncompleteCount; +         +        $lastSkipCount = array_pop($this->skipCounts); +        $this->skipCounts[count($this->skipCounts) - 1] += $lastSkipCount; +         +        array_pop($this->timers); +    } + +    public function startTest(PHPUnit_Framework_Test $test) +    { +        $this->runCounts[count($this->runCounts) - 1]++; +    } + +    public function endTest(PHPUnit_Framework_Test $test, $time) +    { +    } + +    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        $this->errorCounts[count($this->errorCounts) - 1]++; +    } + +    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) +    { +        $this->failureCounts[count($this->failureCounts) - 1]++; +    } + +    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        $this->incompleteCounts[count($this->incompleteCounts) - 1]++; +    } + +    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        $this->skipCounts[count($this->skipCounts) - 1]++; +    } +     +    public function getRunCount() +    { +        return end($this->runCounts); +    } +     +    public function getFailureCount() +    { +        return end($this->failureCounts); +    } +     +    public function getErrorCount() +    { +        return end($this->errorCounts); +    } +     +    public function getIncompleteCount() +    { +        return end($this->incompleteCounts); +    } +     +    public function getSkippedCount() +    { +        return end($this->skipCounts); +    } +     +    public function getElapsedTime() +    { +        if (end($this->timers)) +        { +            return $this->getMicrotime() - end($this->timers); +        } +        else +        { +            return 0; +        } +    } + +    private function getMicrotime() { +        list($usec, $sec) = explode(' ', microtime()); +        return (float)$usec + (float)$sec; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php new file mode 100755 index 00000000..e67cfd2b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php @@ -0,0 +1,128 @@ +<?php +/** + * $Id: 529f9b6ab9ced7b78871e3612cd8afce58261a6f $ + * + * 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/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints plain text output of the test to a specified Writer. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 529f9b6ab9ced7b78871e3612cd8afce58261a6f $ + * @package phing.tasks.ext.phpunit.formatter + * @since 2.1.0 + */ +class PlainPHPUnitResultFormatter extends PHPUnitResultFormatter +{ +    private $inner = ""; +     +    public function getExtension() +    { +        return ".txt"; +    } +     +    public function getPreferredOutfile() +    { +        return "testresults"; +    } + +    public function startTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        parent::startTestSuite($suite); +         +        $this->inner = ""; +    } +     +    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        if ($suite->getName() == 'AllTests') +        { +            return false; +        } +         +        $sb = "Testsuite: " . $suite->getName() . "\n"; +        $sb.= "Tests run: " . $this->getRunCount(); +        $sb.= ", Failures: " . $this->getFailureCount(); +        $sb.= ", Errors: " . $this->getErrorCount(); +        $sb.= ", Incomplete: " . $this->getIncompleteCount(); +        $sb.= ", Skipped: " . $this->getSkippedCount(); +        $sb.= ", Time elapsed: " . sprintf('%0.5f', $this->getElapsedTime()) . " s\n"; + +        if ($this->out != NULL) +        { +            $this->out->write($sb); +            $this->out->write($this->inner); +        } + +        parent::endTestSuite($suite); +    } + +    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        parent::addError($test, $e, $time); +         +        $this->formatError("ERROR", $test, $e); +    } + +    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) +    { +        parent::addFailure($test, $e, $time); +        $this->formatError("FAILED", $test, $e); +    } + +    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        parent::addIncompleteTest($test, $e, $time); +         +        $this->formatError("INCOMPLETE", $test); +    } + +    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        parent::addSkippedTest($test, $e, $time); +        $this->formatError("SKIPPED", $test); +    } + +    private function formatError($type, PHPUnit_Framework_Test $test, Exception $e = null) +    { +        if ($test != null) +        { +            $this->endTest($test, time()); +        } +         +        $this->inner.= $test->getName() . " " . $type . "\n"; +         +        if ($e !== null) { +            $this->inner.= $e->getMessage() . "\n"; +            // $this->inner.= PHPUnit_Util_Filter::getFilteredStackTrace($e, true) . "\n"; +        } +    } +     +    public function endTestRun() +    { +        parent::endTestRun(); +         +        if ($this->out != NULL) +        { +            $this->out->close(); +        } +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php new file mode 100755 index 00000000..0007c235 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php @@ -0,0 +1,62 @@ +<?php +/** + * $Id: bd9c51fa75c9b856105fc810200028d855a3782d $ + * + * 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/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints short summary output of the test to Phing's logging system. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: bd9c51fa75c9b856105fc810200028d855a3782d $ + * @package phing.tasks.ext.formatter + * @since 2.1.0 + */  +class SummaryPHPUnitResultFormatter extends PHPUnitResultFormatter +{ +    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        parent::endTestSuite($suite); +    } +     +    public function endTestRun() +    { +        parent::endTestRun(); +         +        $sb = "Total tests run: " . $this->getRunCount(); +        $sb.= ", Failures: " . $this->getFailureCount(); +        $sb.= ", Errors: " . $this->getErrorCount(); +        $sb.= ", Incomplete: " . $this->getIncompleteCount(); +        $sb.= ", Skipped: " . $this->getSkippedCount(); +        $sb.= ", Time elapsed: " . sprintf('%0.5f', $this->getElapsedTime()) . " s\n"; +         +        if ($this->out != NULL) +        { +            $this->out->write($sb); +            $this->out->close(); +        } +    } +     +    public function getExtension() +    { +        return NULL; +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php new file mode 100755 index 00000000..7fef7454 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php @@ -0,0 +1,120 @@ +<?php +/** + * $Id: 3d9c47a29ded9b67b3a3e10c55602b0ab2a9ea38 $ + * + * 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 'PHPUnit/Util/Log/JUnit.php'; + +require_once 'phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints XML output of the test to a specified Writer + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 3d9c47a29ded9b67b3a3e10c55602b0ab2a9ea38 $ + * @package phing.tasks.ext.formatter + * @since 2.1.0 + */ +class XMLPHPUnitResultFormatter extends PHPUnitResultFormatter +{ +    /** +     * @var PHPUnit_Util_Log_JUnit +     */ +    private $logger = NULL; + +    public function __construct(PHPUnitTask $parentTask) +    { +        parent::__construct($parentTask); +         +        $logIncompleteSkipped = $parentTask->getHaltonincomplete() || $parentTask->getHaltonskipped(); +         +        $this->logger = new PHPUnit_Util_Log_JUnit(null, $logIncompleteSkipped); +        $this->logger->setWriteDocument(false); +    } + +    public function getExtension() +    { +        return ".xml"; +    } + +    public function getPreferredOutfile() +    { +        return "testsuites"; +    } + +    public function startTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        parent::startTestSuite($suite); + +        $this->logger->startTestSuite($suite); +    } + +    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) +    { +        parent::endTestSuite($suite); + +        $this->logger->endTestSuite($suite); +    } + +    public function startTest(PHPUnit_Framework_Test $test) +    { +        parent::startTest($test); + +        $this->logger->startTest($test); +    } + +    public function endTest(PHPUnit_Framework_Test $test, $time) +    { +        parent::endTest($test, $time); + +        $this->logger->endTest($test, $time); +    } + +    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        parent::addError($test, $e, $time); + +        $this->logger->addError($test, $e, $time); +    } + +    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) +    { +        parent::addFailure($test, $e, $time); + +        $this->logger->addFailure($test, $e, $time); +    } + +    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) +    { +        parent::addIncompleteTest($test, $e, $time); + +        $this->logger->addIncompleteTest($test, $e, $time); +    } + +    public function endTestRun() +    { +        parent::endTestRun(); + +        if ($this->out) +        { +            $this->out->write($this->logger->getXML()); +            $this->out->close(); +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php deleted file mode 100644 index 63f8911a..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php -/** - * $Id: BatchTest.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/types/FileSet.php'; - -/** - * Scans a list of (.php) files given by the fileset attribute, extracts - * all subclasses of PHPUnit2_Framework_TestCase. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: BatchTest.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class BatchTest -{ -	/** the list of filesets containing the testcase filename rules */ -	private $filesets = array(); - -	/** the reference to the project */ -	private $project = NULL; - -	/** the classpath to use with Phing::__import() calls */ -	private $classpath = NULL; -	 -	/** names of classes to exclude */ -	private $excludeClasses = array(); -	 -	/** -	 * Create a new batchtest instance -	 * -	 * @param Project the project it depends on. -	 */ -	function __construct(Project $project) -	{ -		$this->project = $project; -	} -	 -	/** -	 * Sets the classes to exclude -	 */ -	function setExclude($exclude) -	{ -		$this->excludeClasses = explode(" ", $exclude); -	} - -	/** -	 * Sets the classpath -	 */ -	function setClasspath(Path $classpath) -	{ -		if ($this->classpath === null) -		{ -			$this->classpath = $classpath; -		} -		else -		{ -			$this->classpath->append($classpath); -		} -	} - -	/** -	 * Creates a new Path object -	 */ -	function createClasspath() -	{ -		$this->classpath = new Path(); -		return $this->classpath; -	} - -	/** -	 * Returns the classpath -	 */ -	function getClasspath() -	{ -		return $this->classpath; -	} - -	/** -	 * Add a new fileset containing the XML results to aggregate -	 * -	 * @param FileSet the new fileset containing XML results. -	 */ -	function addFileSet(FileSet $fileset) -	{ -		$this->filesets[] = $fileset; -	} - -	/** -	 * Iterate over all filesets and return the filename of all files -	 * that end with .php. -	 * -	 * @return array an array of filenames -	 */ -	private function getFilenames() -	{ -		$filenames = array(); - -		foreach ($this->filesets as $fileset) -		{ -			$ds = $fileset->getDirectoryScanner($this->project); -			$ds->scan(); - -			$files = $ds->getIncludedFiles(); - -			foreach ($files as $file) -			{ -				if (strstr($file, ".php")) -				{ -					$filenames[] = $ds->getBaseDir() . "/" . $file; -				} -			} -		} - -		return $filenames; -	} -	 -	/** -	 * Filters an array of classes, removes all classes that are not subclasses of PHPUnit2_Framework_TestCase, -	 * or classes that are declared abstract -	 */ -	private function filterTests($input) -	{ -		$reflect = new ReflectionClass($input); -		 -		return is_subclass_of($input, 'PHPUnit2_Framework_TestCase') && (!$reflect->isAbstract()); -	} - -	/** -	 * Returns an array of PHPUnit2_Framework_TestCase classes that are declared -	 * by the files included by the filesets -	 * -	 * @return array an array of PHPUnit2_Framework_TestCase classes. -	 */ -	function elements() -	{ -		$filenames = $this->getFilenames(); -		 -		$declaredClasses = array();		 - -		foreach ($filenames as $filename) -		{ -			$definedClasses = PHPUnit2Util::getDefinedClasses($filename); -			 -			$declaredClasses = array_merge($declaredClasses, $definedClasses); -		} -		 -		$elements = array_filter($declaredClasses, array($this, "filterTests")); - -		return $elements; -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php deleted file mode 100644 index 9d2a4656..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php -/** - * $Id: FormatterElement.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/ext/phpunit2/XMLPHPUnit2ResultFormatter.php'; -require_once 'phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php'; -require_once 'phing/system/io/PhingFile.php'; - -/** - * A wrapper for the implementations of PHPUnit2ResultFormatter. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: FormatterElement.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class FormatterElement -{ -	protected $formatter = NULL; -	 -	protected $type = ""; -	 -	protected $useFile = true; -	 -	protected $toDir = "."; -	 -	protected $outfile = ""; - -	function setType($type) -	{ -		$this->type = $type; - -		if ($this->type == "xml") -		{ -			$destFile = new PhingFile($this->toDir, 'testsuites.xml'); -			$this->formatter = new XMLPHPUnit2ResultFormatter(); -		} -		else -		if ($this->type == "plain") -		{ -			$this->formatter = new PlainPHPUnit2ResultFormatter(); -		} -		else -		{ -			throw new BuildException("Formatter '" . $this->type . "' not implemented"); -		} -	} - -	function setClassName($className) -	{ -		$classNameNoDot = Phing::import($className); - -		$this->formatter = new $classNameNoDot(); -	} - -	function setUseFile($useFile) -	{ -		$this->useFile = $useFile; -	} -	 -	function getUseFile() -	{ -		return $this->useFile; -	} -	 -	function setToDir($toDir) -	{ -		$this->toDir = $toDir; -	} -	 -	function getToDir() -	{ -		return $this->toDir; -	} - -	function setOutfile($outfile) -	{ -		$this->outfile = $outfile; -	} -	 -	function getOutfile() -	{ -		if ($this->outfile) -		{ -			return $this->outfile; -		} -		else -		{ -			return $this->formatter->getPreferredOutfile() . $this->getExtension(); -		} -	} -	 -	function getExtension() -	{ -		return $this->formatter->getExtension(); -	} - -	function getFormatter() -	{ -		return $this->formatter; -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php deleted file mode 100644 index 1e08e79c..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php -/** - * $Id: PHPUnit2ReportTask.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/Task.php'; -require_once 'phing/system/io/PhingFile.php'; -require_once 'phing/system/io/FileWriter.php'; -require_once 'phing/util/ExtendedFileStream.php'; - -/** - * Transform a PHPUnit2 xml report using XSLT. - * This transformation generates an html report in either framed or non-framed - * style. The non-framed style is convenient to have a concise report via mail,  - * the framed report is much more convenient if you want to browse into  - * different packages or testcases since it is a Javadoc like report. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2ReportTask.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PHPUnit2ReportTask extends Task -{ -	private $format = "noframes"; -	private $styleDir = ""; -	private $toDir = ""; - -	/** the directory where the results XML can be found */ -	private $inFile = "testsuites.xml"; - -	/** -	 * Set the filename of the XML results file to use. -	 */ -	function setInFile($inFile) -	{ -		$this->inFile = $inFile; -	} - -	/** -	 * Set the format of the generated report. Must be noframes or frames. -	 */ -	function setFormat($format) -	{ -		$this->format = $format; -	} - -	/** -	 * Set the directory where the stylesheets are located. -	 */ -	function setStyleDir($styleDir) -	{ -		$this->styleDir = $styleDir; -	} - -	/** -	 * Set the directory where the files resulting from the  -	 * transformation should be written to. -	 */ -	function setToDir($toDir) -	{ -		$this->toDir = $toDir; -	} - -	private function getStyleSheet() -	{ -		$xslname = "phpunit2-" . $this->format . ".xsl"; - -		if ($this->styleDir) -		{ -			$file = new PhingFile($this->styleDir, $xslname); -		} -		else -		{ -			$path = Phing::getResourcePath("phing/etc/$xslname"); -			 -			if ($path === NULL) -			{ -				$path = Phing::getResourcePath("etc/$xslname"); - -				if ($path === NULL) -				{ -					throw new BuildException("Could not find $xslname in resource path"); -				} -			} -			 -			$file = new PhingFile($path); -		} - -		if (!$file->exists()) -		{ -			throw new BuildException("Could not find file " . $file->getPath()); -		} - -		return $file; -	} - -	function transform($document) -	{ -		$dir = new PhingFile($this->toDir); -		 -		if (!$dir->exists()) -		{ -			throw new BuildException("Directory '" . $this->toDir . "' does not exist"); -		} -		 -		$xslfile = $this->getStyleSheet(); - -		$xsl = new DOMDocument(); -		$xsl->load($xslfile->getAbsolutePath()); - -		$proc = new XSLTProcessor(); -		$proc->importStyleSheet($xsl); - -		if ($this->format == "noframes") -		{ -			$writer = new FileWriter(new PhingFile($this->toDir, "phpunit2-noframes.html")); -			$writer->write($proc->transformToXML($document)); -			$writer->close(); -		} -		else -		{ -			ExtendedFileStream::registerStream(); - -			// no output for the framed report -			// it's all done by extension... -			$dir = new PhingFile($this->toDir); -			$proc->setParameter('', 'output.dir', $dir->getAbsolutePath()); -			$proc->transformToXML($document); -		} -	} - -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$testSuitesDoc = new DOMDocument(); -		$testSuitesDoc->load($this->inFile); -		 -		$this->transform($testSuitesDoc); -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php deleted file mode 100644 index 5722c63e..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -/** - * $Id: PHPUnit2ResultFormatter.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 'PHPUnit2/Framework/TestListener.php'; - -require_once 'phing/system/io/Writer.php'; - -/** - * This abstract class describes classes that format the results of a PHPUnit2 testrun. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -abstract class PHPUnit2ResultFormatter implements PHPUnit2_Framework_TestListener -{ -	protected $out = NULL; -	 -	protected $project = NULL; -	 -	private $timer = NULL; - -	private $runCount = 0; -	 -	private $failureCount = 0; -	 -	private $errorCount = 0;	 -	 -	/** -	 * Sets the writer the formatter is supposed to write its results to. -   	 */ -	function setOutput(Writer $out) -	{ -		$this->out = $out;	 -	} - -	/** -	 * Returns the extension used for this formatter -	 * -	 * @return string the extension -	 */ -	function getExtension() -	{ -		return ""; -	} - -	/** -	 * Sets the project -	 * -	 * @param Project the project -	 */ -	function setProject(Project $project) -	{ -		$this->project = $project; -	} -	 -	function getPreferredOutfile() -	{ -		return ""; -	} -	 -	function startTestRun() -	{ -	} -	 -	function endTestRun() -	{ -	} -	 -	function startTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		$this->runCount = 0; -		$this->failureCount = 0; -		$this->errorCount = 0; -		 -		$this->timer = new Timer(); -		$this->timer->start(); -	} -	 -	function endTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		$this->timer->stop(); -	} - -	function startTest(PHPUnit2_Framework_Test $test) -	{ -		$this->runCount++; -	} - -	function endTest(PHPUnit2_Framework_Test $test) -	{ -	} - -	function addError(PHPUnit2_Framework_Test $test, Exception $e) -	{ -		$this->errorCount++; -	} - -	function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t) -	{ -		$this->failureCount++; -	} - -	function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) -	{ -	} - -	function getRunCount() -	{ -		return $this->runCount; -	} -	 -	function getFailureCount() -	{ -		return $this->failureCount; -	} -	 -	function getErrorCount() -	{ -		return $this->errorCount; -	} -	 -	function getElapsedTime() -	{ -		if ($this->timer) -		{ -			return $this->timer->getElapsedTime(); -		} -		else -		{ -			return 0; -		} -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php deleted file mode 100644 index ffd36405..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php -/** - * $Id: PHPUnit2Task.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/Task.php'; -require_once 'phing/system/io/PhingFile.php'; -require_once 'phing/system/io/Writer.php'; -require_once 'phing/util/LogWriter.php'; - -/** - * Runs PHPUnit2 tests. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2Task.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @see BatchTest - * @since 2.1.0 - */ -class PHPUnit2Task extends Task -{ -	private $batchtests = array(); -	private $formatters = array(); -	private $haltonerror = false; -	private $haltonfailure = false; -	private $failureproperty; -	private $errorproperty; -	private $printsummary = false; -	private $testfailed = false; -	private $codecoverage = false; - -	/** -	 * Initialize Task. - 	 * This method includes any necessary PHPUnit2 libraries and triggers -	 * appropriate error if they cannot be found.  This is not done in header -	 * because we may want this class to be loaded w/o triggering an error. -	 */ -	function init() { -		include_once 'PHPUnit2/Util/Filter.php'; -		if (!class_exists('PHPUnit2_Util_Filter')) { -			throw new BuildException("PHPUnit2Task depends on PEAR PHPUnit2 package being installed.", $this->getLocation()); -		} -		 -		if (version_compare(PHP_VERSION, '5.0.3') < 0) { -		    throw new BuildException("PHPUnit2Task requires PHP version >= 5.0.3.", $this->getLocation()); -		} - -		// other dependencies that should only be loaded when class is actually used. -		require_once 'phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php'; -		require_once 'phing/tasks/ext/phpunit2/BatchTest.php'; -		require_once 'phing/tasks/ext/phpunit2/FormatterElement.php'; -		require_once 'phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php'; - -		// add some defaults to the PHPUnit2 Filter -		PHPUnit2_Util_Filter::addFileToFilter('PHPUnit2Task.php'); -		PHPUnit2_Util_Filter::addFileToFilter('PHPUnit2TestRunner.php'); -		PHPUnit2_Util_Filter::addFileToFilter('phing/Task.php'); -		PHPUnit2_Util_Filter::addFileToFilter('phing/Target.php'); -		PHPUnit2_Util_Filter::addFileToFilter('phing/Project.php'); -		PHPUnit2_Util_Filter::addFileToFilter('phing/Phing.php'); -		PHPUnit2_Util_Filter::addFileToFilter('phing.php'); - -	} -	 -	function setFailureproperty($value) -	{ -		$this->failureproperty = $value; -	} -	 -	function setErrorproperty($value) -	{ -		$this->errorproperty = $value; -	} -	 -	function setHaltonerror($value) -	{ -		$this->haltonerror = $value; -	} - -	function setHaltonfailure($value) -	{ -		$this->haltonfailure = $value; -	} - -	function setPrintsummary($printsummary) -	{ -		$this->printsummary = $printsummary; -	} -	 -	function setCodecoverage($codecoverage) -	{ -		$this->codecoverage = $codecoverage; -	} - -	/** -	 * Add a new formatter to all tests of this task. -	 * -	 * @param FormatterElement formatter element -	 */ -	function addFormatter(FormatterElement $fe) -	{ -		$this->formatters[] = $fe; -	} - -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$tests = array(); -		 -		if ($this->printsummary) -		{ -			$fe = new FormatterElement(); -			$fe->setClassName('SummaryPHPUnit2ResultFormatter'); -			$fe->setUseFile(false); -			$this->formatters[] = $fe; -		} -		 -		foreach ($this->batchtests as $batchtest) -		{ -			$tests = array_merge($tests, $batchtest->elements()); -		}			 -		 -		foreach ($this->formatters as $fe) -		{ -			$formatter = $fe->getFormatter();			 -			$formatter->setProject($this->getProject()); - -			if ($fe->getUseFile()) -			{ -				$destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); -				 -				$writer = new FileWriter($destFile->getAbsolutePath()); - -				$formatter->setOutput($writer); -			} -			else -			{ -				$formatter->setOutput($this->getDefaultOutput()); -			} - -			$formatter->startTestRun(); -		} -		 -		foreach ($tests as $test) -		{ -			$this->execute(new PHPUnit2_Framework_TestSuite(new ReflectionClass($test))); -		} - -		foreach ($this->formatters as $fe) -		{ -			$formatter = $fe->getFormatter(); -			$formatter->endTestRun(); -		} -		 -		if ($this->testfailed) -		{ -			throw new BuildException("One or more tests failed"); -		} -	} - -	/** -	 * @throws BuildException -	 */ -	private function execute($suite) -	{ -		$runner = new PHPUnit2TestRunner($suite, $this->project); -		 -		$runner->setCodecoverage($this->codecoverage); - -		foreach ($this->formatters as $fe) -		{ -			$formatter = $fe->getFormatter(); - -			$runner->addFormatter($formatter); -		} - -		$runner->run(); - -		$retcode = $runner->getRetCode(); -		 -		if ($retcode == PHPUnit2TestRunner::ERRORS) { -		    if ($this->errorproperty) { -				$this->project->setNewProperty($this->errorproperty, true); -			} -			if ($this->haltonerror) { -			    $this->testfailed = true; -			} -		} elseif ($retcode == PHPUnit2TestRunner::FAILURES) { -			if ($this->failureproperty) { -				$this->project->setNewProperty($this->failureproperty, true); -			} -			 -			if ($this->haltonfailure) { -				$this->testfailed = true; -			} -		} -		 -	} - -	private function getDefaultOutput() -	{ -		return new LogWriter($this); -	} - -	/** -	 * Adds a set of tests based on pattern matching. -	 * -	 * @return BatchTest a new instance of a batch test. -	 */ -	function createBatchTest() -	{ -		$batchtest = new BatchTest($this->getProject()); - -		$this->batchtests[] = $batchtest; - -		return $batchtest; -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php deleted file mode 100644 index bbd19f34..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php -/** - * $Id: PHPUnit2TestRunner.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 'PHPUnit2/Framework/TestListener.php'; -require_once 'PHPUnit2/Framework/TestResult.php'; -require_once 'PHPUnit2/Framework/TestSuite.php'; - -require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; - -require_once 'phing/system/util/Timer.php'; - -/** - * Simple Testrunner for PHPUnit2 that runs all tests of a testsuite. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2TestRunner.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PHPUnit2TestRunner -{ -	const SUCCESS = 0; -	const FAILURES = 1; -	const ERRORS = 2; - -	private $test = NULL; -	private $suite = NULL; -	private $retCode = 0; -	private $formatters = array(); -	 -	private $codecoverage = false; -	 -	private $project = NULL; - -	function __construct(PHPUnit2_Framework_TestSuite $suite, Project $project) -	{ -		$this->suite = $suite; -		$this->project = $project; -		$this->retCode = self::SUCCESS; -	} -	 -	function setCodecoverage($codecoverage) -	{ -		$this->codecoverage = $codecoverage; -	} - -	function addFormatter(PHPUnit2_Framework_TestListener $formatter) -	{ -		$this->formatters[] = $formatter; -	} - -	function run() -	{ -		$res = new PHPUnit2_Framework_TestResult(); - -		if ($this->codecoverage) -		{ -			$res->collectCodeCoverageInformation(TRUE); -		} - -		foreach ($this->formatters as $formatter) -		{ -			$res->addListener($formatter); -		} - -		$this->suite->run($res); -		 -		if ($this->codecoverage) -		{ -			CoverageMerger::merge($this->project, $res->getCodeCoverageInformation()); -		} -		 -		if ($res->errorCount() != 0) -		{ -			$this->retCode = self::ERRORS; -		} - -		else if ($res->failureCount() != 0 || $res->notImplementedCount() != 0) -		{ -			$this->retCode = self::FAILURES; -		} -	} - -	function getRetCode() -	{ -		return $this->retCode; -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php deleted file mode 100644 index f4d1f62a..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php -/** - * $Id: PHPUnit2Util.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>. - */ - -/** - * Various utility functions - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2Util.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PHPUnit2Util -{ -	protected static $definedClasses = array(); -	 -	/** -	 * Returns the package of a class as defined in the docblock of the class using @package -	 * -	 * @param string the name of the class -	 * @return string the name of the package -	 */ -	static function getPackageName($classname) -	{ -		$reflect = new ReflectionClass($classname); - -		if (preg_match('/@package[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches)) -		{ -			return $matches[1]; -		} -		else -		{ -			return "default"; -		} -	} -	 -	/** -	 * Derives the classname from a filename. -	 * Assumes that there is only one class defined in that particular file, and that -	 * the naming follows the dot-path (Java) notation scheme. -	 * -	 * @param string the filename -	 * @return string the name fo the class -	 */ -	static function getClassFromFileName($filename) -	{ -		$filename = basename($filename); -		 -		$rpos = strrpos($filename, '.'); -		 -		if ($rpos != -1) -		{ -			$filename = substr($filename, 0, $rpos); -		} -		 -		return $filename; -	} - -	/** -	 * @param string the filename -	 * @param Path optional classpath -	 * @return array list of classes defined in the file -	 */ -	static function getDefinedClasses($filename, $classpath = NULL) -	{ -		$filename = realpath($filename); -		 -		if (!file_exists($filename)) -		{ -			throw new Exception("File '" . $filename . "' does not exist"); -		} -		 -		if (isset(self::$definedClasses[$filename])) -		{ -			return self::$definedClasses[$filename]; -		} -		 -		Phing::__import($filename, $classpath); - -		$declaredClasses = get_declared_classes(); -		 -		foreach ($declaredClasses as $classname) -		{ -			$reflect = new ReflectionClass($classname); -			 -			self::$definedClasses[$reflect->getFilename()][] = $classname; -			 -			if (is_array(self::$definedClasses[$reflect->getFilename()])) -			{			 -				self::$definedClasses[$reflect->getFilename()] = array_unique(self::$definedClasses[$reflect->getFilename()]); -			} -		} -				 -		return self::$definedClasses[$filename]; -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php deleted file mode 100644 index b0a9ae58..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php -/** - * $Id: PlainPHPUnit2ResultFormatter.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 'PHPUnit2/Framework/Test.php'; -require_once 'PHPUnit2/Util/Filter.php'; - -require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php'; - -/** - * Prints plain text output of the test to a specified Writer. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PlainPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PlainPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter -{ -	private $inner = ""; -	 -	function getExtension() -	{ -		return ".txt"; -	} -	 -	function getPreferredOutfile() -	{ -		return "testresults"; -	} - -	function startTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		parent::startTestSuite($suite); -		 -		$this->inner = ""; -	} -	 -	function endTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		parent::endTestSuite($suite); -		 -		$sb = "Testsuite: " . $suite->getName() . "\n"; -		$sb.= "Tests run: " . $this->getRunCount(); -		$sb.= ", Failures: " . $this->getFailureCount(); -		$sb.= ", Errors: " . $this->getErrorCount(); -		$sb.= ", Time elapsed: " . $this->getElapsedTime(); -		$sb.= " sec\n"; - -		if ($this->out != NULL) -		{ -			$this->out->write($sb); -			$this->out->write($this->inner); -		} -	} - -	function addError(PHPUnit2_Framework_Test $test, Exception $e) -	{ -		parent::addError($test, $e); -		 -		$this->formatError("ERROR", $test, $e); -	} - -	function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t) -	{ -		parent::addFailure($test, $t); -		 -		$this->formatError("FAILED", $test, $t); -	} - -	function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) -	{ -		parent::addIncompleteTest($test, $e); -		 -		$this->formatError("INCOMPLETE", $test, $e); -	} - -	private function formatError($type, PHPUnit2_Framework_Test $test, Exception $e) -	{ -		if ($test != null) -		{ -			$this->endTest($test); -		} - -		$this->inner.= $test->getName() . " " . $type . "\n"; -		$this->inner.= $e->getMessage() . "\n"; -		$this->inner.= PHPUnit2_Util_Filter::getFilteredStackTrace($e) . "\n"; -	} -	 -	function endTestRun() -	{ -		parent::endTestRun(); -		 -		if ($this->out != NULL) -		{ -			$this->out->close(); -		} -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php deleted file mode 100644 index ac2fec8f..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php -/** - * $Id: XMLPHPUnit2ResultFormatter.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 'PHPUnit2/Framework/Test.php'; -require_once 'PHPUnit2/Runner/Version.php'; - -require_once 'PHPUnit2/Util/Log/XML.php'; - -require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php'; - -/** - * Prints XML output of the test to a specified Writer - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: XMLPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class XMLPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter -{ -	private $logger = NULL; -	 -	function __construct() -	{ -		$this->logger = new PHPUnit2_Util_Log_XML(); -		$this->logger->setWriteDocument(false); -	} -	 -	function getExtension() -	{ -		return ".xml"; -	} -	 -	function getPreferredOutfile() -	{ -		return "testsuites"; -	} -	 -	function startTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		parent::startTestSuite($suite); -		 -		$this->logger->startTestSuite($suite); -	} -	 -	function endTestSuite(PHPUnit2_Framework_TestSuite $suite) -	{ -		parent::endTestSuite($suite); -		 -		$this->logger->endTestSuite($suite); -	} -	 -	function startTest(PHPUnit2_Framework_Test $test) -	{ -		parent::startTest($test); -		 -		$this->logger->startTest($test); -	} - -	function endTest(PHPUnit2_Framework_Test $test) -	{ -		parent::endTest($test); -		 -		$this->logger->endTest($test); -	} -	 -	function addError(PHPUnit2_Framework_Test $test, Exception $e) -	{ -		parent::addError($test, $e); -		 -		$this->logger->addError($test, $e); -	} - -	function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t) -	{ -		parent::addFailure($test, $t); -		 -		$this->logger->addFailure($test, $t); -	} - -	function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) -	{ -		parent::addIncompleteTest($test, $e); -		 -		$this->logger->addIncompleteTest($test, $e); -	} -	 -	function endTestRun() -	{ -		parent::endTestRun(); -		 -		if ($this->out) -		{ -			$this->out->write($this->logger->getXML()); -			$this->out->close(); -		} -	} -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/rSTTask.php b/buildscripts/phing/classes/phing/tasks/ext/rSTTask.php new file mode 100644 index 00000000..77170f18 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/rSTTask.php @@ -0,0 +1,476 @@ +<?php + +/** + * reStructuredText rendering task for Phing, the PHP build tool. + * + * PHP version 5 + * + * @category   Tasks + * @package    phing.tasks.ext + * @author     Christian Weiske <cweiske@cweiske.de> + * @license    LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link       http://www.phing.info/ + * @version    SVN: $Id: ad2ac21008b4635c4f557e3a65c9306a350ca1f2 $ + */ + +require_once 'phing/Task.php'; +require_once 'phing/util/FileUtils.php'; + +/** + * reStructuredText rendering task for Phing, the PHP build tool. + * + * PHP version 5 + * + * @category   Tasks + * @package    phing.tasks.ext + * @author     Christian Weiske <cweiske@cweiske.de> + * @license    LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link       http://www.phing.info/ + */ +class rSTTask extends Task +{ +    /** +     * @var string Taskname for logger +     */ +    protected $taskName = 'rST'; + +    /** +     * Result format, defaults to "html". +     * @see $supportedFormats for all possible options +     * +     * @var string +     */ +    protected $format = 'html'; + +    /** +     * Array of supported output formats +     * +     * @var array +     * @see $format +     * @see $targetExt +     */ +    protected static $supportedFormats = array( +        'html', 'latex', 'man', 'odt', 's5', 'xml' +    ); + +    /** +     * Maps formats to file extensions +     * +     * @var array +     */ +    protected static $targetExt = array( +        'html'  => 'html', +        'latex' => 'tex', +        'man'   => '3', +        'odt'   => 'odt', +        's5'    => 'html', +        'xml'   => 'xml', +    ); + +    /** +     * Input file in rST format. +     * Required +     * +     * @var string +     */ +    protected $file = null; + +    /** +     * Additional rst2* tool parameters. +     * +     * @var string +     */ +    protected $toolParam = null; + +    /** +     * Full path to the tool, i.e. /usr/local/bin/rst2html +     * +     * @var string +     */ +    protected $toolPath = null; + +    /** +     * Output file or directory. May be omitted. +     * When it ends with a slash, it is considered to be a directory +     * +     * @var string +     */ +    protected $destination = null; + +    protected $filesets      = array(); // all fileset objects assigned to this task +    protected $mapperElement = null; + +    /** +     * all filterchains objects assigned to this task +     * +     * @var array +     */ +    protected $filterChains = array(); + +    /** +     * mode to create directories with +     * +     * @var integer +     */ +    protected $mode = 0755; + +    /** +     * Only render files whole source files are newer than the +     * target files +     * +     * @var boolean +     */ +    protected $uptodate = false; + + +    /** +     * Init method: requires the PEAR System class +     */ +    public function init() +    { +        require_once 'System.php'; +    } + +    /** +     * The main entry point method. +     * +     * @return void +     */ +    public function main() +    { +        $tool = $this->getToolPath($this->format); +        if (count($this->filterChains)) { +            $this->fileUtils = new FileUtils(); +        } + +        if ($this->file != '') { +            $file   = $this->file; +            $targetFile = $this->getTargetFile($file, $this->destination); +            $this->render($tool, $file, $targetFile); +            return; +        } + +        if (!count($this->filesets)) { +            throw new BuildException( +                '"file" attribute or "fileset" subtag required' +            ); +        } + +        // process filesets +        $mapper = null; +        if ($this->mapperElement !== null) { +            $mapper = $this->mapperElement->getImplementation(); +        } + +        $project = $this->getProject(); +        foreach ($this->filesets as $fs) { +            $ds = $fs->getDirectoryScanner($project); +            $fromDir  = $fs->getDir($project); +            $srcFiles = $ds->getIncludedFiles(); + +            foreach ($srcFiles as $src) { +                $file  = new PhingFile($fromDir, $src); +                if ($mapper !== null) { +                    $results = $mapper->main($file); +                    if ($results === null) { +                        throw new BuildException( +                            sprintf( +                                'No filename mapper found for "%s"', +                                $file +                            ) +                        ); +                    } +                    $targetFile = reset($results); +                } else { +                    $targetFile = $this->getTargetFile($file, $this->destination); +                } +                $this->render($tool, $file, $targetFile); +            } +        } +    } + + + +    /** +     * Renders a single file and applies filters on it +     * +     * @param string $tool       conversion tool to use +     * @param string $source     rST source file +     * @param string $targetFile target file name +     * +     * @return void +     */ +    protected function render($tool, $source, $targetFile) +    { +        if (count($this->filterChains) == 0) { +            return $this->renderFile($tool, $source, $targetFile); +        } + +        $tmpTarget = tempnam(sys_get_temp_dir(), 'rST-'); +        $this->renderFile($tool, $source, $tmpTarget); + +        $this->fileUtils->copyFile( +            new PhingFile($tmpTarget), +            new PhingFile($targetFile), +            true, false, $this->filterChains, +            $this->getProject(), $this->mode +        ); +        unlink($tmpTarget); +    } + + + +    /** +     * Renders a single file with the rST tool. +     * +     * @param string $tool       conversion tool to use +     * @param string $source     rST source file +     * @param string $targetFile target file name +     * +     * @return void +     * +     * @throws BuildException When the conversion fails +     */ +    protected function renderFile($tool, $source, $targetFile) +    { +        if ($this->uptodate && file_exists($targetFile) +            && filemtime($source) <= filemtime($targetFile) +        ) { +            //target is up to date +            return; +        } +        //work around a bug in php by replacing /./ with / +        $targetDir = str_replace('/./', '/', dirname($targetFile)); +        if (!is_dir($targetDir)) { +            $this->log("Creating directory '$targetDir'", Project::MSG_VERBOSE); +            mkdir($targetDir, $this->mode, true); +        } + +        $cmd = $tool +            . ' --exit-status=2' +            . ' ' . $this->toolParam +            . ' ' . escapeshellarg($source) +            . ' ' . escapeshellarg($targetFile) +            . ' 2>&1'; + +        $this->log('command: ' . $cmd, Project::MSG_VERBOSE); +        exec($cmd, $arOutput, $retval); +        if ($retval != 0) { +            $this->log(implode("\n", $arOutput), Project::MSG_INFO); +            throw new BuildException('Rendering rST failed'); +        } +        $this->log(implode("\n", $arOutput), Project::MSG_DEBUG); +    } + + + +    /** +     * Finds the rst2* binary path +     * +     * @param string $format Output format +     * +     * @return string Full path to rst2$format +     * +     * @throws BuildException When the tool cannot be found +     */ +    protected function getToolPath($format) +    { +        if ($this->toolPath !== null) { +            return $this->toolPath; +        } + +        $tool = 'rst2' . $format; +        $path = System::which($tool); +        if (!$path) { +            throw new BuildException( +                sprintf('"%s" not found. Install python-docutils.', $tool) +            ); +        } + +        return $path; +    } + + + +    /** +     * Determines and returns the target file name from the +     * input file and the configured destination name. +     * +     * @param string $file        Input file +     * @param string $destination Destination file or directory name, +     *                            may be null +     * +     * @return string Target file name +     * +     * @uses $format +     * @uses $targetExt +     */ +    public function getTargetFile($file, $destination = null) +    { +        if ($destination != '' +            && substr($destination, -1) !== '/' +            && substr($destination, -1) !== '\\' +        ) { +            return $destination; +        } + +        if (strtolower(substr($file, -4)) == '.rst') { +            $file = substr($file, 0, -4); +        } + +        return $destination . $file . '.'  . self::$targetExt[$this->format]; +    } + + + +    /** +     * The setter for the attribute "file" +     * +     * @param string $file Path of file to render +     * +     * @return void +     */ +    public function setFile($file) +    { +        $this->file = $file; +    } + + + +    /** +     * The setter for the attribute "format" +     * +     * @param string $format Output format +     * +     * @return void +     * +     * @throws BuildException When the format is not supported +     */ +    public function setFormat($format) +    { +        if (!in_array($format, self::$supportedFormats)) { +            throw new BuildException( +                sprintf( +                    'Invalid output format "%s", allowed are: %s', +                    $format, +                    implode(', ', self::$supportedFormats) +                ) +            ); +        } +        $this->format = $format; +    } + + + +    /** +     * The setter for the attribute "destination" +     * +     * @param string $destination Output file or directory. When it ends +     *                            with a slash, it is taken as directory. +     * +     * @return void +     */ +    public function setDestination($destination) +    { +        $this->destination = $destination; +    } + +    /** +     * The setter for the attribute "toolparam" +     * +     * @param string $param Additional rst2* tool parameters +     * +     * @return void +     */ +    public function setToolparam($param) +    { +        $this->toolParam = $param; +    } + +    /** +     * The setter for the attribute "toolpath" +     * +     * @param string $param Full path to tool path, i.e. /usr/local/bin/rst2html +     * +     * @return void +     * +     * @throws BuildException When the tool does not exist or is not executable +     */ +    public function setToolpath($path) +    { +        if (!file_exists($path)) { +            $fullpath = System::which($path); +            if ($fullpath === false) { +                throw new BuildException( +                    'Tool does not exist. Path: ' . $path +                ); +            } +            $path = $fullpath; +        } +        if (!is_executable($path)) { +            throw new BuildException( +                'Tool not executable. Path: ' . $path +            ); +        } +        $this->toolPath = $path; +    } + +    /** +     * The setter for the attribute "uptodate" +     * +     * @param string $uptodate True/false +     * +     * @return void +     */ +    public function setUptodate($uptodate) +    { +        $this->uptodate = (boolean)$uptodate; +    } + + + +    /** +     * Add a set of files to be rendered. +     * +     * @param FileSet $fileset Set of rst files to render +     * +     * @return void +     */ +    public function addFileset(FileSet $fileset) +    { +        $this->filesets[] = $fileset; +    } + + + +    /** +     * Nested creator, creates one Mapper for this task +     * +     * @return Mapper The created Mapper type object +     * +     * @throws BuildException +     */ +    public function createMapper() +    { +        if ($this->mapperElement !== null) { +            throw new BuildException( +                'Cannot define more than one mapper', $this->location +            ); +        } +        $this->mapperElement = new Mapper($this->project); +        return $this->mapperElement; +    } + + + +    /** +     * Creates a filterchain, stores and returns it +     * +     * @return FilterChain The created filterchain object +     */ +    public function createFilterChain() +    { +        $num = array_push($this->filterChains, new FilterChain($this->project)); +        return $this->filterChains[$num-1]; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php index 654d65dd..32fbc212 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestCountResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: ae09aa1a433f4de854fa7c27903e7eb0957bc90b $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,29 +24,28 @@ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php';  /**   * Dummy result formatter used to count SimpleTest results   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestCountResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: ae09aa1a433f4de854fa7c27903e7eb0957bc90b $   * @package phing.tasks.ext.simpletest   * @since 2.2.0   */  class SimpleTestCountResultFormatter extends SimpleTestResultFormatter  { -	const SUCCESS = 0; -	const FAILURES = 1; -	const ERRORS = 2; -	 -	function getRetCode() -	{ -		if ($this->getExceptionCount() != 0) -		{ -			return self::ERRORS; -		} -		else if ($this->getFailCount() != 0) -		{ -			return self::FAILURES; -		} -		 -		return self::SUCCESS; -	}	 +    const SUCCESS = 0; +    const FAILURES = 1; +    const ERRORS = 2; +     +    function getRetCode() +    { +        if ($this->getExceptionCount() != 0) +        { +            return self::ERRORS; +        } +        else if ($this->getFailCount() != 0) +        { +            return self::FAILURES; +        } +         +        return self::SUCCESS; +    }     } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php new file mode 100755 index 00000000..de78ab24 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php @@ -0,0 +1,119 @@ +<?php +/** + * $Id: d7e7e397e81588c3eafcb9e758666fec0fa166f5 $ + * + * 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/ext/simpletest/SimpleTestResultFormatter.php'; + +/** + * Prints plain text output of the test to a specified Writer. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: d7e7e397e81588c3eafcb9e758666fec0fa166f5 $ + * @package phing.tasks.ext.simpletest + * @since 2.2.0 + */ +class SimpleTestDebugResultFormatter extends SimpleTestResultFormatter +{ +    protected $current_case = ""; +    protected $current_test = ""; +    private $failingTests = array(); + +    function printFailingTests()  { +        foreach ($this->failingTests as $test) { +            $this->out->write($test . "\n"); +        } +    } + +    function paintCaseStart($test_name) +    { +        parent::paintCaseStart($test_name); +        $this->paint( "Testsuite: $test_name\n"); +    $this->current_case = $test_name; +    } + +  function paintMethodStart($test_name) +    { +    parent::paintMethodStart($test_name); +    $this->current_test = $test_name; +    //$msg = "{$this->current_case} :: $test_name\n"; +    $msg = "    TestCase: $test_name"; +    $this->paint($msg); +  } + +  function paint($msg) { +    if ($this->out == null ) { +      print $msg; +    } else { +      $this->out->write($msg); +    } +  } + +  function paintMethodEnd($test_name) { +    parent::paintMethodEnd($test_name); +    $this->paint("\n"); +  } + +  function paintCaseEnd($test_name) +  { +    parent::paintCaseEnd($test_name); +    $this->current_case = ""; +    /* Only count suites where more than one test was run */ + +    if ($this->getRunCount() && false) +    { +      $sb = ""; +      $sb.= "Tests run: " . $this->getRunCount(); +      $sb.= ", Failures: " . $this->getFailureCount(); +      $sb.= ", Errors: " . $this->getErrorCount(); +      $sb.= ", Time elapsed: " . $this->getElapsedTime(); +      $sb.= " sec\n"; +      $this->paint($sb); +    } + +  } + +  function paintError($message) +  { +    parent::paintError($message); +    $this->formatError("ERROR", $message); +    $this->failingTests[] = $this->current_case . "->" . $this->current_test; +  } + +  function paintFail($message) +  { +    parent::paintFail($message); +    $this->formatError("FAILED", $message); +    $this->failingTests[] = $this->current_case . "->" . $this->current_test; +  } +  function paintException($message) +  { +    parent::paintException($message); +    $this->failingTests[] = $this->current_case . "->" . $this->current_test; +    $this->formatError("Exception", $message); +  } + + + +  private function formatError($type, $message) +  { +    $this->paint("ERROR: $type: $message"); +  } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php index 768a041f..5ae9ba23 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestFormatterElement.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: 2441f1b83b9f9d1aeb2a4afd7e049c840d70bbd9 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,108 +19,50 @@   * <http://phing.info>.   */ -require_once 'phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php'; -require_once 'phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php'; -require_once 'phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php'; +require_once 'phing/tasks/ext/phpunit/FormatterElement.php';  /**   * Child class of "FormatterElement", overrides setType to provide other   * formatter classes for SimpleTest   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestFormatterElement.php 58 2006-04-28 14:41:04Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 2441f1b83b9f9d1aeb2a4afd7e049c840d70bbd9 $   * @package phing.tasks.ext.simpletest   * @since 2.2.0   */ -class SimpleTestFormatterElement +class SimpleTestFormatterElement extends FormatterElement  { -	protected $formatter = NULL; +    function setType($type) +    { +        $this->type = $type; -	protected $type = ""; - -	protected $useFile = true; - -	protected $toDir = "."; - -	protected $outfile = ""; - -	function setType($type) -	{ -		$this->type = $type; - -		if ($this->type == "xml") -		{ -			//$destFile = new PhingFile($this->toDir, 'testsuites.xml'); -			$this->formatter = new SimpleTestXmlResultFormatter(); -		} -		else -		if ($this->type == "plain") -		{ -			$this->formatter = new SimpleTestPlainResultFormatter(); -		} -		else -		if ($this->type == "summary") -		{ -			$this->formatter = new SimpleTestSummaryResultFormatter(); -		} -		else -		{ -			throw new BuildException("Formatter '" . $this->type . "' not implemented"); -		} -	} - -	function setClassName($className) -	{ -		$classNameNoDot = Phing::import($className); - -		$this->formatter = new $classNameNoDot(); -	} - -	function setUseFile($useFile) -	{ -		$this->useFile = $useFile; -	} - -	function getUseFile() -	{ -		return $this->useFile; -	} - -	function setToDir($toDir) -	{ -		$this->toDir = $toDir; -	} - -	function getToDir() -	{ -		return $this->toDir; -	} - -	function setOutfile($outfile) -	{ -		$this->outfile = $outfile; -	} - -	function getOutfile() -	{ -		if ($this->outfile) -		{ -			return $this->outfile; -		} -		else -		{ -			return $this->formatter->getPreferredOutfile() . $this->getExtension(); -		} -	} - -	function getExtension() -	{ -		return $this->formatter->getExtension(); -	} - -	function getFormatter() -	{ -		return $this->formatter; -	} +        if ($this->type == "xml") +        { +            require_once 'phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php'; +            $destFile = new PhingFile($this->toDir, 'testsuites.xml'); +            $this->formatter = new SimpleTestXmlResultFormatter(); +        } +        else +        if ($this->type == "plain") +        { +            require_once 'phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php'; +            $this->formatter = new SimpleTestPlainResultFormatter(); +        } +        else +        if ($this->type == "summary") +        { +            require_once 'phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php'; +            $this->formatter = new SimpleTestSummaryResultFormatter(); +        } +        else +        if ($this->type == "debug") +        { +            require_once 'phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php'; +            $this->formatter = new SimpleTestDebugResultFormatter(); +        } +        else +        { +            throw new BuildException("Formatter '" . $this->type . "' not implemented"); +        } +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php index 9d570486..cfba9533 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c0fa060b8f439f7d0013a0ec016ede4c5a76b42d $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,72 +24,72 @@ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php';  /**   * Prints plain text output of the test to a specified Writer.   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: c0fa060b8f439f7d0013a0ec016ede4c5a76b42d $   * @package phing.tasks.ext.simpletest   * @since 2.2.0   */  class SimpleTestPlainResultFormatter extends SimpleTestResultFormatter  { -	private $inner = ""; +    private $inner = ""; +     +    function getExtension() +    { +        return ".txt"; +    } +     +    function getPreferredOutfile() +    { +        return "testresults"; +    } -	function getExtension() -	{ -		return ".txt"; -	} +    function paintCaseStart($test_name) +    { +        parent::paintCaseStart($test_name); +         +        $this->inner = ""; +    } +     +    function paintCaseEnd($test_name) +    { +        parent::paintCaseEnd($test_name); +         +    $sb = ""; +        /* Only count suites where more than one test was run */ +        if ($this->getRunCount()) +        { +            $sb.= "Testsuite: $test_name\n"; +            $sb.= "Tests run: " . $this->getRunCount(); +            $sb.= ", Failures: " . $this->getFailureCount(); +            $sb.= ", Errors: " . $this->getErrorCount(); +            $sb.= ", Time elapsed: " . $this->getElapsedTime(); +            $sb.= " sec\n"; -	function getPreferredOutfile() -	{ -		return "testresults"; -	} +            if ($this->out != NULL) +            { +                $this->out->write($sb); +                $this->out->write($this->inner); +            } +        } +    } -	function paintCaseStart($test_name) -	{ -		parent::paintCaseStart($test_name); +    function paintError($message) +    { +        parent::paintError($message); +         +        $this->formatError("ERROR", $message); +    } -		$this->inner = ""; -	} +    function paintFail($message) +    { +        parent::paintFail($message); +         +        $this->formatError("FAILED", $message); +    } -	function paintCaseEnd($test_name) -	{ -		parent::paintCaseEnd($test_name); - -		/* Only count suites where more than one test was run */ -		if ($this->getRunCount()) -		{ -			$sb = "Testsuite: $test_name\n"; -			$sb.= "Tests run: " . $this->getRunCount(); -			$sb.= ", Failures: " . $this->getFailureCount(); -			$sb.= ", Errors: " . $this->getErrorCount(); -			$sb.= ", Time elapsed: " . $this->getElapsedTime(); -			$sb.= " sec\n"; - -			if ($this->out != NULL) -			{ -				$this->out->write($sb); -				$this->out->write($this->inner); -			} -		} -	} - -	function paintError($message) -	{ -		parent::paintError($message); - -		$this->formatError("ERROR", $message); -	} - -	function paintFail($message) -	{ -		parent::paintFail($message); - -		$this->formatError("FAILED", $message); -	} - -	private function formatError($type, $message) -	{ -		$this->inner.= $this->getTestName() . " " . $type . "\n"; -		$this->inner.= $message . "\n"; -	} +    private function formatError($type, $message) +    { +        $this->inner.= $this->getTestName() . " " . $type . "\n"; +        $this->inner.= $message . "\n";  +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php index 35077210..8efcbb63 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: b9fbde1e1a21cccbcf6c3bdc29765cf0cf681e31 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,144 +19,143 @@   * <http://phing.info>.   */ -//require_once 'simpletest/scorer.php'; +require_once 'simpletest/scorer.php';  require_once 'phing/system/io/Writer.php';  /**   * This abstract class describes classes that format the results of a SimpleTest testrun.   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ - * @package phing.tasks.ext.phpunit2 + * @author Michiel Rook <mrook@php.net> + * @version $Id: b9fbde1e1a21cccbcf6c3bdc29765cf0cf681e31 $ + * @package phing.tasks.ext.simpletest   * @since 2.2.0   */  abstract class SimpleTestResultFormatter extends SimpleReporter  { -	protected $out = NULL; +    protected $out = NULL; +     +    protected $project = NULL; +     +    private $timer = NULL; -	protected $project = NULL; +    private $runCount = 0; +     +    private $failureCount = 0; +     +    private $errorCount = 0;     -	private $timer = NULL; +    private $currentTest = ""; +     +    /** +     * Sets the writer the formatter is supposed to write its results to. +     */ +    function setOutput(Writer $out) +    { +        $this->out = $out;   +    } -	private $runCount = 0; +    /** +     * Returns the extension used for this formatter +     * +     * @return string the extension +     */ +    function getExtension() +    { +        return ""; +    } -	private $failureCount = 0; +    /** +     * Sets the project +     * +     * @param Project the project +     */ +    function setProject(Project $project) +    { +        $this->project = $project; +    } +     +    function getPreferredOutfile() +    { +        return ""; +    } +     +    function paintMethodStart($test_name) +    { +        parent::paintMethodStart($test_name); +         +        $this->currentTest = $test_name; +    } +     +    function paintMethodEnd($test_name) +    { +        parent::paintMethodEnd($test_name); +         +        $this->runCount++; +    } +     +    function paintCaseStart($test_name) +    { +        parent::paintCaseStart($test_name); +         +        $this->runCount = 0; +        $this->failureCount = 0; +        $this->errorCount = 0; +         +        $this->timer = new Timer(); +        $this->timer->start(); +    } +         +    function paintCaseEnd($test_name) +    { +        parent::paintCaseEnd($test_name); +         +        $this->timer->stop(); +    } -	private $errorCount = 0; +    function paintError($message) +    { +        parent::paintError($message); +         +        $this->errorCount++; +    } -	private $currentTest = ""; +    function paintFail($message) +    { +        parent::paintFail($message); +         +        $this->failureCount++; +    } -	/** -	 * Sets the writer the formatter is supposed to write its results to. -   	 */ -	function setOutput(Writer $out) -	{ -		$this->out = $out; -	} - -	/** -	 * Returns the extension used for this formatter -	 * -	 * @return string the extension -	 */ -	function getExtension() -	{ -		return ""; -	} - -	/** -	 * Sets the project -	 * -	 * @param Project the project -	 */ -	function setProject(Project $project) -	{ -		$this->project = $project; -	} - -	function getPreferredOutfile() -	{ -		return ""; -	} - -	function paintMethodStart($test_name) -	{ -		parent::paintMethodStart($test_name); - -		$this->currentTest = $test_name; -	} - -	function paintMethodEnd($test_name) -	{ -		parent::paintMethodEnd($test_name); - -		$this->runCount++; -	} - -	function paintCaseStart($test_name) -	{ -		parent::paintCaseStart($test_name); - -		$this->runCount = 0; -		$this->failureCount = 0; -		$this->errorCount = 0; - -		$this->timer = new Timer(); -		$this->timer->start(); -	} - -	function paintCaseEnd($test_name) -	{ -		parent::paintCaseEnd($test_name); - -		$this->timer->stop(); -	} - -	function paintError($message) -	{ -		parent::paintError($message); - -		$this->errorCount++; -	} - -	function paintFail($message) -	{ -		parent::paintFail($message); - -		$this->failureCount++; -	} - -	function getRunCount() -	{ -		return $this->runCount; -	} - -	function getFailureCount() -	{ -		return $this->failureCount; -	} - -	function getErrorCount() -	{ -		return $this->errorCount; -	} - -	function getTestName() -	{ -		return $this->currentTest; -	} - -	function getElapsedTime() -	{ -		if ($this->timer) -		{ -			return $this->timer->getElapsedTime(); -		} -		else -		{ -			return 0; -		} -	} +    function getRunCount() +    { +        return $this->runCount; +    } +     +    function getFailureCount() +    { +        return $this->failureCount; +    } +     +    function getErrorCount() +    { +        return $this->errorCount; +    } +     +    function getTestName() +    { +        return $this->currentTest; +    } +     +    function getElapsedTime() +    { +        if ($this->timer) +        { +            return $this->timer->getElapsedTime(); +        } +        else +        { +            return 0; +        } +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php index a2fafb0a..e0a78f11 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestSummaryResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: cd15496bfbce39bfd20fe17d52f9348848df0706 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,31 +24,30 @@ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php';  /**   * Prints short summary output of the test to Phing's logging system.   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestSummaryResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: cd15496bfbce39bfd20fe17d52f9348848df0706 $   * @package phing.tasks.ext.simpletest   * @since 2.2.0   */  class SimpleTestSummaryResultFormatter extends SimpleTestResultFormatter  { -	function paintCaseEnd($test_name) -	{ -		parent::paintCaseEnd($test_name); +    function paintCaseEnd($test_name) +    { +        parent::paintCaseEnd($test_name); +         +        /* Only count suites where more than one test was run */ +        if ($this->getRunCount()) +        { +            $sb.= "Tests run: " . $this->getRunCount(); +            $sb.= ", Failures: " . $this->getFailureCount(); +            $sb.= ", Errors: " . $this->getErrorCount(); +            $sb.= ", Time elapsed: " . $this->getElapsedTime(); +            $sb.= " sec\n"; -		/* Only count suites where more than one test was run */ -		if ($this->getRunCount()) -		{ -			$sb= "Tests run: " . $this->getRunCount(); -			$sb.= ", Failures: " . $this->getFailureCount(); -			$sb.= ", Errors: " . $this->getErrorCount(); -			$sb.= ", Time elapsed: " . $this->getElapsedTime(); -			$sb.= " sec\n"; - -			if ($this->out != NULL) -			{ -				$this->out->write($sb); -			} -		} -	} +            if ($this->out != NULL) +            { +                $this->out->write($sb); +            } +        } +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php index e32c31c6..8082e1ee 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestTask.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: d53b946f773798618069fe162d47ac5f6643662a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,208 +27,238 @@ require_once 'phing/util/LogWriter.php';  /**   * Runs SimpleTest tests.   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestTask.php 58 2006-04-28 14:41:04Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: d53b946f773798618069fe162d47ac5f6643662a $   * @package phing.tasks.ext.simpletest   * @since 2.2.0   */  class SimpleTestTask extends Task  { -	private $formatters = array(); -	private $haltonerror = false; -	private $haltonfailure = false; -	private $failureproperty; -	private $errorproperty; -	private $printsummary = false; -	private $testfailed = false; -	private $filesets=array(); +    private $formatters = array(); +    private $haltonerror = false; +    private $haltonfailure = false; +    private $failureproperty; +    private $errorproperty; +    private $printsummary = false; +    private $testfailed = false; +    private $debug = false; -	/** -	 * Initialize Task. - 	 * This method includes any necessary SimpleTest libraries and triggers -	 * appropriate error if they cannot be found.  This is not done in header -	 * because we may want this class to be loaded w/o triggering an error. -	 */ -	function init() { +    /** +     * Initialize Task. +     * This method includes any necessary SimpleTest libraries and triggers +     * appropriate error if they cannot be found.  This is not done in header +     * because we may want this class to be loaded w/o triggering an error. +     */ +    function init() { +        @include_once 'simpletest/scorer.php'; +         +        if (!class_exists('SimpleReporter')) { +            throw new BuildException("SimpleTestTask depends on SimpleTest package being installed.", $this->getLocation()); +        } +         +        require_once 'simpletest/reporter.php'; +        require_once 'simpletest/xml.php'; +        require_once 'simpletest/test_case.php'; +        require_once 'phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php'; +        require_once 'phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php'; +        require_once 'phing/tasks/ext/simpletest/SimpleTestFormatterElement.php'; +    } +     +    function setFailureproperty($value) +    { +        $this->failureproperty = $value; +    } +     +    function setErrorproperty($value) +    { +        $this->errorproperty = $value; +    } +     +    function setHaltonerror($value) +    { +        $this->haltonerror = $value; +    } -		if (!class_exists('SimpleReporter')) { -			throw new BuildException("SimpleTestTask depends on SimpleTest package being installed.", $this->getLocation()); -		} -		require_once 'phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php'; -		require_once 'phing/tasks/ext/simpletest/SimpleTestFormatterElement.php'; -	} +    function setHaltonfailure($value) +    { +        $this->haltonfailure = $value; +    } -	function setFailureproperty($value) -	{ -		$this->failureproperty = $value; -	} +    function setPrintsummary($printsummary) +    { +        $this->printsummary = $printsummary; +    } -	function setErrorproperty($value) -	{ -		$this->errorproperty = $value; -	} +    public function setDebug($debug) +    { +        $this->debug = $debug; +    } -	function setHaltonerror($value) -	{ -		$this->haltonerror = $value; -	} +    public function getDebug() +    { +        return $this->debug; +    }    +     +    /** +     * Add a new formatter to all tests of this task. +     * +     * @param SimpleTestFormatterElement formatter element +     */ +    function addFormatter(SimpleTestFormatterElement $fe) +    { +        $this->formatters[] = $fe; +    } -	function setHaltonfailure($value) -	{ -		$this->haltonfailure = $value; -	} +    /** +     * Add a new fileset containing the XML results to aggregate +     * +     * @param FileSet the new fileset containing XML results. +     */ +    function addFileSet(FileSet $fileset) +    { +        $this->filesets[] = $fileset; +    } -	function setPrintsummary($printsummary) -	{ -		$this->printsummary = $printsummary; -	} +    /** +     * Iterate over all filesets and return the filename of all files +     * that end with .php. +     * +     * @return array an array of filenames +     */ +    private function getFilenames() +    { +        $filenames = array(); -	/** -	 * Add a new formatter to all tests of this task. -	 * -	 * @param SimpleTestFormatterElement formatter element -	 */ -	function addFormatter(SimpleTestFormatterElement $fe) -	{ -		$this->formatters[] = $fe; -	} +        foreach ($this->filesets as $fileset) +        { +            $ds = $fileset->getDirectoryScanner($this->project); +            $ds->scan(); -	/** -	 * Add a new fileset containing the XML results to aggregate -	 * -	 * @param FileSet the new fileset containing XML results. -	 */ -	function addFileSet(FileSet $fileset) -	{ -		$this->filesets[] = $fileset; -	} +            $files = $ds->getIncludedFiles(); -	/** -	 * Iterate over all filesets and return the filename of all files -	 * that end with .php. -	 * -	 * @return array an array of filenames -	 */ -	private function getFilenames() -	{ -		$filenames = array(); +            foreach ($files as $file) +            { +                if (strstr($file, ".php")) +                { +                    $filenames[] = $ds->getBaseDir() . "/" . $file; +                } +            } +        } -		foreach ($this->filesets as $fileset) -		{ -			$ds = $fileset->getDirectoryScanner($this->project); -			$ds->scan(); +        return $filenames; +    } -			$files = $ds->getIncludedFiles(); +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $suite= new TestSuite(); +         +        $filenames = $this->getFilenames(); +         +        foreach ($filenames as $testfile) +        { +            $suite->addFile($testfile); +        } +         +        if ($this->debug) +        { +            $fe = new SimpleTestFormatterElement(); +            $fe->setType('debug'); +            $fe->setUseFile(false); +            $this->formatters[] = $fe; +        } +         +        if ($this->printsummary) +        { +            $fe = new SimpleTestFormatterElement(); +            $fe->setType('summary'); +            $fe->setUseFile(false); +            $this->formatters[] = $fe; +        } +         +        foreach ($this->formatters as $fe) +        { +            $formatter = $fe->getFormatter(); +            $formatter->setProject($this->getProject()); -			foreach ($files as $file) -			{ -				if (strstr($file, ".php")) -				{ -					$filenames[] = $ds->getBaseDir() . "/" . $file; -				} -			} -		} +            if ($fe->getUseFile()) +            { +                $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); +                 +                $writer = new FileWriter($destFile->getAbsolutePath()); -		return $filenames; -	} +                $formatter->setOutput($writer); +            } +            else +            { +                $formatter->setOutput($this->getDefaultOutput()); +            } +        } +         +        $this->execute($suite); +         +        if ($this->testfailed && $this->formatters[0]->getFormatter() instanceof SimpleTestDebugResultFormatter ) +        { +            $this->getDefaultOutput()->write("Failed tests: "); +            $this->formatters[0]->getFormatter()->printFailingTests(); +        } +         +        if ($this->testfailed) +        { +            throw new BuildException("One or more tests failed"); +        } +    } +     +    private function execute($suite) +    { +        $counter = new SimpleTestCountResultFormatter(); +        $reporter = new MultipleReporter(); +        $reporter->attachReporter($counter); +         +        foreach ($this->formatters as $fe) +        { +            // SimpleTest 1.0.1 workaround +            $formatterList[] = $fe->getFormatter(); +             +            $reporter->attachReporter(end($formatterList)); +        } +         +        $suite->run($reporter); +         +        $retcode = $counter->getRetCode(); +         +        if ($retcode == SimpleTestCountResultFormatter::ERRORS) +        { +            if ($this->errorproperty) +            { +                $this->project->setNewProperty($this->errorproperty, true); +            } +             +            if ($this->haltonerror) +            { +                $this->testfailed = true; +            } +        } +        elseif ($retcode == SimpleTestCountResultFormatter::FAILURES) +        { +            if ($this->failureproperty) +            { +                $this->project->setNewProperty($this->failureproperty, true); +            } +             +            if ($this->haltonfailure) +            { +                $this->testfailed = true; +            } +        } +    } -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$group = new GroupTest(); - -		$filenames = $this->getFilenames(); - -		foreach ($filenames as $testfile) -		{ -			$group->addTestFile($testfile); -		} - -		if ($this->printsummary) -		{ -			$fe = new SimpleTestFormatterElement(); -			$fe->setType('summary'); -			$fe->setUseFile(false); -			$this->formatters[] = $fe; -		} - -		foreach ($this->formatters as $fe) -		{ -			$formatter = $fe->getFormatter(); -			$formatter->setProject($this->getProject()); - -			if ($fe->getUseFile()) -			{ -				$destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); - -				$writer = new FileWriter($destFile->getAbsolutePath()); - -				$formatter->setOutput($writer); -			} -			else -			{ -				$formatter->setOutput($this->getDefaultOutput()); -			} -		} - -		$this->execute($group); - -		if ($this->testfailed) -		{ -			throw new BuildException("One or more tests failed"); -		} -	} - -	private function execute($suite) -	{ -		$counter = new SimpleTestCountResultFormatter(); -		$reporter = new MultipleReporter(); -		$reporter->attachReporter($counter); - -		foreach ($this->formatters as $fe) -		{ -			$formatter = $fe->getFormatter(); - -			$reporter->attachReporter($formatter); -		} - -		$suite->run($reporter); - -		$retcode = $counter->getRetCode(); - -		if ($retcode == SimpleTestCountResultFormatter::ERRORS) -		{ -		    if ($this->errorproperty) -		    { -				$this->project->setNewProperty($this->errorproperty, true); -			} - -			if ($this->haltonerror) -			{ -			    $this->testfailed = true; -			} -		} -		elseif ($retcode == SimpleTestCountResultFormatter::FAILURES) -		{ -			if ($this->failureproperty) -			{ -				$this->project->setNewProperty($this->failureproperty, true); -			} - -			if ($this->haltonfailure) -			{ -				$this->testfailed = true; -			} -		} -	} - -	private function getDefaultOutput() -	{ -		return new LogWriter($this); -	} +    private function getDefaultOutput() +    { +        return new LogWriter($this); +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php index 66c4ccd8..5ffa668b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 03b9f976a961a2688d51c9429087a98c31326f42 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,135 +20,159 @@   */  require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php'; +require_once 'simpletest/xml.php';  /**   * Prints plain text output of the test to a specified Writer.   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 03b9f976a961a2688d51c9429087a98c31326f42 $   * @package phing.tasks.ext.simpletest   * @since 2.2.0   */  class SimpleTestXmlResultFormatter extends SimpleTestResultFormatter  { -	private $results=array(); -	private $currentSuite; -	private $currentTest; -	private $methodCounts=0; -	private $methodTime=0; +    /** +     * @var XmlReporter +     */ +    private $logger = NULL; +     +    private $xmlData = ""; -	function paintFooter($test_name) -	{ -		if($test_name=='GroupTest') -			 $this->printXml($test_name); +    function __construct() +    { +        $this->logger = new XmlReporter(); +    } +     +    function getExtension() +    { +        return ".xml"; +    } +     +    function getPreferredOutfile() +    { +        return "testsuites"; +    } +     +    private function captureStart() +    { +        ob_start(); +    } +     +    private function captureStop() +    { +        $this->xmlData .= ob_get_contents(); +        ob_end_clean();      } -	protected function printXml($test_name) -	{ -		$suites = $this->printXmlSuites($this->results); -$content = <<<EOD -<?xml version="1.0" encoding="UTF-8"?> -<testsuites total="{$this->getRunCount()}" name="{$test_name}"> -$suites -</testsuites> -EOD; -		$this->out->write($content); -	} +    function paintGroupStart($test_name, $size) +    { +        parent::paintGroupStart($test_name, $size); +         +        $this->captureStart(); +        $this->logger->paintGroupStart($test_name, $size); +        $this->captureStop(); +    } +     +    function paintGroupEnd($test_name) +    { +        parent::paintGroupEnd($test_name); +         +        $this->captureStart(); +        $this->logger->paintGroupEnd($test_name); +        $this->captureStop(); -	protected function printXmlSuites($results) -	{ -		$contents = ''; -		foreach($results as $suiteName => $suite) -		{ -			$tests = $this->printXmlTests($suite['tests'],$suiteName); -$contents .= <<<EOD -<testsuite name="{$suiteName}" tests="{$suite['total']}" failures="{$suite['failures']}" errors="{$suite['errors']}" time="{$suite['time']}"> -		$tests -</testsuite> -EOD; -		} -		return $contents; -	} +        if (count($this->_test_stack) == 0) +        { +            if ($this->out) +            { +                $this->out->write($this->xmlData); +                $this->out->close(); +            } +        } +    } -	protected function printXmlTests($tests,$suiteName) -	{ -		$contents = ''; -		foreach($tests as $name => $result) -		{ -			if(count($result['results'])==0) -			{ -				$contents .= <<<EOD -<testcase name="{$name}" class="{$suiteName}" result="success" time="{$result['time']}"/> -EOD; -			} -			else -			{ -				$type = strtolower($result['results']['type']); -				$message = htmlspecialchars($result['results']['message']); -$contents .= <<<EOD -<testcase name="{$name}" class="{$suiteName}" result="{$type}" time="{$result['time']}"> -	<{$type}>$message</{$type}> -</testcase> -EOD; -			} -		} -		return $contents; -	} +    function paintCaseStart($test_name) +    { +        $this->captureStart(); +        $this->logger->paintCaseStart($test_name); +        $this->captureStop(); +    } +     +    function paintCaseEnd($test_name) +    { +        $this->captureStart(); +        $this->logger->paintCaseEnd($test_name); +        $this->captureStop(); +    } -	function paintCaseStart($test_name) -	{ -		parent::paintCaseStart($test_name); -		$this->results[$test_name] = array('tests'=>array()); -		$this->currentSuite=$test_name; -		$this->methodCounts=0; -	} +    function paintMethodStart($test_name) +    { +        $this->captureStart(); +        $this->logger->paintMethodStart($test_name); +        $this->captureStop(); +    } +     +    function paintMethodEnd($test_name) +    { +        $this->captureStart(); +        $this->logger->paintMethodEnd($test_name); +        $this->captureStop(); +    } -	function paintCaseEnd($test_name) -	{ -		parent::paintCaseEnd($test_name); -		$details = 	array( -			'total' => $this->methodCounts, -			'failures' => $this->getFailureCount(), -			'errors' => $this->getErrorCount(), -			'time' => $this->getElapsedTime()); +    function paintPass($message) +    { +        $this->captureStart(); +        $this->logger->paintPass($message); +        $this->captureStop(); +    } +     +    function paintError($message) +    { +        $this->captureStart(); +        $this->logger->paintError($message); +        $this->captureStop(); +    } -		$this->results[$test_name] = array_merge($this->results[$test_name],$details); -	} +    function paintFail($message) +    { +        $this->captureStart(); +        $this->logger->paintFail($message); +        $this->captureStop(); +    } -	function paintMethodStart($test_name) -	{ -		$this->currentTest=$test_name; -		parent::paintMethodStart($test_name); -		$this->results[$this->currentSuite]['tests'][$test_name]['results'] = array(); -		$this->methodCounts++; -		$this->methodTime = new Timer(); -		$this->methodTime->start(); -	} +    function paintException($exception) +    { +        $this->captureStart(); +        $this->logger->paintException($exception); +        $this->captureStop(); +    } -	function paintMethodEnd($test_name) -	{ -		parent::paintMethodEnd($test_name); -		$this->methodTime->stop(); -		$this->results[$this->currentSuite]['tests'][$test_name]['time'] = $this->methodTime->getElapsedTime(); -	} +    function paintSkip($message) +    { +        $this->captureStart(); +        $this->logger->paintSkip($message); +        $this->captureStop(); +    } -	function paintError($message) -	{ -		parent::paintError($message); -		$this->formatError("ERROR", $message); -	} +    function paintMessage($message) +    { +        $this->captureStart(); +        $this->logger->paintMessage($message); +        $this->captureStop(); +    } -	function paintFail($message) -	{ -		parent::paintFail($message); -		$this->formatError("FAILED", $message); -	} +    function paintFormattedMessage($message) +    { +        $this->captureStart(); +        $this->logger->paintFormattedMessage($message); +        $this->captureStop(); +    } -	private function formatError($type, $message) -	{ -		$result = array('type'=>$type, 'message' => $message); -		$this->results[$this->currentSuite]['tests'][$this->currentTest]['results'] = -			$result; -	} +    function paintSignal($type, $payload) +    { +        $this->captureStart(); +        $this->logger->paintSignal($type, $payload); +        $this->captureStop(); +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php index 55c695cf..ed9cb276 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: SvnBaseTask.php 38 2006-03-09 14:05:11Z mrook $ + *  $Id: b6c644f650a69cad32ced1d030685a7a7a46251c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,159 +22,326 @@  include_once 'phing/Task.php';  /** - *  Send a message by mail()  + * Base class for Subversion tasks   * - *  <mail to="user@example.org" subject="build complete">The build process is a success...</mail>  - *  - *  @author   Francois Harvey at SecuriWeb (http://www.securiweb.net) - *  @version  $Id: SvnBaseTask.php 38 2006-03-09 14:05:11Z mrook $ - *  @package  phing.tasks.ext + * @author Michiel Rook <mrook@php.net> + * @author Andrew Eddie <andrew.eddie@jamboworks.com>  + * @version $Id: b6c644f650a69cad32ced1d030685a7a7a46251c $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.2.0   */  abstract class SvnBaseTask extends Task  { -	private $workingCopy = ""; -	 -	private $repositoryUrl = ""; -	 -	private $svnPath = "/usr/bin/svn"; -	 -	private $svn = NULL; -	 -	private $mode = ""; -	 -	private $svnArgs = array(); +    private $workingCopy = ""; +     +    private $repositoryUrl = ""; +     +    private $svnPath = "/usr/bin/svn"; +     +    private $svn = NULL; +     +    private $mode = ""; +     +    private $svnArgs = array(); +     +    private $svnSwitches = array(); -	/** -	 * Initialize Task. - 	 * This method includes any necessary SVN libraries and triggers -	 * appropriate error if they cannot be found.  This is not done in header -	 * because we may want this class to be loaded w/o triggering an error. -	 */ -	function init() { -		include_once 'VersionControl/SVN.php'; -		if (!class_exists('VersionControl_SVN')) { -			throw new Exception("SvnLastRevisionTask depends on PEAR VersionControl_SVN package being installed."); -		} -	} +    private $toDir = ""; +     +    protected $fetchMode = VERSIONCONTROL_SVN_FETCHMODE_ASSOC; -	/** -	 * Sets the path to the workingcopy -	 */ -	function setWorkingCopy($workingCopy) -	{ -		$this->workingCopy = $workingCopy; -	} +    /** +     * Initialize Task. +     * This method includes any necessary SVN libraries and triggers +     * appropriate error if they cannot be found.  This is not done in header +     * because we may want this class to be loaded w/o triggering an error. +     */ +    function init() { +        include_once 'VersionControl/SVN.php'; +        if (!class_exists('VersionControl_SVN')) { +            throw new Exception("The SVN tasks depend on PEAR VersionControl_SVN package being installed."); +        } +    } -	/** -	 * Returns the path to the workingcopy -	 */ -	function getWorkingCopy() -	{ -		return $this->workingCopy; -	} +    /** +     * Sets the path to the workingcopy +     */ +    function setWorkingCopy($workingCopy) +    { +        $this->workingCopy = $workingCopy; +    } -	/** -	 * Sets the path/URI to the repository -	 */ -	function setRepositoryUrl($repositoryUrl) -	{ -		$this->repositoryUrl = $repositoryUrl; -	} +    /** +     * Returns the path to the workingcopy +     */ +    function getWorkingCopy() +    { +        return $this->workingCopy; +    } -	/** -	 * Returns the path/URI to the repository -	 */ -	function getRepositoryUrl() -	{ -		return $this->repositoryUrl; -	} +    /** +     * Sets the path/URI to the repository +     */ +    function setRepositoryUrl($repositoryUrl) +    { +        $this->repositoryUrl = $repositoryUrl; +    } -	/** -	 * Sets the path to the SVN executable -	 */ -	function setSvnPath($svnPath) -	{ -		$this->svnPath = $svnPath; -	} +    /** +     * Returns the path/URI to the repository +     */ +    function getRepositoryUrl() +    { +        return $this->repositoryUrl; +    } -	/** -	 * Returns the path to the SVN executable -	 */ -	function getSvnPath() -	{ -		return $this->svnPath; -	} -	 -	/** -	 * Creates a VersionControl_SVN class based on $mode -	 * -	 * @param string The SVN mode to use (info, export, checkout, ...) -	 * @throws BuildException -	 */ -	protected function setup($mode) -	{ -		$this->mode = $mode; -		 -		// Set up runtime options. Will be passed to all -		// subclasses. -		$options = array('fetchmode' => VERSIONCONTROL_SVN_FETCHMODE_ASSOC, 'svn_path' => $this->getSvnPath()); -		 -		// Pass array of subcommands we need to factory -		$this->svn = VersionControl_SVN::factory($mode, $options); +    /** +     * Sets the path to the SVN executable +     */ +    function setSvnPath($svnPath) +    { +        $this->svnPath = $svnPath; +    } + +    /** +     * Returns the path to the SVN executable +     */ +    function getSvnPath() +    { +        return $this->svnPath; +    } + +    // +    // Args +    // + +    /** +     * Sets the path to export/checkout to +     */ +    function setToDir($toDir) +    { +        $this->toDir = $toDir; +    } + +    /** +     * Returns the path to export/checkout to +     */ +    function getToDir() +    { +        return $this->toDir; +    } + +    // +    // Switches +    // -		if (!empty($this->repositoryUrl)) -		{ -			$this->svnArgs = array($this->repositoryUrl); -		} -		else -		if (!empty($this->workingCopy)) -		{ -			if (is_dir($this->workingCopy)) -			{ -				if (in_array(".svn", scandir($this->workingCopy))) -				{ -					$this->svnArgs = array($this->workingCopy); -				} -				else -				{ -					throw new BuildException("'".$this->workingCopy."' doesn't seem to be a working copy"); -				} -			} -			else -			{ -				throw new BuildException("'".$this->workingCopy."' is not a directory"); -			} -		} -	} -	 +    /** +     * Sets the force switch +     */ +    function setForce($value) +    { +        $this->svnSwitches['force'] = $value; +    } + +    /** +     * Returns the force switch +     */ +    function getForce() +    { +        return isset( $this->svnSwitches['force'] ) ? $this->svnSwitches['force'] : ''; +    } + +    /** +     * Sets the username of the user to export +     */ +    function setUsername($value) +    { +        $this->svnSwitches['username'] = $value; +    } + +    /** +     * Returns the username +     */ +    function getUsername() +    { +        return isset( $this->svnSwitches['username'] ) ? $this->svnSwitches['username'] : ''; +    } + +    /** +     * Sets the password of the user to export +     */ +    function setPassword($value) +    { +        $this->svnSwitches['password'] = $value; +    } + +    /** +     * Returns the password +     */ +    function getPassword() +    { +        return isset( $this->svnSwitches['password'] ) ? $this->svnSwitches['password'] : ''; +    } + +    /** +     * Sets the no-auth-cache switch +     */ +    function setNoCache($value) +    { +        $this->svnSwitches['no-auth-cache'] = $value; +    } + +    /** +     * Returns the no-auth-cache switch +     */ +    function getNoCache() +    { +        return isset( $this->svnSwitches['no-auth-cache'] ) ? $this->svnSwitches['no-auth-cache'] : ''; +    } +     +    /** +     * Sets the non-recursive switch +     */ +    function setRecursive($value) +    { +        $this->svnSwitches['non-recursive'] = is_bool($value) ? !$value : true; +    } +     +    /** +     * Returns the non-recursive switch +     */ +    function getRecursive() +    { +        return isset( $this->svnSwitches['non-recursive'] ) ? !$this->svnSwitches['non-recursive'] : true; +    } + +    /** +     * Sets the ignore-externals switch +     */ +    function setIgnoreExternals($value) +    { +        $this->svnSwitches['ignore-externals'] = $value; +    } +     +    /** +     * Returns the ignore-externals switch +     */ +    function getIgnoreExternals() +    { +        return isset( $this->svnSwitches['ignore-externals'] ) ? $this->svnSwitches['ignore-externals'] : ''; +    } +      	/** -	 * Executes the constructed VersionControl_SVN instance -	 * -	 * @param array Additional arguments to pass to SVN. -	 * @param array Switches to pass to SVN. -	 * @return string Output generated by SVN. -	 */ -	protected function run($args = array(), $switches = array()) -	{ -		$svnstack = PEAR_ErrorStack::singleton('VersionControl_SVN'); -		 -		$tempArgs = $this->svnArgs; -		 -		$tempArgs = array_merge($tempArgs, $args); -		 -		if ($output = $this->svn->run($tempArgs, $switches)) -		{ -			return $output; -		} -		else -		{ -			if (count($errs = $svnstack->getErrors())) -			{ -				$err = current($errs); +     * Sets the trust-server-cert switch +     */ +    public function setTrustServerCert($value) +    { +        $this->svnSwitches['trust-server-cert'] = $value; +    } + +    /** +     * Returns the trust-server-cert switch +     */ +    public function getTrustServerCert() +    { +        return isset($this->svnSwitches['trust-server-cert']) ? $this->svnSwitches['trust-server-cert'] : ''; +    } +     +    /** +     * Creates a VersionControl_SVN class based on $mode +     * +     * @param string The SVN mode to use (info, export, checkout, ...) +     * @throws BuildException +     */ +    protected function setup($mode) +    { +        $this->mode = $mode; +         +        // Set up runtime options. Will be passed to all +        // subclasses. +        $options = array('fetchmode' => $this->fetchMode, 'svn_path' => $this->getSvnPath()); +         +        // Pass array of subcommands we need to factory +        $this->svn = VersionControl_SVN::factory($mode, $options); +                 +        $this->svn->use_escapeshellcmd = false; -				throw new BuildException("Failed to run the 'svn " . $this->mode . "' command: " . $err['message']); -			} -		} -	} +        if (!empty($this->repositoryUrl)) +        { +            $this->svnArgs = array($this->repositoryUrl); +        } +        else +        if (!empty($this->workingCopy)) +        { +            if (is_dir($this->workingCopy)) +            { +                if (in_array(".svn", scandir($this->workingCopy))) +                { +                    $this->svnArgs = array($this->workingCopy); +                } +                else +                { +                    throw new BuildException("'".$this->workingCopy."' doesn't seem to be a working copy"); +                } +            } +            else +            if ($mode=='info' ) +            { +                if (is_file($this->workingCopy)) +                { +                    $this->svnArgs = array($this->workingCopy); +                } +                else +                { +                    throw new BuildException("'".$this->workingCopy."' is not a directory nor a file"); +                } +            } +            else +            { +                throw new BuildException("'".$this->workingCopy."' is not a directory"); +            } +        } +    } +     +    /** +     * Executes the constructed VersionControl_SVN instance +     * +     * @param array Additional arguments to pass to SVN. +     * @param array Switches to pass to SVN. +     * @return string Output generated by SVN. +     */ +    protected function run($args = array(), $switches = array()) +    { +        $svnstack = PEAR_ErrorStack::singleton('VersionControl_SVN'); +         +        $tempArgs = $this->svnArgs; +         +        $tempArgs = array_merge($tempArgs, $args); + +        $tempSwitches = $this->svnSwitches; +         +        $tempSwitches = array_merge($tempSwitches, $switches); + +        if ($output = $this->svn->run($tempArgs, $tempSwitches)) +        { +            return $output; +        } +        else +        { +            if (count($errs = $svnstack->getErrors())) +            { +                $err = current($errs); +                 +                $errorMessage = $err['message']; +                 +                if (isset($err['params']['errstr'])) { +                    $errorMessage = $err['params']['errstr']; +                } +                 +                throw new BuildException("Failed to run the 'svn " . $this->mode . "' command: " . $errorMessage); +            } +        } +    }  } -?>
\ No newline at end of file + diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCheckoutTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCheckoutTask.php new file mode 100644 index 00000000..76dc976a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCheckoutTask.php @@ -0,0 +1,67 @@ +<?php +/** + * $Id: f8844430c9e30d1c603452d8763fbd1114d80051 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Checks out a repository to a local directory + * + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @version $Id: f8844430c9e30d1c603452d8763fbd1114d80051 $ + * @package phing.tasks.ext.svn + * @since 2.3.0 + */ +class SvnCheckoutTask extends SvnBaseTask +{ +    /** +     * Which Revision to Export +     *  +     * @todo check if version_control_svn supports constants +     *  +     * @var string +     */ +    private $revision = 'HEAD'; + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('checkout'); + +        $this->log("Checking out SVN repository to '" . $this->getToDir() . "'". ($this->revision=='HEAD'?'':" (revision: {$this->revision})")); + +        // revision +        $switches = array( +            'r' => $this->revision, +        ); + +        $this->run(array($this->getToDir()), $switches); +    } + +    public function setRevision($revision) +    { +        $this->revision = $revision; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCommitTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCommitTask.php new file mode 100644 index 00000000..7eb1ce7a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCommitTask.php @@ -0,0 +1,113 @@ +<?php +/** + * $Id: 6fdb36b57778f5c0cd46110fd36c8c261ced0e86 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Commits changes in a local working copy to the repository + * + * @author Johan Persson <johanp@aditus.nu> + * @version $Id: 6fdb36b57778f5c0cd46110fd36c8c261ced0e86 $ + * @package phing.tasks.ext.svn + * @since 2.4.0 + */ +class SvnCommitTask extends SvnBaseTask +{ +       /** +        * Commit message +        */ +        private $message = ''; + +       /** +        * Property name where we store the revision number of the just +        * commited version. +        */ +        private $propertyName = "svn.committedrevision"; + +        /** +         * Sets the commit message +         */ +        function setMessage($message) +        { +                $this->message = $message; +        } + +        /** +         * Gets the commit message +         */ +        function getMessage() +        { +                 return $this->message; +        } + +        /** +         * Sets the name of the property to use for returned revision +         */ +        function setPropertyName($propertyName) +        { +                $this->propertyName = $propertyName; +        } + +        /** +         * Returns the name of the property to use for returned revision +         */ +        function getPropertyName() +        { +                return $this->propertyName; +        } + +        /** +         * The main entry point +         * +         * @throws BuildException +         */ +        function main() +        { +                if( trim($this->message) === '' ) +                { +                        throw new BuildException('SVN Commit message can not be empty.'); +                } + +                $this->setup('commit'); + +                $this->log("Commiting SVN working copy at '" . $this->getWorkingCopy() . "' with message '".$this->GetMessage()."'"); + +                $output = $this->run(array(), array('message' => $this->GetMessage() ) ); + +                if( preg_match('/[\s]*Committed revision[\s]+([\d]+)/', $output, $matches) ) +                { +                        $this->project->setProperty($this->getPropertyName(), $matches[1]); +                } +                else +                { +                        /** +                         * If no new revision was committed set revision to "empty". Remember that +                         * this is not necessarily an error. It could be that the specified working +                         * copy is identical to to the copy in the repository and in that case +                         * there will be no update and no new revision number. +                         */ +                        $this->project->setProperty($this->getPropertyName(), '' ); +                } + +        } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCopyTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCopyTask.php new file mode 100644 index 00000000..c1eb7089 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCopyTask.php @@ -0,0 +1,70 @@ +<?php +/** + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Copies a repository from the repository url to another + * + * @version $Id: 6f39598901c83ecaf8e7fcb9d4065f70b38324cb $ + * @package phing.tasks.ext.svn + * @since 2.3.0 + */ +class SvnCopyTask extends SvnBaseTask +{ +    private $message = ""; + +    /** +     * Sets the message +     */ +    function setMessage($message) +    { +        $this->message = $message; +    } + +    /** +     * Gets the message +     */ +    function getMessage() +    { +        return $this->message; +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('copy'); + +        $this->log("Copying SVN repository from '" . $this->getRepositoryUrl()  .  "' to '" . $this->getToDir() . "'"); +         +        $options = array(); +         +        if (strlen($this->getMessage()) > 0) { +            $options['message'] = $this->getMessage(); +        } + +        $this->run(array($this->getToDir()), $options); +    } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php index 7cb6c897..e0b2e78b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SvnExportTask.php 37 2006-03-09 14:04:22Z mrook $ + * $Id: ca2d150a53b870fe410f5434f4d500decc7cda73 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,45 +24,47 @@ require_once 'phing/tasks/ext/svn/SvnBaseTask.php';  /**   * Exports/checks out a repository to a local directory + * with authentication    * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SvnExportTask.php 37 2006-03-09 14:04:22Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @author Andrew Eddie <andrew.eddie@jamboworks.com>  + * @version $Id: ca2d150a53b870fe410f5434f4d500decc7cda73 $   * @package phing.tasks.ext.svn - * @see VersionControl_SVN - * @since 2.1.0 + * @since 2.2.0   */  class SvnExportTask extends SvnBaseTask  { -	private $toDir = ""; +    /** +     * Which Revision to Export +     *  +     * @todo check if version_control_svn supports constants +     *  +     * @var string +     */ +    private $revision = 'HEAD'; -	/** -	 * Sets the path to export/checkout to -	 */ -	function setToDir($toDir) -	{ -		$this->toDir = $toDir; -	} +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('export'); +         +        $this->log("Exporting SVN repository to '" . $this->getToDir() . "'"); -	/** -	 * Returns the path to export/checkout to -	 */ -	function getToDir() -	{ -		return $this->toDir; -	} +        $switches = array(); -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$this->setup('export'); -		 -		$this->log("Exporting SVN repository to '" . $this->toDir . "'"); -		 -		$this->run(array($this->toDir)); -	} +        if (!empty($this->revision)) { +            $switches['r'] = $this->revision; +        } + +        $this->run(array($this->getToDir()), $switches); +    } + +    public function setRevision($revision) +    { +        $this->revision = $revision; +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnInfoTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnInfoTask.php new file mode 100644 index 00000000..68111d74 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnInfoTask.php @@ -0,0 +1,112 @@ +<?php +/** + * $Id: 36ffb2ececed4c83c9ca7ad3674b3fa11074f2a5 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Parses the output of 'svn info --xml' and + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 36ffb2ececed4c83c9ca7ad3674b3fa11074f2a5 $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.4.9 + */ +class SvnInfoTask extends SvnBaseTask +{ +    private $propertyName = "svn.info"; +     +    private $element = 'url'; +    private $subElement = null; + +    /** +     * Sets the name of the property to use +     */ +    public function setPropertyName($propertyName) +    { +        $this->propertyName = $propertyName; +    } + +    /** +     * Returns the name of the property to use +     */ +    public function getPropertyName() +    { +        return $this->propertyName; +    } +     +    /** +     * Sets the name of the xml element to use +     */ +    public function setElement($element) +    { +        $this->element = $element; +    } +     +    /** +     * Returns the name of the xml element to use +     */ +    public function getElement() +    { +        return $this->element; +    } + +    /** +     * Sets the name of the xml sub element to use +     */ +    public function setSubElement($subElement) +    { +        $this->subElement = $subElement; +    } +     +    /** +     * Returns the name of the xml sub element to use +     */ +    public function getSubElement() +    { +        return $this->subElement; +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('info'); + +        $output = $this->run(array('--xml', '--incremental')); +             +        if ($xmlObj = @simplexml_load_string($output)) { +            $object = $xmlObj->{$this->element}; +             +            if (!empty($this->subElement)) { +                $object = $object->{$this->subElement}; +            } +                 +            $this->project->setProperty($this->getPropertyName(), (string) $object); +        } else { +            throw new BuildException("Failed to parse the output of 'svn info --xml'."); +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php index e45ac50c..7305c27b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php @@ -1,6 +1,6 @@  <?php  /** - * $Id: SvnLastRevisionTask.php 37 2006-03-09 14:04:22Z mrook $ + * $Id: 74d61db8c11978a2383f071b7ab7ed0afae6953c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,51 +25,96 @@ require_once 'phing/tasks/ext/svn/SvnBaseTask.php';  /**   * Stores the number of the last revision of a workingcopy in a property   * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SvnLastRevisionTask.php 37 2006-03-09 14:04:22Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 74d61db8c11978a2383f071b7ab7ed0afae6953c $   * @package phing.tasks.ext.svn   * @see VersionControl_SVN   * @since 2.1.0   */  class SvnLastRevisionTask extends SvnBaseTask  { -	private $propertyName = "svn.lastrevision"; +    private $propertyName = "svn.lastrevision"; +    private $forceCompatible = false; +    private $lastChanged = false; -	/** -	 * Sets the name of the property to use -	 */ -	function setPropertyName($propertyName) -	{ -		$this->propertyName = $propertyName; -	} +    /** +     * Sets the name of the property to use +     */ +    function setPropertyName($propertyName) +    { +        $this->propertyName = $propertyName; +    } -	/** -	 * Returns the name of the property to use -	 */ -	function getPropertyName() -	{ -		return $this->propertyName; -	} +    /** +     * Returns the name of the property to use +     */ +    function getPropertyName() +    { +        return $this->propertyName; +    } +     +    /** +     * Sets whether to force compatibility with older SVN versions (< 1.2) +     */ +    public function setForceCompatible($force) +    { +        $this->forceCompatible = (bool) $force; +    } +     +    /** +     * Sets whether to retrieve the last changed revision +     */ +    public function setLastChanged($lastChanged) +    { +        $this->lastChanged = (bool) $lastChanged; +    } -	/** -	 * The main entry point -	 * -	 * @throws BuildException -	 */ -	function main() -	{ -		$this->setup('info'); -		 -		$output = $this->run(); -		 -		if (preg_match('/Rev:[\s]+([\d]+)/', $output, $matches)) -		{ -			$this->project->setProperty($this->getPropertyName(), $matches[1]); -		} -		else -		{ -			throw new BuildException("Failed to parse the output of 'svn info'."); -		} -	} +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('info'); +         +        if ($this->forceCompatible) +        { +            $output = $this->run(); +             +            if ($this->lastChanged) { +                $found = preg_match('/Rev:[\s]+([\d]+)/', $output, $matches); +            } else { +                $found = preg_match('/Last Changed Rev:[\s]+([\d]+)/', $output, $matches); +            } + +            if ($found) +            { +                $this->project->setProperty($this->getPropertyName(), $matches[1]); +            } +            else +            { +                throw new BuildException("Failed to parse the output of 'svn info'."); +            }             +        } +        else +        { +            $output = $this->run(array('--xml')); +             +            if ($xmlObj = @simplexml_load_string($output)) +            { +                if ($this->lastChanged) { +                    $lastRevision = (int)$xmlObj->entry->commit['revision']; +                } else { +                    $lastRevision = (int)$xmlObj->entry['revision']; +                } +                 +                $this->project->setProperty($this->getPropertyName(), $lastRevision); +            } +            else +            { +                throw new BuildException("Failed to parse the output of 'svn info --xml'."); +            } +        } +    }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnListTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnListTask.php new file mode 100755 index 00000000..63d8445c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnListTask.php @@ -0,0 +1,128 @@ +<?php +/** + * $Id: 5dfcc23bc58efaad0eb11ef4964bcd7be0fb99e9 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Stores the output of a list command on a workingcopy or repositoryurl in a property. + * This stems from the SvnLastRevisionTask. + * + * @author Anton Stöckl <anton@stoeckl.de> + * @author Michiel Rook <mrook@php.net> (SvnLastRevisionTask) + * @version $Id: 5dfcc23bc58efaad0eb11ef4964bcd7be0fb99e9 $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.1.0 + */ +class SvnListTask extends SvnBaseTask +{ +    private $propertyName = "svn.list"; +    private $forceCompatible = true; +    private $limit = null; +    private $orderDescending = false; + +    /** +     * Sets the name of the property to use +     */ +    function setPropertyName($propertyName) +    { +        $this->propertyName = $propertyName; +    } + +    /** +     * Returns the name of the property to use +     */ +    function getPropertyName() +    { +        return $this->propertyName; +    } + +    /** +     * Sets whether to force compatibility with older SVN versions (< 1.2) +     */ +    public function setForceCompatible($force) +    { +        //$this->forceCompatible = (bool) $force; +        // see below, we need this to be true as xml mode does not work +    } + +    /** +     * Sets the max num of tags to display +     */ +    function setLimit($limit) +    { +        $this->limit = (int) $limit; +    } + +    /** +     * Sets whether to sort tags in descending order +     */ +    function setOrderDescending($orderDescending) +    { +        $this->orderDescending = (bool) $orderDescending; +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('list'); + +        if ($this->forceCompatible) { +            $output = $this->run(array('--verbose')); +            $result = null; + +            $lines = $output['.']['name']; + +            if ($this->orderDescending) { +                $lines = array_reverse($lines); +            } + +            $count = 0; +            foreach ($lines as $line) { +                if ($this->limit > 0 && $count >= $this->limit) { +                    break; +                } +                if (preg_match('@\s+(\d+)\s+(\S+)\s+(\S+ \S+ \S+)\s+(\S+)@', $line, $matches)) { +                    if ($matches[4] == '.') { +                        continue; +                    } +                    $result .= (!empty($result)) ? "\n" : ''; +                    $result .= $matches[1] . ' | ' . $matches[2] . ' | ' . $matches[3] . ' | ' . $matches[4]; +                    $count++; +                } +            } + +            if (!empty($result)) { +                $this->project->setProperty($this->getPropertyName(), $result); +            } else { +                throw new BuildException("Failed to parse the output of 'svn list --verbose'."); +            } +        } else { +            // this is not possible at the moment as SvnBaseTask always uses fetchmode ASSOC +            // which transfers everything into nasty assoc array instead of xml +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLogTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLogTask.php new file mode 100755 index 00000000..7f5c4025 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLogTask.php @@ -0,0 +1,108 @@ +<?php +/** + * $Id: fc8bc4cf4caa997c13dd66095997fa5478c47959 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Stores the output of a log command on a workingcopy or repositoryurl in a property. + * This stems from the SvnLastRevisionTask. + * + * @author Anton Stöckl <anton@stoeckl.de> + * @author Michiel Rook <mrook@php.net> (SvnLastRevisionTask) + * @version $Id: fc8bc4cf4caa997c13dd66095997fa5478c47959 $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.1.0 + */ +class SvnLogTask extends SvnBaseTask +{ +    private $propertyName = "svn.log"; +    private $forceCompatible = true; +    private $limit = null; + +    /** +     * Sets the name of the property to use +     */ +    function setPropertyName($propertyName) +    { +        $this->propertyName = $propertyName; +    } + +    /** +     * Returns the name of the property to use +     */ +    function getPropertyName() +    { +        return $this->propertyName; +    } + +    /** +     * Sets whether to force compatibility with older SVN versions (< 1.2) +     */ +    public function setForceCompatible($force) +    { +        //$this->forceCompatible = (bool) $force; +        // see below, we need this to be true as xml mode does not work +    } + +    /** +     * Sets the max num of log entries to get from svn +     */ +    function setLimit($limit) +    { +        $this->limit = (int) $limit; +    } + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('log'); + +        $switches= array(); +        if ($this->limit > 0) { +            $switches['limit'] = $this->limit; +        } + +        if ($this->forceCompatible) { +            $output = $this->run(array(), $switches); +            $result = null; + +            foreach ($output as $line) { +                $result .= (!empty($result)) ? "\n" : ''; +                $result .= "{$line['REVISION']} | {$line['AUTHOR']}  | {$line['DATE']}  | {$line['MSG']}"; +            } + +            if (!empty($result)) { +                $this->project->setProperty($this->getPropertyName(), $result); +            } else { +                throw new BuildException("Failed to parse the output of 'svn log'."); +            } +        } else { +            // this is not possible at the moment as SvnBaseTask always uses fetchmode ASSOC +            // which transfers everything into nasty assoc array instead of xml +        } +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnSwitchTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnSwitchTask.php new file mode 100644 index 00000000..cb6c5ca4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnSwitchTask.php @@ -0,0 +1,73 @@ +<?php +/** + * $Id: 2beb14d928ee47f36cceb9467b4a2ac9d2c81ef4 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Switches a repository at a given local directory to a different location + * + * @author Dom Udall <dom.udall@clock.co.uk> + * @version $Id: 2beb14d928ee47f36cceb9467b4a2ac9d2c81ef4 $ + * @package phing.tasks.ext.svn + * @since 2.4.3 + */ +class SvnSwitchTask extends SvnBaseTask +{ +    /** +     * Which Revision to Export +     * +     * @todo check if version_control_svn supports constants +     * +     * @var string +     */ +    private $revision = 'HEAD'; + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('switch'); + +        $this->log("Switching SVN repository at '" . $this->getToDir() . "' to '" . $this->getRepositoryUrl() . "' " +          . ($this->getRevision()=='HEAD'?'':" (revision: {$this->getRevision()})")); + +        // revision +        $switches = array( +            'r' => $this->getRevision(), +        ); + +        $this->run(array($this->getToDir()), $switches); +    } + +    public function setRevision($revision) +    { +        $this->revision = $revision; +    } +     +    public function getRevision() +    { +        return $this->revision; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnUpdateTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnUpdateTask.php new file mode 100644 index 00000000..c70039fc --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnUpdateTask.php @@ -0,0 +1,67 @@ +<?php +/** + * $Id: 9f5e4de2948b03eb6c9e459b1065bcedd851c025 $ + * + * 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/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Updates a repository in local directory + * + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @version $Id: 9f5e4de2948b03eb6c9e459b1065bcedd851c025 $ + * @package phing.tasks.ext.svn + * @since 2.3.0 + */ +class SvnUpdateTask extends SvnBaseTask +{ +    /** +     * Which Revision to Export +     *  +     * @todo check if version_control_svn supports constants +     *  +     * @var string +     */ +    private $revision = 'HEAD'; + +    /** +     * The main entry point +     * +     * @throws BuildException +     */ +    function main() +    { +        $this->setup('update'); + +        $this->log("Updating SVN repository at '" . $this->getToDir() . "'". ($this->revision=='HEAD'?'':" (revision: {$this->revision})")); + +        // revision +        $switches = array( +            'r' => $this->revision, +        ); + +        $this->run(array($this->getToDir()), $switches); +    } + +    public function setRevision($revision) +    { +        $this->revision = $revision; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php new file mode 100644 index 00000000..33d2e4e3 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php @@ -0,0 +1,510 @@ +<?php + +/* + *  $Id: cdbb2883ab70c650896a465a872b3da30f13eb00 $ + * + * 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/util/SourceFileScanner.php'; +include_once 'phing/mappers/MergeMapper.php'; +include_once 'phing/util/StringHelper.php'; + +/** + * Encodes files using Zeng Guard Encoder + * + * @author    Petr Rybak <petr@rynawe.net> + * @version   $Id: cdbb2883ab70c650896a465a872b3da30f13eb00 $ + * @package   phing.tasks.ext.zendguard + * @since     2.4.3 + */ +class ZendGuardEncodeTask extends MatchingTask +{ +    protected $filesets = array(); +    protected $encodeCommand; + + +    /** +     * TASK PROPERTIES +     * +     * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf +     * for more information on how to use ZendGuard +     * +     */ +    /** +     * Permanently deletes (see warning below) the original source files specified in the +     * SourceInputPath and saves the encoded files in its place. +     * This option has no option parameter. +     * When this option is use, do not use the output_file parameter. +     * +     * Warning: +     * To avoid permanent loss of non-encoded scripts, make a backup. Deleted files +     * cannot be restored or recovered and will be permanently deleted with this option. +     * If you are unsure about deleting the source files, use the ––rename-source option +     * instead +     * +     * @var bool +     */ +    protected $deleteSource = true; +    /** +     * Move the original source file to <input_file>.<renameSourceExt> and save the encoded file in its +     * place. +     * +     * If specified deleteSource will be automatically disabled. +     * +     * @var string +     */ +    protected $renameSourceExt = null; +    /** +     * Turns short PHP tag (“<?†) recognition either on or off. +     * On or off must be specified as an argument when using this option. +     * The default, when option is not used in the command-line, is - on +     * +     * @var bool +     */ +    protected $shortTags = true; +    /** +     * Turn ASP tag (“<%†) recognition on/off. (default: off). On or off must be specified +     * as an argument when using this option. +     * The default, when this option is not used in the command-line, is - off +     * +     * @var bool +     */ +    protected $aspTags = false; +    /** +     * +     * Disables the PHP-compatible header that is added to the top of every encoded file +     * by default. Encoded files generated with this option will not display a meaningful +     * error when loaded by PHP that doesn't have the Zend Optimizer properly installed. +     * Using this option saves approximately 1.5KB for every encoded file. Do not use it +     * unless disk space constraints are critica +     * +     * @var bool +     */ +    protected $noHeader = false; +    /** +     * If cryptography should be used to encode the source code +     * +     * @var bool +     */ +    protected $useCrypto = false; +    /** +     * Force cooperation with other encoded files only. This option generates files that +     * work exclusively with associated encoded files. Associated encoded files are +     * those generated by the same company. Files that do not share the same encoded +     * company association cannot call these files +     * +     * @var bool +     */ +    protected $encodedOnly = false; +    /** +     * Allow encoding previously encoded files. (NOT recommended!) +     * +     * @var bool +     */ +    protected $forceEncode = false; +    /** +     * Make an encoded file to expire on the given date. Date is in yyyy-mm-dd format. +     * +     * @var string +     */ +    protected $expires = null; +    /** +     * Level of obfuscation. Defaults to 0 (no obfuscation). +     * +     * @var int +     */ +    protected $obfuscationLevel = 0; +    /** +     * Optimization mask. (default value: [+++++++]) +     * opt_mask is an integer representing a bit-mask. +     * The default value enables all of the optimization passes. +     * Each optimization pass of the Zend Optimizer can be turned on or off based on +     * the mask entered +     * +     * @var int +     */ +    protected $optMask = null; +    /** +     * Path to the zend encoder binary +     * +     * @var string +     */ +    protected $zendEncoderPath = null; +    /** +     * Path to private key for licensing +     * +     * @var string +     */ +    protected $privateKeyPath = null; +    /** +     * Enable licensing. +     * If enabled, productName must be defined. +     * +     * @var bool +     */ +    protected $licenseProduct = false; +    /** +     * If true the ownership, permissions and timestamps +     * of the encoded files won't be preserved. +     * +     * @var bool +     */ +    protected $ignoreFileModes = false; +    /** +     * Enable signing +     * If enabled, productName must be defined. +     * +     * @var bool +     */ +    protected $signProduct = false; +    /** +     * Product name. Must be defined if licenseProduct +     * or signProduct is set to 1 +     * +     * @var string +     */ +    protected $productName = null; +    /** +     * Embed the information in the specified file into the header of the encoded file +     * (overrides noHeader) +     * +     * @var string +     */ +    protected $prologFile = null; + +    /** +     * TASK PROPERTIES SETTERS +     */ +    public function setZendEncoderPath($value) +    { +        $this->zendEncoderPath = $value; +    } + +    public function setPrivateKeyPath($value) +    { +        $this->privateKeyPath = $value; +    } + +    public function setShortTags($value) +    { +        $this->shortTags = (bool) $value; +    } + +    public function setAspTags($value) +    { +        $this->aspTags = (bool) $value; +    } + +    public function setDeleteSource($value) +    { +        $this->shortTags = (bool) $value; +    } + +    public function setUseCrypto($value) +    { +        $this->useCrypto = (bool) $value; +    } + +    public function setObfuscationLevel($value) +    { +        $this->obfuscationLevel = (int) $value; +    } + +    public function setLicenseProduct($value) +    { +        $this->licenseProduct = (bool) $value; +    } + +    public function setPrologFile($value) +    { +        $this->prologFile = $value; +    } + +    public function setSignProduct($value) +    { +        $this->signProduct = (bool) $value; +    } + +    public function setForceEncode($value) +    { +        $this->forceEncode = (bool) $value; +    } + +    public function setEncodedOnly($value) +    { +        $this->encodedOnly = (bool) $value; +    } + +    public function setIgnoreFileModes($value) +    { +        $this->ignoreFileModes = (bool) $value; +    } + +    public function setExpires($value) +    { +        $this->expires = $value; +    } + +    public function setProductName($value) +    { +        $this->productName = $value; +    } + +    public function setOptMask($value) +    { +        $this->optMask = (int) $value; +    } + +    public function setRenameSourceExt($value) +    { +        $this->renameSourceExt = $value; +    } + +    public function setNoHeader($value) +    { +        $this->noHeader = (bool) $value; +    } + +    /** +     * Add a new fileset. +     * +     * @return FileSet +     */ +    public function createFileSet() +    { +        $this->fileset = new ZendGuardFileSet(); +        $this->filesets[] = $this->fileset; +        return $this->fileset; +    } + +    /** +     * Verifies that the configuration is correct +     * +     * @throws BuildException +     */ +    protected function verifyConfiguration() +    { +        // Check that the zend encoder path is specified +        if (empty($this->zendEncoderPath)) { +            throw new BuildException("Zend Encoder path must be specified"); +        } + +        // verify that the zend encoder binary exists +        if (!file_exists($this->zendEncoderPath)) { +            throw new BuildException("Zend Encoder not found on path " . $this->zendEncoderPath); +        } + +        // if either sign or license is required the private key path needs to be defined +        // and the file has to exist and product name has to be specified +        if ($this->signProduct || $this->licenseProduct) { +            if (empty($this->privateKeyPath)) { +                throw new BuildException("Licensing or signing requested but privateKeyPath not provided."); +            } +            if (!is_readable($this->privateKeyPath)) { +                throw new BuildException("Licensing or signing requested but private key path doesn't exist or is unreadable."); +            } +            if (empty($this->productName)) { +                throw new BuildException("Licensing or signing requested but product name not provided."); +            } +        } + +        // verify prolog file exists +        if (!empty($this->prologFile)) { +            if (!file_exists($this->prologFile)) { +                throw new BuildException("The prolog file doesn't exist: " . $this->prologFile); +            } +        } +    } + +    /** +     * Do the work +     * +     * @throws BuildException +     */ +    public function main() +    { +        $this->verifyConfiguration(); +        $this->prepareEncoderCommand(); + +        try { +            if (empty($this->filesets)) { +                throw new BuildException("You must supply nested fileset.", +                    $this->getLocation()); +            } + +            $encodedFilesCounter = 0; + +            foreach ($this->filesets as $fs) { +                /* @var $fs FileSet */ + +                /* @var $fsBasedir PhingFile */ +                $fsBasedir = $fs->getDir($this->project)->getAbsolutePath(); + +                $files = $fs->getFiles($this->project, false); + +                foreach ($files as $file) { +                    $f = new PhingFile($fsBasedir, $file); + +                    if ($f->isFile()) { +                        $path = $f->getAbsolutePath(); + +                        $this->log("Encoding " . $path, Project::MSG_VERBOSE); +                        $this->encodeFile($path); + +                        $encodedFilesCounter++; +                    } +                } +            } + +            $this->log("Encoded files: " . $encodedFilesCounter); +        } catch (IOException $ioe) { +            $msg = "Problem encoding files: " . $ioe->getMessage(); +            throw new BuildException($msg, $ioe, $this->getLocation()); +        } +    } + +    /** +     * Prepares the main part of the command that will be +     * used to encode the given file(s). +     */ +    protected function prepareEncoderCommand() +    { +        $command = $this->zendEncoderPath . " \\\n"; + +        if (!empty($this->renameSourceExt)) { +            $command .= " --rename-source " . $this->renameSourceExt . " \\\n"; +        } elseif ($this->deleteSource) { +            // delete source +            $command .= " --delete-source \\\n"; +        } + +        // short tags +        $command .= " --short-tags " . (($this->shortTags) ? 'on' : 'off') . " \\\n"; + +        // asp tags +        $command .= " --asp-tags " . (($this->aspTags) ? 'on' : 'off') . " \\\n"; + +        // use crypto +        if ($this->useCrypto) { +            $command .= " --use-crypto  \\\n"; +        } + +        // ignore file modes +        if ($this->ignoreFileModes) { +            $command .= " --ignore-file-modes \\\n"; +        } + +        // force encode +        if ($this->forceEncode) { +            $command .= " --force-encode \\\n"; +        } + +        // expires +        if (!empty($this->expires)) { +            $command .= " --expires " . $this->expires . " \\\n"; +        } + +        // insert prolog file name or no-header +        if (!empty($this->prologFile)) { +            $command .= " --prolog-filename " . $this->prologFile . " \\\n"; +        } elseif ($this->noHeader) { +            // no-header +            $command .= " --no-header \\\n"; +        } + +        // obfuscation level +        if ($this->obfuscationLevel > 0) { +            $command .= " --obfuscation-level " . $this->obfuscationLevel . " \\\n"; +        } + +        // encoded only +        if ($this->encodedOnly) { +            $command .= " --encoded-only  \\\n"; +        } + +        // opt mask +        if (null !== $this->optMask) { +            $command .= " --optimizations " . $this->optMask . " \\\n"; +        } + +        // Signing or licensing +        if ($this->signProduct) { +            $command .= " --sign-product " . $this->productName . " --private-key " . $this->privateKeyPath . " \\\n"; +        } elseif ($this->licenseProduct) { +            $command .= " --license-product " . $this->productName . " --private-key " . $this->privateKeyPath . " \\\n"; +        } + +        // add a blank space +        $command .= " "; + +        $this->encodeCommand = $command; + +    } + +    /** +     * Encodes a file using currently defined Zend Guard settings +     * +     * @param string $filePath Path to the encoded file +     */ +    protected function encodeFile($filePath) +    { +        $command = $this->encodeCommand . $filePath . ' 2>&1'; + +        $this->log('Running: ' . $command, Project::MSG_VERBOSE); + +        $tmp = exec($command, $output, $return_var); +        if ($return_var !== 0) { +            throw new BuildException("Encoding failed. \n Msg: " . $tmp . " \n Encode command: " . $command); +        } + +        return true; +    } + +} + +/** + * This is a FileSet with the to specify permissions. + * + * Permissions are currently not implemented by PEAR Archive_Tar, + * but hopefully they will be in the future. + * + * @package phing.tasks.ext.zendguard + */ +class ZendGuardFileSet extends FileSet +{ +    private $files = null; + +    /** +     *  Get a list of files and directories specified in the fileset. +     *  @return array a list of file and directory names, relative to +     *    the baseDir for the project. +     */ +    public function getFiles(Project $p, $includeEmpty = true) +    { + +        if ($this->files === null) { + +            $ds = $this->getDirectoryScanner($p); +            $this->files = $ds->getIncludedFiles(); +        } // if ($this->files===null) + +        return $this->files; +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.php b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.php new file mode 100644 index 00000000..2a3f71ca --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.php @@ -0,0 +1,524 @@ +<?php + +/* + *  $Id: 96af59b9cbecaf7f146dffab1d0b5a806a56b47f $ + * + * 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>. + */ + +/** + * Produce license files using Zeng Guard. + * The task can produce a license file from the given + * license properties or it can use a template. + * + * @author    Petr Rybak <petr@rynawe.net> + * @version   $Id: 96af59b9cbecaf7f146dffab1d0b5a806a56b47f $ + * @package   phing.tasks.ext.zendguard + * @since     2.4.3 + */ +class ZendGuardLicenseTask extends Task +{ +    protected $zendsignCommand; +    private $tmpLicensePath; + +    /** +     * TASK PROPERTIES +     * +     * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf +     * for more information on how to use ZendGuard +     * +     */ +    /** +     * Path to Zend Guard zendenc_sign executable +     *  +     * @var string +     */ +    protected $zendsignPath; +    /** +     * Path to private key that will be used to sign the license +     *  +     * @var string +     */ +    protected $privateKeyPath; +    /** +     * Where to store the signed license file +     *  +     * @var string  +     */ +    protected $outputFile; +    /** +     * Path to license template. If specified all +     * license properties will be ignored and the +     * template will be used to generate the file. +     * +     * @var string +     */ +    protected $licenseTemplate; +    /** +     * The name assigned to Product. This must be the same name used when encoding +     * the PHP files. +     * +     * REQUIRED +     *  +     * @var string +     */ +    protected $productName; +    /** +     * The Name of the Registered owner of the license. +     * +     * REQUIRED +     *  +     * @var string  +     */ +    protected $registeredTo; +    /** +     * Expiration date of the license. Used if the license is issued with a date restriction. +     * Possible values: +     *     - 'Never', '0' or false: the license won't expire +     *     - A Date in format DD-MM-YYYY to set expiration for that date +     *     - Relative date supported by the PHP strtotime function (e.g. +1 month) +     * +     * REQUIRED +     * +     * @var string +     */ +    protected $expires; +    /** +     * Limits the use of the license to IP addresses that fall within specification. Supports  +     * wildcards for any of the IP place holders, as well as the two types of net masks  +     * (filters). +     * Netmask pair An IP a.b.c.d, and a netmask w.x.y.z. (That is., 10.1.0.0/255.255.0.0),  +     * where the binary of mask is applied to filter IP addresses. +     * ip/nnn (similar to a CIDR specification) This mask consists of nnn high-order 1 bits.  +     * (That is, 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0). Instead of spelling out  +     * the bits of the subnet mask, this mask notation is simply listed as the number of 1s  +     * bits that start the mask. Rather than writing the address and subnet mask as  +     * 192.60.128.0/255.255.252.0 the network address would be written simply as:  +     * 192.60.128.0/22 which indicates starting address of the network and number of 1s +     * bits (22) in the network portion of the address. The mask in binary is  +     * (11111111.11111111.11111100.00000000). +     *  +     * OPTIONAL +     *  +     * Example (Wildcard): +     * IP-Range = 10.1.*.* +     * Example (Net Mask): +     * IP-Range = 10.1.0.0/255.255.0.0 +     * Example (Net Mask): +     * IP-Range = 10.1.0.0/16 +     *  +     * @var string  +     */ +    protected $ipRange; +    /** +     * Coded string (Zend Host ID) used to lock the license to a specific hardware. The  +     * Zend Host ID obtained from the machine where the encoded files and license are  +     * to be installed. The Zend Host ID code can be obtained by using the zendid utility. +     * For more details, see Getting the Zend Host ID. +     *  +     * REQUIRED if Hardware-Locked is set equal to YES. +     * Meaningless if Hardware-Locked is set equal to NO. +     * +     * User semicolon to enter more than one Host-ID +     * +     * Example: +     * Host-ID = H:MFM43-Q9CXC-B9EDX-GWYSU;H:MFM43-Q9CXC-B9EDX-GWYTY +     *  +     * @var string  +     */ +    protected $hostID; +    /** +     * Option that indicates if the license will be locked to a specific machine +     * using the Zend Host ID code(s). If set to YES, the Host-ID is required. +     *  +     * OPTIONAL +     * +     * @var bool +     */ +    protected $hardwareLocked; +    /** +     * Semi-colon separated user defined values that will be part of the license. These values +     * CANNOT be modified after the license is produced. Modification +     * would invalidate the license. +     * +     * OPTIONAL +     * Example: +     * Tea=Mint Flavor;Coffee=Arabica +     * +     * @var string +     */ +    protected $userDefinedValues; +    /** +     * Semi-colon separated user defined x-values that will be part of the license. These values +     * CAN be modified after the license is produced. Modification +     * won't invalidate the license. +     * +     * OPTIONAL +     * Example: +     * Tea=Mint Flavor;Coffee=Arabica +     * +     * @var string +     */ +    protected $xUserDefinedValues; + + +    public function setLicenseTemplate($value) +    { +        $this->licenseTemplate = $value; +    } + +    public function setProductName($productName) +    { +        $this->productName = $productName; +    } + +    public function setRegisteredTo($registeredTo) +    { +        $this->registeredTo = $registeredTo; +    } + +    /** +     * Process the expires property. If the value is +     * empty (false, '', ...) it will set the value to 'Never' +     * Otherwise it will run the value through strtotime so relative +     * date and time notation can be used (e.g. +1 month) +     * +     * @param mixed $expires +     * +     * @return string +     */ +    public function setExpires($expires) +    { +        // process the expires value +        if (false === $expires || '0' === $expires || strtolower($expires) == 'never' || '' === $expires) { +            $this->expires = 'Never'; +        } else { +            $time = strtotime($expires); +            if (!$time) { +                throw new BuildException("Unsupported expires format: " . $expires); +            } +            $this->expires = date('d-M-Y', $time); +        } +    } + +    public function setIpRange($iprange) +    { +        $this->ipRange = $iprange; +    } + +    public function setHostID($hostID) +    { +        $this->hostID = $hostID; +    } + +    public function setHardwareLocked($hardwareLocked) +    { +        $this->hardwareLocked = (bool) $hardwareLocked; +    } + +    public function setUserDefinedValues($userDefinedValues) +    { +        $this->userDefinedValues = $userDefinedValues; +    } + +    public function setXUserDefinedValues($xUserDefinedValues) +    { +        $this->xUserDefinedValues = $xUserDefinedValues; +    } + +    public function setZendsignPath($zendsignPath) +    { +        $this->zendsignPath = $zendsignPath; +    } + +    public function setPrivateKeyPath($privateKeyPath) +    { +        $this->privateKeyPath = $privateKeyPath; +    } + +    public function setOutputFile($outputFile) +    { +        $this->outputFile = $outputFile; +    } + +    /** +     * Verifies that the configuration is correct +     * +     * @throws BuildException +     */ +    protected function verifyConfiguration() +    { +        // Check that the zend encoder path is specified +        if (empty($this->zendsignPath)) { +            throw new BuildException("Zendenc_sign path must be specified"); +        } +        // verify that the zend encoder binary exists +        if (!file_exists($this->zendsignPath)) { +            throw new BuildException("Zendenc_sign not found on path " . $this->zendsignPath); +        } + +        // verify that the private key path is defined +        if (empty($this->privateKeyPath)) { +            throw new BuildException("You must define privateKeyPath."); +        } +        // verify that the private key file is readable +        if (!is_readable($this->privateKeyPath)) { +            throw new BuildException("Private key file is not readable: " . $this->privateKeyPath); +        } + +        // if template is passed, verify that it is readable +        if (!empty($this->licenseTemplate)) { +            if (!is_readable($this->licenseTemplate)) { +                throw new BuildException("License template file is not readable " . $this->licenseTemplate); +            } +        } + +        // check that output file path is defined +        if (empty($this->outputFile)) { +            throw new BuildException("Path where to store the result file needs to be defined in outputFile property"); +        } + +        // if license template is NOT provided check that all required parameters are defined +        if (empty($this->licenseTemplate)) { + +            // check productName +            if (empty($this->productName)) { +                throw new BuildException("Property must be defined: productName"); +            } + +            // check expires +            if (null === $this->expires) { +                throw new BuildException("Property must be defined: expires"); +            } + +            // check registeredTo +            if (empty($this->registeredTo)) { +                throw new BuildException("Property must be defined: registeredTo"); +            } + +            // check hardwareLocked +            if (null === $this->hardwareLocked) { +                throw new BuildException("Property must be defined: hardwareLocked"); +            } + +            // if hardwareLocked is set to true, check that Host-ID is set +            if ($this->hardwareLocked) { +                if (empty($this->hostID)) { +                    throw new BuildException("If you set hardwareLocked to true hostID must be provided"); +                } +            } +        } +    } + +    /** +     * Do the work +     * +     * @throws BuildException +     */ +    public function main() +    { +        try { +            $this->verifyConfiguration(); + +            $this->generateLicense(); +        } catch (Exception $e) { +            // remove the license temp file if it was created +            $this->cleanupTmpFiles(); + +            throw $e; +        } +        $this->cleanupTmpFiles(); +    } + +    /** +     * If temporary license file was created during the process +     * this will remove it +     * +     * @return void +     */ +    private function cleanupTmpFiles() +    { +        if (!empty($this->tmpLicensePath) && file_exists($this->tmpLicensePath)) { +            $this->log("Deleting temporary license template " . $this->tmpLicensePath, Project::MSG_VERBOSE); + +            unlink($this->tmpLicensePath); +        } +    } + +    /** +     * Prepares and returns the command that will be +     * used to create the license. +     * +     * @return string +     */ +    protected function prepareSignCommand() +    { +        $command = $this->zendsignPath; + +        // add license path +        $command .= ' ' . $this->getLicenseTemplatePath(); + +        // add result file path +        $command .= ' ' . $this->outputFile; + +        // add key path +        $command .= ' ' . $this->privateKeyPath; + + +        $this->zendsignCommand = $command; + +        return $command; +    } + +    /** +     * Checks if the license template path is defined +     * and returns it. +     * If it the license template path is not defined +     * it will generate a temporary template file and +     * provide it as a template. +     * +     * @return string +     */ +    protected function getLicenseTemplatePath() +    { +        if (!empty($this->licenseTemplate)) { +            return $this->licenseTemplate; +        } else { +            return $this->generateLicenseTemplate(); +        } +    } + +    /** +     * Creates the signed license at the defined output path +     * +     * @return void +     */ +    protected function generateLicense() +    { +        $command = $this->prepareSignCommand() . ' 2>&1'; + +        $this->log('Creating license at ' . $this->outputFile); + +        $this->log('Running: ' . $command, Project::MSG_VERBOSE); +        $tmp = exec($command, $output, $return_var); + +        // Check for exit value 1. Zendenc_sign command for some reason +        // returns 0 in case of failure and 1 in case of success... +        if ($return_var !== 1) { +            throw new BuildException("Creating license failed. \n\nZendenc_sign msg:\n" . join("\n", $output) . "\n\n"); +        } +    } + +    /** +     * It will generate a temporary license template +     * based on the properties defined. +     * +     * @return string Path of the temporary license template file +     */ +    protected function generateLicenseTemplate() +    { +        $this->tmpLicensePath = tempnam(sys_get_temp_dir(), 'zendlicense'); + +        $this->log("Creating temporary license template " . $this->tmpLicensePath, Project::MSG_VERBOSE); +        if (file_put_contents($this->tmpLicensePath, $this->generateLicenseTemplateContent()) === false) { +            throw new BuildException("Unable to create temporary template license file: " . $this->tmpLicensePath); +        } + +        return $this->tmpLicensePath; +    } + +    /** +     * Generates license template content based +     * on the defined parameters +     * +     * @return string +     */ +    protected function generateLicenseTemplateContent() +    { +        $contentArr = array(); + +        // Product Name +        $contentArr[] = array('Product-Name', $this->productName); +        // Registered to +        $contentArr[] = array('Registered-To', $this->registeredTo); +        // Hardware locked +        $contentArr[] = array('Hardware-Locked', ($this->hardwareLocked ? 'Yes' : 'No')); + +        // Expires +        $contentArr[] = array('Expires', $this->expires); + +        // IP-Range +        if (!empty($this->ipRange)) { +            $contentArr[] = array('IP-Range', $this->ipRange); +        } +        // Host-ID +        if (!empty($this->hostID)) { +            foreach (explode(';', $this->hostID) as $hostID) { +                $contentArr[] = array('Host-ID', $hostID); +            } +        } else { +            $contentArr[] = array('Host-ID', 'Not-Locked'); +        } + +        // parse user defined fields +        if (!empty($this->userDefinedValues)) { +            $this->parseAndAddUserDefinedValues($this->userDefinedValues, $contentArr); +        } +        // parse user defined x-fields +        if (!empty($this->xUserDefinedValues)) { +            $this->parseAndAddUserDefinedValues($this->xUserDefinedValues, $contentArr, 'X-'); +        } + +        // merge all the values +        $content = ''; +        foreach ($contentArr as $valuePair) { + +            list($key, $value) = $valuePair; + +            $content .= $key . " = " . $value . "\n"; +        } + +        return $content; +    } + +    /** +     * Parse the given string in format like key1=value1;key2=value2;... and  +     * converts it to array +     *   (key1=>value1, key2=value2, ...) +     * +     * @param stirng $valueString Semi-colon separated value pairs +     * @param array  $valueArray Array to which the values will be added +     * @param string $keyPrefix Prefix to use when adding the key +     * +     * @return void +     */ +    protected function parseAndAddUserDefinedValues($valueString, array &$valueArray, $keyPrefix = '', +                                                    $pairSeparator = ';') +    { +        // explode the valueString (semicolon) +        $valuePairs = explode($pairSeparator, $valueString); +        if (!empty($valuePairs)) { +            foreach ($valuePairs as $valuePair) { +                list($key, $value) = explode('=', $valuePair, 2); + +                // add pair into the valueArray +                $valueArray[] = array($keyPrefix . $key, $value); +            } +        } +    } + +} diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php index e4c291a1..ce0ca210 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: AdhocTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 03a742eb03e5e1515c297d941970a86b00e1f69e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ require_once 'phing/Task.php';   * Subclasses exist for conveniently declaring and registering tasks and types.   *    * @author   Hans Lellelid <hans@xmpl.org> - * @version  $Revision: 1.6 $ + * @version  $Id$   * @package  phing.tasks.system   */  class AdhocTask extends Task { @@ -51,10 +51,10 @@ class AdhocTask extends Task {          $this->execute();                  if ($this->newClasses) {              foreach($this->newClasses as $classname) { -                $this->log("Added adhoc class " . $classname, PROJECT_MSG_VERBOSE); +                $this->log("Added adhoc class " . $classname, Project::MSG_VERBOSE);              }          } else { -            $this->log("Adhoc task executed but did not result in any new classes.", PROJECT_MSG_VERBOSE); +            $this->log("Adhoc task executed but did not result in any new classes.", Project::MSG_VERBOSE);          }      } diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php index ea336f84..03f80b27 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: AdhocTaskdefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: da14cd0fdc73a0eb13ecc8c0b5ae693550a052b1 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -46,10 +46,11 @@ require_once 'phing/tasks/system/AdhocTask.php';   * </target>   *     * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.5 $ + * @version   $Id$   * @package   phing.tasks.system   */ -class AdhocTaskdefTask extends AdhocTask { +class AdhocTaskdefTask extends AdhocTask +{      /**       * The tag that refers to this task. @@ -60,31 +61,43 @@ class AdhocTaskdefTask extends AdhocTask {       * Set the tag that will represent this adhoc task/type.       * @param string $name       */        -    public function setName($name) { +    public function setName($name) +    {          $this->name = $name;      }      /** Main entry point */ -    public function main() {         -        if ($this->name === null) { +    public function main() +    { +        if ($this->name === null) +        {              throw new BuildException("The name attribute is required for adhoc task definition.",$this->location);          } -        $this->execute(); +        $taskdefs = $this->getProject()->getTaskDefinitions(); -        $classes = $this->getNewClasses(); -        if (count($classes) !== 1) { -            throw new BuildException("You must define one (and only one) class for AdhocTaskdefTask."); -        } -        $classname = array_shift($classes); -         -        // instantiate it to make sure it is an instance of Task -        $t = new $classname(); -        if (!($t instanceof Task)) { -            throw new BuildException("The adhoc class you defined must be an instance of phing.Task", $this->location); +        if (!isset($taskdefs[$this->name])) +        { +            $this->execute(); + +            $classes = $this->getNewClasses(); +             +            if (count($classes) < 1) +            { +                throw new BuildException("You must define at least one class for AdhocTaskdefTask."); +            } +             +            $classname = array_pop($classes); + +            // instantiate it to make sure it is an instance of Task +            $t = new $classname(); +            if (!($t instanceof Task)) +            { +                throw new BuildException("The adhoc class you defined must be an instance of phing.Task", $this->location); +            } +             +            $this->log("Task " . $this->name . " will be handled by class " . $classname, Project::MSG_VERBOSE); +            $this->project->addTaskDefinition($this->name, $classname);          } -         -        $this->log("Task " . $this->name . " will be handled by class " . $classname, PROJECT_MSG_VERBOSE); -        $this->project->addTaskDefinition($this->name, $classname);              }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php index b836ad93..80be2fc9 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: AdhocTypedefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 679ed701a01fef022a2da8ff5db16cff658b77e6 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ require_once 'phing/tasks/system/AdhocTask.php';   * A class for creating adhoc datatypes in build file.   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.4 $ + * @version   $Id$   * @package   phing.tasks.system   */  class AdhocTypedefTask extends AdhocTask { @@ -65,7 +65,7 @@ class AdhocTypedefTask extends AdhocTask {              throw new BuildException("The adhoc class you defined must be an instance of phing.ProjectComponent", $this->location);          } -        $this->log("Datatype " . $this->name . " will be handled by class " . $classname, PROJECT_MSG_VERBOSE); +        $this->log("Datatype " . $this->name . " will be handled by class " . $classname, Project::MSG_VERBOSE);          $this->project->addDataTypeDefinition($this->name, $classname);              }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/AppendTask.php b/buildscripts/phing/classes/phing/tasks/system/AppendTask.php index feb797cf..a7c4dcda 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AppendTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AppendTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: AppendTask.php 59 2006-04-28 14:49:47Z mrook $   + *  $Id: 056086ae305f5447baee1a4c7b1ad59ceb8cf50b $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -48,7 +48,7 @@ include_once 'phing/types/FileSet.php';   * </append>   * </code>   * @package phing.tasks.system - * @version $Revision: 1.14 $ + * @version $Id$   */  class AppendTask extends Task { @@ -80,7 +80,7 @@ class AppendTask extends Task {       * @deprecated Will be removed with final release.       */      function setTo(PhingFile $f) {         -        $this->log("The 'to' attribute is deprecated in favor of 'destFile'; please update your code.", PROJECT_MSG_WARN); +        $this->log("The 'to' attribute is deprecated in favor of 'destFile'; please update your code.", Project::MSG_WARN);          $this->to = $f;      } @@ -165,7 +165,7 @@ class AppendTask extends Task {              // out for better performance(?)              $lines = explode("\n", $this->text);              foreach($lines as $line) { -                $this->log($line, PROJECT_MSG_VERBOSE); +                $this->log($line, Project::MSG_VERBOSE);              }              $writer->write($this->text); @@ -177,7 +177,7 @@ class AppendTask extends Task {                  try {                      $this->appendFile($writer, $this->file);                  } catch (Exception $ioe) { -                    $this->log("Unable to append contents of file " . $this->file->getAbsolutePath() . ": " . $ioe->getMessage(), PROJECT_MSG_WARN); +                    $this->log("Unable to append contents of file " . $this->file->getAbsolutePath() . ": " . $ioe->getMessage(), Project::MSG_WARN);                  }                              } @@ -187,7 +187,7 @@ class AppendTask extends Task {                      $files = $fl->getFiles($this->project);                      $this->appendFiles($writer, $files, $fl->getDir($this->project));                  } catch (BuildException $be) { -                    $this->log($be->getMessage(), PROJECT_MSG_WARN); +                    $this->log($be->getMessage(), Project::MSG_WARN);                  }              } @@ -197,7 +197,7 @@ class AppendTask extends Task {                      $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles();                      $this->appendFiles($writer, $files, $fs->getDir($this->project));                  } catch (BuildException $be) { -                    $this->log($be->getMessage(), PROJECT_MSG_WARN); +                    $this->log($be->getMessage(), Project::MSG_WARN);                  }              }                         @@ -224,7 +224,7 @@ class AppendTask extends Task {                      $pathSlot->setValue($f->getPath());                      $this->appendFile($writer, $f);                  } catch (Exception $ioe) { -                    $this->log("Unable to append contents of file " . $f->getAbsolutePath() . ": " . $ioe->getMessage(), PROJECT_MSG_WARN); +                    $this->log("Unable to append contents of file " . $f->getAbsolutePath() . ": " . $ioe->getMessage(), Project::MSG_WARN);                  }              }          } // if !empty         diff --git a/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php b/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php index 76de3e40..bd5701e4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: AvailableTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 7388bc66c9574987edd02ad3b2d6f14462f6b157 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,23 +28,25 @@ include_once 'phing/tasks/system/condition/ConditionBase.php';   *  Note: implements condition interface (see condition/Condition.php)   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.11 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @package   phing.tasks.system   */  class AvailableTask extends Task {      /** Property to check for. */      private $property; -     +      /** Value property should be set to. */      private $value = "true"; -     +      /** Resource to check for */      private $resource; -     +      private $type = null;      private $filepath = null; +     +    private $followSymlinks = false;      function setProperty($property) {          $this->property = (string) $property; @@ -65,6 +67,36 @@ class AvailableTask extends Task {      function setType($type) {          $this->type = (string) strtolower($type);      } +     +    public function setFollowSymlinks($followSymlinks) +    { +        $this->followSymlinks = (bool) $followSymlinks; +    } +     +    /** +     * Set the path to use when looking for a file. +     *  +     * @param Path $filepath a Path instance containing the search path for files. +     */ +    public function setFilepath(Path $filepath) { +        if ($this->filepath === null) { +            $this->filepath = $filepath; +        } else { +            $this->filepath->append($filepath); +        } +    } + +    /** +     * Creates a path to be configured +     *  +     * @return Path +     */  +    public function createFilepath() { +        if ($this->filepath === null) { +            $this->filepath = new Path($this->project); +        } +        return $this->filepath->createPath(); +    }      function main() {          if ($this->property === null) { @@ -77,20 +109,20 @@ class AvailableTask extends Task {      function evaluate() {          if ($this->file === null && $this->resource === null) { -            throw new BuildException("At least one of (file|resource) is required", $this->location);             +            throw new BuildException("At least one of (file|resource) is required", $this->location);          }          if ($this->type !== null && ($this->type !== "file" && $this->type !== "dir")) {              throw new BuildException("Type must be one of either dir or file", $this->location);          } -         +          if (($this->file !== null) && !$this->_checkFile()) { -            $this->log("Unable to find " . $this->file->__toString() . " to set property " . $this->property, PROJECT_MSG_VERBOSE); +            $this->log("Unable to find " . $this->file->__toString() . " to set property " . $this->property, Project::MSG_VERBOSE);              return false;          }          if (($this->resource !== null) && !$this->_checkResource($this->resource)) { -            $this->log("Unable to load resource " . $this->resource . " to set property " . $this->property, PROJECT_MSG_VERBOSE); +            $this->log("Unable to load resource " . $this->resource . " to set property " . $this->property, Project::MSG_VERBOSE);              return false;          } @@ -98,13 +130,13 @@ class AvailableTask extends Task {      }      // this is prepared for the path type -    function _checkFile() { +    private function _checkFile() {          if ($this->filepath === null) {              return $this->_checkFile1($this->file);          } else { -            $paths = $this->filepath->listDir(); +            $paths = $this->filepath->listPaths();              for($i=0,$pcnt=count($paths); $i < $pcnt; $i++) { -                $this->log("Searching " . $paths[$i], PROJECT_MSG_VERBOSE); +                $this->log("Searching " . $paths[$i], Project::MSG_VERBOSE);                  $tmp = new PhingFile($paths[$i], $this->file->getName());                  if($tmp->isFile()) {                      return true; @@ -114,7 +146,12 @@ class AvailableTask extends Task {          return false;      } -    function _checkFile1($file) { +    private function _checkFile1(PhingFile $file) { +        // Resolve symbolic links +        if ($this->followSymlinks && $file->isLink()) { +            $file = new PhingFile($file->getLinkTarget()); +        } +                  if ($this->type !== null) {              if ($this->type === "dir") {                  return $file->isDirectory(); @@ -124,9 +161,12 @@ class AvailableTask extends Task {          }          return $file->exists();      } - -    function _checkResource($resource) { -        return $this->_checkFile1(new PhingFile(Phing::getResourcePath($resource))); +     +    private function _checkResource($resource) { +        if (null != ($resourcePath = Phing::getResourcePath($resource))) { +            return $this->_checkFile1(new PhingFile($resourcePath)); +        } else { +            return false; +        }      } -  } diff --git a/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php b/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php index 80470dea..b2300459 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ChmodTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: fad30caf32ff1ee9ff98f63849d61053ab88f645 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ include_once 'phing/types/FileSet.php';   *   * @author    Manuel Holtgrewe <grin@gmx.net>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.12 $ + * @version   $Id: fad30caf32ff1ee9ff98f63849d61053ab88f645 $   * @package   phing.tasks.system   */  class ChmodTask extends Task { @@ -39,21 +39,22 @@ class ChmodTask extends Task {      private $filesets = array();      private $filesystem; -	 -	private $quiet = false;	 -	private $failonerror = true; -	 -	/** -	 * This flag means 'note errors to the output, but keep going' -	 * @see setQuiet() -	 */ +     +    private $quiet = false;  +    private $failonerror = true; +    private $verbose = true; +     +    /** +     * This flag means 'note errors to the output, but keep going' +     * @see setQuiet() +     */      function setFailonerror($bool) {          $this->failonerror = $bool; -    }	 +    }         /**       * Set quiet mode, which suppresses warnings if chmod() fails. -	 * @see setFailonerror() +     * @see setFailonerror()       */      function setQuiet($bool) {          $this->quiet = $bool; @@ -61,7 +62,15 @@ class ChmodTask extends Task {              $this->failonerror = false;          }      } -	 +     +    /** +     * Set verbosity, which if set to false surpresses all but an overview +     * of what happened. +     */ +    function setVerbose($bool) { +        $this->verbose = (bool)$bool; +    } +          /**       * Sets a single source file to touch.  If the file does not exist       * an empty file will be created. @@ -118,16 +127,21 @@ class ChmodTask extends Task {       * @return void       */      private function chmod() { -    	 -		if (strlen($this->mode) === 4) { -			$mode = octdec($this->mode); -		} else { -			// we need to prepend the 0 before converting -			$mode = octdec("0". $this->mode); -		} +         +        if (strlen($this->mode) === 4) { +            $mode = octdec($this->mode); +        } else { +            // we need to prepend the 0 before converting +            $mode = octdec("0". $this->mode); +        } +         +        // counters for non-verbose output +        $total_files = 0; +        $total_dirs = 0;          // one file          if ($this->file !== null) { +            $total_files = 1;              $this->chmodFile($this->file, $mode);          } @@ -140,38 +154,50 @@ class ChmodTask extends Task {              $srcFiles = $ds->getIncludedFiles();              $srcDirs = $ds->getIncludedDirectories(); -            for ($j = 0, $filecount = count($srcFiles); $j < $filecount; $j++) { +            $filecount = count($srcFiles); +            $total_files = $total_files + $filecount; +            for ($j = 0; $j < $filecount; $j++) {                  $this->chmodFile(new PhingFile($fromDir, $srcFiles[$j]), $mode);              } -            for ($j = 0, $dircount = count($srcDirs); $j <  $dircount; $j++) { +            $dircount = count($srcDirs); +            $total_dirs = $total_dirs + $dircount; +            for ($j = 0; $j <  $dircount; $j++) {                  $this->chmodFile(new PhingFile($fromDir, $srcDirs[$j]), $mode);              }          } +        if (!$this->verbose) { +            $this->log('Total files changed to ' . vsprintf('%o', $mode) . ': ' . $total_files); +            $this->log('Total directories changed to ' . vsprintf('%o', $mode) . ': ' . $total_dirs); +        } +      } -	/** -	 * Actually change the mode for the file. -	 * @param PhingFile $file -	 * @param int $mode -	 */ +    /** +     * Actually change the mode for the file. +     * @param PhingFile $file +     * @param int $mode +     */      private function chmodFile(PhingFile $file, $mode) {          if ( !$file->exists() ) {              throw new BuildException("The file " . $file->__toString() . " does not exist");          }    -		      -		try { -			$file->setMode($mode); -			$this->log("Changed file mode on '" . $file->__toString() ."' to " . vsprintf("%o", $mode)); -		} catch (Exception $e) { -			if($this->failonerror) { -				throw $e; -			} else { -				$this->log($e->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); -			} -		} +              +        try { +            $file->setMode($mode); +            if ($this->verbose) { +                $this->log("Changed file mode on '" . $file->__toString() ."' to " . vsprintf("%o", $mode)); +            } +        } catch (Exception $e) { +            if($this->failonerror) { +                throw $e; +            } else { +                $this->log($e->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); +            } +        }      } -	 +      } + diff --git a/buildscripts/phing/classes/phing/tasks/system/ChownTask.php b/buildscripts/phing/classes/phing/tasks/system/ChownTask.php new file mode 100755 index 00000000..60b8105c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/ChownTask.php @@ -0,0 +1,216 @@ +<?php +/* + *  $Id: f7234abd52e7f80177f4b121436ae7276370993c $ + * + * 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/Task.php'; +include_once 'phing/types/FileSet.php'; + +/** + * Task that changes the permissions on a file/directory. + * + * @author    Mehmet Emre Yilmaz <mehmety@gmail.com> + * @version   $Id: f7234abd52e7f80177f4b121436ae7276370993c $ + * @package   phing.tasks.system + */ +class ChownTask extends Task { + +    private $file; + +    private $user; +    private $group; + +    private $filesets = array(); + +    private $filesystem; + +    private $quiet = false; +    private $failonerror = true; +    private $verbose = true; + +    /** +     * This flag means 'note errors to the output, but keep going' +     * @see setQuiet() +     */ +    function setFailonerror($bool) { +        $this->failonerror = $bool; +    } + +    /** +     * Set quiet mode, which suppresses warnings if chown() fails. +     * @see setFailonerror() +     */ +    function setQuiet($bool) { +        $this->quiet = $bool; +        if ($this->quiet) { +            $this->failonerror = false; +        } +    } + +    /** +     * Set verbosity, which if set to false surpresses all but an overview +     * of what happened. +     */ +    function setVerbose($bool) { +        $this->verbose = (bool)$bool; +    } + +    /** +     * Sets a single source file to touch.  If the file does not exist +     * an empty file will be created. +     */ +    function setFile(PhingFile $file) { +        $this->file = $file; +    } + +    /** +     * Sets the user +     */ +    function setUser($user) { +        $this->user = $user; +    } + +    /** +     * Sets the group +     */ +    function setGroup($group) { +        $this->group = $group; +    } + +    /** +     * Nested creator, adds a set of files (nested fileset attribute). +     */ +    function addFileSet(FileSet $fs) { +        $this->filesets[] = $fs; +    } + +    /** +     * Execute the touch operation. +     * @return void +     */ +    function main() { +        // Check Parameters +        $this->checkParams(); +        $this->chown(); +    } + +    /** +     * Ensure that correct parameters were passed in. +     * @return void +     */ +    private function checkParams() { + +        if ($this->file === null && empty($this->filesets)) { +            throw new BuildException("Specify at least one source - a file or a fileset."); +        } + +        if ($this->user === null && $this->group === null) { +            throw new BuildException("You have to specify either an owner or a group for chown."); +        } +    } + +    /** +     * Does the actual work. +     * @return void +     */ +    private function chown() { +        $userElements = explode('.', $this->user); + +        $user = $userElements[0]; +         +        if (count($userElements) > 1) { +            $group = $userElements[1]; +        } else { +            $group = $this->group; +        } + +        // counters for non-verbose output +        $total_files = 0; +        $total_dirs = 0; + +        // one file +        if ($this->file !== null) { +            $total_files = 1; +            $this->chownFile($this->file, $user, $group); +        } + +        // filesets +        foreach($this->filesets as $fs) { + +            $ds = $fs->getDirectoryScanner($this->project); +            $fromDir = $fs->getDir($this->project); + +            $srcFiles = $ds->getIncludedFiles(); +            $srcDirs = $ds->getIncludedDirectories(); + +            $filecount = count($srcFiles); +            $total_files = $total_files + $filecount; +            for ($j = 0; $j < $filecount; $j++) { +                $this->chownFile(new PhingFile($fromDir, $srcFiles[$j]), $user, $group); +            } + +            $dircount = count($srcDirs); +            $total_dirs = $total_dirs + $dircount; +            for ($j = 0; $j <  $dircount; $j++) { +                $this->chownFile(new PhingFile($fromDir, $srcDirs[$j]), $user, $group); +            } +        } + +        if (!$this->verbose) { +            $this->log('Total files changed to ' . $user . ($group ? "." . $group : "") . ': ' . $total_files); +            $this->log('Total directories changed to ' . $user . ($group ? "." . $group : "") . ': ' . $total_dirs); +        } + +    } + +    /** +     * Actually change the mode for the file. +     * @param PhingFile $file +     * @param string $user +     * @param string $group +     */ +    private function chownFile(PhingFile $file, $user, $group = "") { +        if ( !$file->exists() ) { +            throw new BuildException("The file " . $file->__toString() . " does not exist"); +        } + +        try { +            if (!empty($user)) { +                $file->setUser($user); +            } +             +            if (!empty($group)) { +                $file->setGroup($group); +            } +             +            if ($this->verbose) { +                $this->log("Changed file owner on '" . $file->__toString() ."' to " . $user . ($group ? "." . $group : "")); +            } +        } catch (Exception $e) { +            if($this->failonerror) { +                throw $e; +            } else { +                $this->log($e->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); +            } +        } +    } + +} + + diff --git a/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php b/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php index fe6ee60b..040fff8a 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ConditionTask.php 59 2006-04-28 14:49:47Z mrook $   + *  $Id: 31dfd9d24212a4cf5afcce43a9ae337669bafc35 $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,8 +31,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php';   *  ConditionBase.</p>   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.7 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @access    public   *  @package   phing.tasks.system   */ diff --git a/buildscripts/phing/classes/phing/tasks/system/CopyTask.php b/buildscripts/phing/classes/phing/tasks/system/CopyTask.php index c5e4c2a5..2533bb95 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/CopyTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/CopyTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: CopyTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 86322e73609da671413e4c959082958c16a510cc $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -18,7 +18,7 @@   * and is licensed under the LGPL. For more information please see   * <http://phing.info>.   */ - +   require_once 'phing/Task.php';  include_once 'phing/system/io/PhingFile.php';  include_once 'phing/util/FileUtils.php'; @@ -33,27 +33,33 @@ include_once 'phing/mappers/FlattenMapper.php';   * exist. It is possible to explictly overwrite existing files.   *   * @author   Andreas Aderhold, andi@binarycloud.com - * @version  $Revision: 1.16 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @version  $Id: 86322e73609da671413e4c959082958c16a510cc $   * @package  phing.tasks.system   */  class CopyTask extends Task { - +          protected $file          = null;   // the source file (from xml attribute)      protected $destFile      = null;   // the destiantion file (from xml attribute)      protected $destDir       = null;   // the destination dir (from xml attribute)      protected $overwrite     = false;  // overwrite destination (from xml attribute) -    protected $preserveLMT   = true;   // sync timestamps (from xml attribute) +    protected $preserveLMT   = false;   // sync timestamps (from xml attribute)      protected $includeEmpty  = true;   // include empty dirs? (from XML)      protected $flatten       = false;  // apply the FlattenMapper right way (from XML)      protected $mapperElement = null;      protected $fileCopyMap   = array(); // asoc array containing mapped file names      protected $dirCopyMap    = array(); // asoc array containing mapped file names +    protected $completeDirMap= array(); // asoc array containing complete dir names      protected $fileUtils     = null;    // a instance of fileutils      protected $filesets      = array(); // all fileset objects assigned to this task +    protected $filelists     = array(); // all filelist objects assigned to this task      protected $filterChains  = array(); // all filterchains objects assigned to this task -    protected $verbosity     = PROJECT_MSG_VERBOSE; +    protected $verbosity     = Project::MSG_VERBOSE; +     +    protected $mode           = 0755;   // mode to create directories with +     +    protected $haltonerror   = true;    // stop build on errors      /**       * Sets up this object internal stuff. i.e. the Fileutils instance @@ -84,14 +90,21 @@ class CopyTask extends Task {       */      function setVerbose($verbosity) {          if ($verbosity) { -            $this->verbosity = PROJECT_MSG_INFO; +            $this->verbosity = Project::MSG_INFO;          } else { -            $this->verbosity = PROJECT_MSG_VERBOSE; +            $this->verbosity = Project::MSG_VERBOSE;          }      } - +     +    /** +     * @see CopyTask::setPreserveLastModified +     */ +    function setTstamp($bool) { +       $this->setPreserveLastModified($bool);  +    } +          /** -     * Set the preserve timestmap flag. IntrospectionHelper takes care of +     * Set the preserve timestamp flag. IntrospectionHelper takes care of       * booleans in set* methods so we can assume that the right       * value (boolean primitive) is coming in here.       * @@ -99,11 +112,10 @@ class CopyTask extends Task {       * @return void       * @access public       */ -    function setTstamp($bool) { +    function setPreserveLastModified($bool) {          $this->preserveLMT = (boolean) $bool;      } -      /**       * Set the include empty dirs flag. IntrospectionHelper takes care of       * booleans in set* methods so we can assume that the right @@ -127,7 +139,7 @@ class CopyTask extends Task {       * @return void       * @access public       */ -    function setFile(PhingFile $file) { +    function setFile(PhingFile $file) {                  $this->file = $file;      } @@ -141,10 +153,21 @@ class CopyTask extends Task {       * @return void       * @access public       */ -    function setTofile(PhingFile $file) { +    function setTofile(PhingFile $file) {                 $this->destFile = $file;      } +    /** +     * Sets the mode to create destination directories with (ignored on Windows). +     * Default mode is 0755. +     * +     * @param  integer  Octal mode +     * @return void +     * @access public +     */ +    function setMode($mode) { +        $this->mode = (int) base_convert($mode, 8, 10); +    }      /**       * Set the toDir. We have to manually take care of the @@ -155,22 +178,44 @@ class CopyTask extends Task {       * @return void       * @access public       */ -    function setTodir(PhingFile $dir) { +    function setTodir(PhingFile $dir) {                  $this->destDir = $dir;      }      /** +     * Set the haltonerror attribute - when true, will +     * make the build fail when errors are detected. +     * +     * @param  boolean  Flag if the build should be stopped on errors +     * @return void +     * @access public +     */ +    function setHaltonerror($haltonerror) {         +        $this->haltonerror = (boolean) $haltonerror; +    } + +    /**       * Nested creator, creates a FileSet for this task       * -     * @access  public -     * @return  object  The created fileset object +     * @param FileSet $fileset Set of files to copy +     * +     * @return void       */ -    function createFileSet() { -        $num = array_push($this->filesets, new FileSet()); -        return $this->filesets[$num-1]; +    public function addFileSet(FileSet $fs) { +        $this->filesets[] = $fs;      }      /** +     * Nested creator, adds a set of files (nested fileset attribute). +     * +     * @access  public +     * @return  object  The created filelist object +     */ +    function createFileList() { +        $num = array_push($this->filelists, new FileList()); +        return $this->filelists[$num-1]; +    } +    /**       * Creates a filterchain       *       * @access public @@ -204,7 +249,7 @@ class CopyTask extends Task {       * @throws  BuildException       */      function main() { - +              $this->validateAttributes();          if ($this->file !== null) { @@ -219,18 +264,38 @@ class CopyTask extends Task {                  }              } else {                  // terminate build -                throw new BuildException("Could not find file " . $this->file->__toString() . " to copy."); +                $this->logError("Could not find file " . $this->file->__toString() . " to copy.");              }          }          $project = $this->getProject(); +        // process filelists +        foreach($this->filelists as $fl) { +            $fromDir  = $fl->getDir($project); +            $srcFiles = $fl->getFiles($project); +            $srcDirs  = array($fl->getDir($project)); +             +            if (!$this->flatten && $this->mapperElement === null) +            { +                $this->completeDirMap[$fromDir->getAbsolutePath()] = $this->destDir->getAbsolutePath(); +            } +             +            $this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs); +        } +                  // process filesets          foreach($this->filesets as $fs) {              $ds = $fs->getDirectoryScanner($project);              $fromDir  = $fs->getDir($project);              $srcFiles = $ds->getIncludedFiles();              $srcDirs  = $ds->getIncludedDirectories(); +             +            if (!$this->flatten && $this->mapperElement === null) +            { +                $this->completeDirMap[$fromDir->getAbsolutePath()] = $this->destDir->getAbsolutePath(); +            } +                          $this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs);          } @@ -249,10 +314,10 @@ class CopyTask extends Task {       * @return  void       * @throws  BuildException       */ -    private function validateAttributes() { - -        if ($this->file === null && count($this->filesets) === 0) { -            throw new BuildException("CopyTask. Specify at least one source - a file or a fileset."); +    protected function validateAttributes() { +     +        if ($this->file === null && count($this->filesets) === 0 && count($this->filelists) === 0) { +            throw new BuildException("CopyTask. Specify at least one source - a file, fileset or filelist.");          }          if ($this->destFile !== null && $this->destDir !== null) { @@ -295,7 +360,7 @@ class CopyTask extends Task {              $mapper = new IdentityMapper();          }          $this->buildMap($fromDir, $toDir, $files, $mapper, $this->fileCopyMap); -		$this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap); +        $this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap);      }      /** @@ -336,17 +401,41 @@ class CopyTask extends Task {       * @return  void       * @throws  BuildException       */ -    private function doWork() { - -		// These "slots" allow filters to retrieve information about the currently-being-process files -		$fromSlot = $this->getRegisterSlot("currentFromFile"); -		$fromBasenameSlot = $this->getRegisterSlot("currentFromFile.basename"); - -		$toSlot = $this->getRegisterSlot("currentToFile"); -		$toBasenameSlot = $this->getRegisterSlot("currentToFile.basename"); +    protected function doWork() { +         +        // These "slots" allow filters to retrieve information about the currently-being-process files       +        $fromSlot = $this->getRegisterSlot("currentFromFile"); +        $fromBasenameSlot = $this->getRegisterSlot("currentFromFile.basename");  +        $toSlot = $this->getRegisterSlot("currentToFile"); +        $toBasenameSlot = $this->getRegisterSlot("currentToFile.basename");  +                  $mapSize = count($this->fileCopyMap);          $total = $mapSize; + +        // handle empty dirs if appropriate +        if ($this->includeEmpty) { +            $count = 0; +            foreach ($this->dirCopyMap as $srcdir => $destdir) { +                $s = new PhingFile((string) $srcdir); +                $d = new PhingFile((string) $destdir); +                if (!$d->exists()) { +                    if (!$d->mkdirs()) { +                        $this->logError("Unable to create directory " . $d->__toString()); +                    } else { +                        if ($this->preserveLMT) { +                            $d->setLastModified($s->lastModified()); +                        } + +                        $count++; +                    } +                } +            } +            if ($count > 0) { +                $this->log("Created ".$count." empty director" . ($count == 1 ? "y" : "ies") . " in " . $this->destDir->getAbsolutePath()); +            } +        } +          if ($mapSize > 0) {              $this->log("Copying ".$mapSize." file".(($mapSize) === 1 ? '' : 's')." to ". $this->destDir->getAbsolutePath());              // walks the map and actually copies the files @@ -359,42 +448,32 @@ class CopyTask extends Task {                  }                  $this->log("From ".$from." to ".$to, $this->verbosity);                  try { // try to copy file - -					$fromFile = new PhingFile($from); -					$toFile = new PhingFile($to); - +                 +                    $fromFile = new PhingFile($from); +                    $toFile = new PhingFile($to); +                                          $fromSlot->setValue($fromFile->getPath()); -					$fromBasenameSlot->setValue($fromFile->getName()); - -					$toSlot->setValue($toFile->getPath()); -					$toBasenameSlot->setValue($toFile->getName()); - -                    $this->fileUtils->copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject()); +                    $fromBasenameSlot->setValue($fromFile->getName()); +                    $toSlot->setValue($toFile->getPath()); +                    $toBasenameSlot->setValue($toFile->getName()); +                     +                    $this->fileUtils->copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->mode); +                                  $count++;                  } catch (IOException $ioe) { -                    $this->log("Failed to copy " . $from . " to " . $to . ": " . $ioe->getMessage(), PROJECT_MSG_ERR); +                    $this->logError("Failed to copy " . $from . " to " . $to . ": " . $ioe->getMessage());                  }              }          } - -        // handle empty dirs if appropriate -        if ($this->includeEmpty) { -            $e = array_values($this->dirCopyMap); -            $count = 0; -            foreach ($e as $dir) { -                $d = new PhingFile((string) $dir); -                if (!$d->exists()) { -                    if (!$d->mkdirs()) { -                        $this->log("Unable to create directory " . $d->__toString(), PROJECT_MSG_ERR); -                    } else { -                        $count++; -                    } -                } -            } -            if ($count > 0) { -                $this->log("Copied ".$count." empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath()); -            } +    } +     +    protected function logError($message, $location = NULL) +    { +        if ($this->haltonerror) { +            throw new BuildException($message, $location); +        } else { +            $this->log($message, Project::MSG_ERR);          }      } diff --git a/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php b/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php index 0003c50f..87a9b63c 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: CvsPassTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: c1e02a8d43f62c584ba2f1cd5a6f0cc690bceb94 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ include_once 'phing/util/StringHelper.php';   *   * @author Hans Lellelid <hans@xmpl.org> (Phing)   * @author Jeff Martin <jeff@custommonkey.org> (Ant) - * @version $Revision: 1.7 $ + * @version $Id$   * @package phing.tasks.system   */  class CVSPassTask extends Task { @@ -84,9 +84,9 @@ class CVSPassTask extends Task {              throw new BuildException("password is required");          } -        $this->log("cvsRoot: " . $this->cvsRoot, PROJECT_MSG_DEBUG); -        $this->log("password: " . $this->password, PROJECT_MSG_DEBUG); -        $this->log("passFile: " . $this->passFile->__toString(), PROJECT_MSG_DEBUG); +        $this->log("cvsRoot: " . $this->cvsRoot, Project::MSG_DEBUG); +        $this->log("password: " . $this->password, Project::MSG_DEBUG); +        $this->log("passFile: " . $this->passFile->__toString(), Project::MSG_DEBUG);          $reader = null;          $writer = null; @@ -100,14 +100,14 @@ class CVSPassTask extends Task {                  $line = null;                  while (($line = $reader->readLine()) !== null) {                      if (!StringHelper::startsWith($this->cvsRoot, $line)) { -                        $buf .= $line . Phing::getProperty("line.separator"); +                        $buf .= $line . PHP_EOL;                      }                  }              }              $pwdfile = $buf . $this->cvsRoot . " A" . $this->mangle($this->password); -            $this->log("Writing -> " . $pwdfile , PROJECT_MSG_DEBUG); +            $this->log("Writing -> " . $pwdfile , Project::MSG_DEBUG);              $writer = new BufferedWriter(new FileWriter($this->passFile));              $writer->write($pwdfile); diff --git a/buildscripts/phing/classes/phing/tasks/system/CvsTask.php b/buildscripts/phing/classes/phing/tasks/system/CvsTask.php index de2950ec..3c12a597 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/CvsTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/CvsTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: CvsTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 642c6947fa58e02a8c7893c8c4dfab2debfdd51d $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,7 +35,7 @@ include_once 'phing/types/Commandline.php';   * @author stefano@apache.org (Ant)   * @author Wolfgang Werner <wwerner@picturesafe.de> (Ant)   * @author Kevin Ross <kevin.ross@bredex.com> (Ant) - * @version $Revision: 1.14 $ + * @version $Id: 642c6947fa58e02a8c7893c8c4dfab2debfdd51d $   * @package phing.tasks.system   */  class CvsTask extends Task { @@ -155,14 +155,14 @@ class CvsTask extends Task {          if ($this->passFile !== null) {              if ($this->passFile->isFile() && $this->passFile->canRead()) {                              putenv("CVS_PASSFILE=" . $this->passFile->__toString()); -                $this->log("Using cvs passfile: " . $this->passFile->__toString(), PROJECT_MSG_INFO); +                $this->log("Using cvs passfile: " . $this->passFile->__toString(), Project::MSG_INFO);              } elseif (!$this->passFile->canRead()) {                  $this->log("cvs passfile: " . $this->passFile->__toString()  -                    . " ignored as it is not readable", PROJECT_MSG_WARN); +                    . " ignored as it is not readable", Project::MSG_WARN);              } else {                  $this->log("cvs passfile: " . $this->passFile->__toString()                       . " ignored as it is not a file", -                    PROJECT_MSG_WARN); +                    Project::MSG_WARN);              }          } @@ -201,14 +201,14 @@ class CvsTask extends Task {          try {              $actualCommandLine = $toExecuteStr; // we converted to string above -            $this->log($actualCommandLine, PROJECT_MSG_INFO); -            $retCode = $exe->execute(); -            $this->log("retCode=" . $retCode, PROJECT_MSG_DEBUG); +            $this->log($actualCommandLine, Project::MSG_INFO); +            $retCode = $exe->main(); +            $this->log("retCode=" . $retCode, Project::MSG_DEBUG);              /*Throw an exception if cvs exited with error. (Iulian)*/              if ($this->failOnError && $retCode !== 0) {                  throw new BuildException("cvs exited with error code "                                           . $retCode  -                                         . Phing::getProperty("line.separator") +                                         . PHP_EOL                                           . "Command line was ["                                           . $toExecute->describeCommand() . "]", $this->getLocation());              } @@ -216,7 +216,7 @@ class CvsTask extends Task {              if ($this->failOnError) {                  throw new BuildException($e, $this->getLocation());              } else { -                $this->log("Caught exception: " . $e, PROJECT_MSG_WARN); +                $this->log("Caught exception: " . $e, Project::MSG_WARN);              }          } catch (BuildException $e) {              if ($this->failOnError) { @@ -226,13 +226,13 @@ class CvsTask extends Task {                  if ($t === null) {                      $t = $e;                  } -                $this->log("Caught exception: " . $t, PROJECT_MSG_WARN); +                $this->log("Caught exception: " . $t, Project::MSG_WARN);              }          } catch (Exception $e) {              if ($this->failOnError) {                  throw new BuildException($e, $this->getLocation());              } else { -                $this->log("Caught exception: " . $e, PROJECT_MSG_WARN); +                $this->log("Caught exception: " . $e, Project::MSG_WARN);              }          }      } diff --git a/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php b/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php index 00e1e7a7..8af8a632 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: DeleteTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: f25fc4c605ead65db9235c9fe328b2d47b7c8299 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,7 +24,7 @@ require_once 'phing/Task.php';  /**   * Deletes a file or directory, or set of files defined by a fileset.   *  - * @version   $Revision: 1.13 $ + * @version   $Id: f25fc4c605ead65db9235c9fe328b2d47b7c8299 $   * @package   phing.tasks.system   */  class DeleteTask extends Task { @@ -36,11 +36,11 @@ class DeleteTask extends Task {      protected $quiet = false;      protected $failonerror = true; -    protected $verbosity = PROJECT_MSG_VERBOSE; -	 -	/** Any filelists of files that should be deleted. */ +    protected $verbosity = Project::MSG_VERBOSE; +     +    /** Any filelists of files that should be deleted. */      private $filelists = array(); -	 +          /**        * Set the name of a single file to be removed.       * @param PhingFile $file @@ -63,9 +63,9 @@ class DeleteTask extends Task {       */      function setVerbose($verbosity) {          if ($verbosity) { -            $this->verbosity = PROJECT_MSG_INFO; +            $this->verbosity = Project::MSG_INFO;          } else { -            $this->verbosity = PROJECT_MSG_VERBOSE; +            $this->verbosity = Project::MSG_VERBOSE;          }      } @@ -96,12 +96,11 @@ class DeleteTask extends Task {      }      /** Nested creator, adds a set of files (nested fileset attribute). */ -    function createFileSet() { -        $num = array_push($this->filesets, new FileSet()); -        return $this->filesets[$num-1]; +    function addFileSet(FileSet $fs) { +        $this->filesets[] = $fs;      } -	 -	/** Nested creator, adds a set of files (nested fileset attribute). */ +     +    /** Nested creator, adds a set of files (nested fileset attribute). */      function createFileList() {          $num = array_push($this->filelists, new FileList());          return $this->filelists[$num-1]; @@ -131,38 +130,38 @@ class DeleteTask extends Task {                          if($this->failonerror) {                              throw new BuildException($message);                          } else { -                            $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); +                            $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);                          }                                              }                  }              } else { -                $this->log("Could not find file " . $this->file->getAbsolutePath() . " to delete.",PROJECT_MSG_VERBOSE); +                $this->log("Could not find file " . $this->file->getAbsolutePath() . " to delete.",Project::MSG_VERBOSE);              }          }          // delete the directory          if ($this->dir !== null && $this->dir->exists() && $this->dir->isDirectory()) { -            if ($this->verbosity === PROJECT_MSG_VERBOSE) { +            if ($this->verbosity === Project::MSG_VERBOSE) {                  $this->log("Deleting directory " . $this->dir->__toString());              }              $this->removeDir($this->dir);          } -		 -		// delete the files in the filelists -		foreach($this->filelists as $fl) { -			try { -				$files = $fl->getFiles($this->project); -				$this->removeFiles($fl->getDir($this->project), $files, $empty=array()); -			} catch (BuildException $be) { -				// directory doesn't exist or is not readable -					if ($this->failonerror) { -					throw $be; -				} else { -					$this->log($be->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); -				} -			} -		} -			 +         +        // delete the files in the filelists +        foreach($this->filelists as $fl) { +            try { +                $files = $fl->getFiles($this->project); +                $this->removeFiles($fl->getDir($this->project), $files, $empty=array()); +            } catch (BuildException $be) { +                // directory doesn't exist or is not readable +                    if ($this->failonerror) { +                    throw $be; +                } else { +                    $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); +                } +            } +        } +                      // delete the files in the filesets          foreach($this->filesets as $fs) {              try { @@ -175,7 +174,7 @@ class DeleteTask extends Task {                      if ($this->failonerror) {                          throw $be;                      } else { -                        $this->log($be->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); +                        $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);                      }                  }          } @@ -204,7 +203,7 @@ class DeleteTask extends Task {                      if($this->failonerror) {                          throw new BuildException($message);                      } else { -                        $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); +                        $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);                      }                  }                             } @@ -217,7 +216,7 @@ class DeleteTask extends Task {              if($this->failonerror) {                throw new BuildException($message);              } else { -              $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); +              $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);              }          }                     } @@ -242,7 +241,7 @@ class DeleteTask extends Task {                      if($this->failonerror) {                          throw new BuildException($message);                      } else { -                        $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); +                        $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);                      }                  }                @@ -260,11 +259,11 @@ class DeleteTask extends Task {                          $dir->delete();                          $dirCount++;                      } catch (Exception $e) { -                        $message="Unable to delete directory " + $dir; +                        $message="Unable to delete directory " . $dir->__toString();                          if($this->failonerror) {                              throw new BuildException($message);                          } else { -                            $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); +                            $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);                          }                      }                  } diff --git a/buildscripts/phing/classes/phing/tasks/system/EchoTask.php b/buildscripts/phing/classes/phing/tasks/system/EchoTask.php index 229f5130..edc098c4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/EchoTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/EchoTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: EchoTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: c5ebadd12256533d9ca4d6fb6cabd50415bdddbf $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,14 +24,14 @@ include_once 'phing/Task.php';  /**   *  Echos a message to the logging system or to a file   * - *  @author   Michiel Rook <michiel@trendserver.nl> + *  @author   Michiel Rook <mrook@php.net>   *  @author   Andreas Aderhold, andi@binarycloud.com - *  @version  $Revision: 1.5 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + *  @version  $Id$   *  @package  phing.tasks.system   */  class EchoTask extends Task { -	 +          protected $msg = "";      protected $file = ""; @@ -40,54 +40,87 @@ class EchoTask extends Task {      protected $level = "info"; -    function main() {		 -		switch ($this->level) -		{ -			case "error": $loglevel = PROJECT_MSG_ERR; break; -			case "warning": $loglevel = PROJECT_MSG_WARN; break; -			case "info": $loglevel = PROJECT_MSG_INFO; break; -			case "verbose": $loglevel = PROJECT_MSG_VERBOSE; break; -			case "debug": $loglevel = PROJECT_MSG_DEBUG; break; -		} -		 -		if (empty($this->file)) -		{ -        	$this->log($this->msg, $loglevel); -		} -		else -		{ -			if ($this->append) -			{ -				$handle = fopen($this->file, "a"); -			} -			else -			{ -				$handle = fopen($this->file, "w"); -			} -			 -			fwrite($handle, $this->msg); -			 -			fclose($handle); -		} +    protected $filesets = array(); + +    function main() {        +        switch ($this->level) +        { +            case "error": $loglevel = Project::MSG_ERR; break; +            case "warning": $loglevel = Project::MSG_WARN; break; +            case "info": $loglevel = Project::MSG_INFO; break; +            case "verbose": $loglevel = Project::MSG_VERBOSE; break; +            case "debug": $loglevel = Project::MSG_DEBUG; break; +        } + +        if (count($this->filesets)) { +            if (trim(substr($this->msg, -1)) != '') { +                $this->msg .= "\n"; +            } +            $this->msg .= $this->getFilesetsMsg(); +        } +         +        if (empty($this->file)) +        { +            $this->log($this->msg, $loglevel); +        } +        else +        { +            if ($this->append) +            { +                $handle = fopen($this->file, "a"); +            } +            else +            { +                $handle = fopen($this->file, "w"); +            } +             +            fwrite($handle, $this->msg); +             +            fclose($handle); +        } +    } + +    /** +     * Merges all filesets into a string to be echoed out +     * +     * @return string String to echo +     */ +    protected function getFilesetsMsg() +    { +        $project = $this->getProject(); +        $msg = ''; +        foreach ($this->filesets as $fs) { +            $ds = $fs->getDirectoryScanner($project); +            $fromDir  = $fs->getDir($project); +            $srcFiles = $ds->getIncludedFiles(); +            $msg .= 'Directory: ' . $fromDir . ' => ' +                . realpath($fromDir) . "\n"; +            foreach ($srcFiles as $file) { +                $relPath = $fromDir . DIRECTORY_SEPARATOR . $file; +                $msg .= $relPath . "\n"; +            } +        } + +        return $msg;      }      /** setter for file */      function setFile($file)      { -		$this->file = (string) $file; -	} +        $this->file = (string) $file; +    }      /** setter for level */      function setLevel($level)      { -		$this->level = (string) $level; -	} +        $this->level = (string) $level; +    }      /** setter for append */      function setAppend($append)      { -		$this->append = $append; -	} +        $this->append = $append; +    }      /** setter for message */      function setMsg($msg) { @@ -104,4 +137,16 @@ class EchoTask extends Task {      {          $this->msg = (string) $msg;      } + +    /** +     * Adds a fileset to echo the files of +     * +     * @param FileSet $fs Set of files to echo +     * +     * @return void +     */ +    public function addFileSet(FileSet $fs) +    { +        $this->filesets[] = $fs; +    }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/ExecTask.php b/buildscripts/phing/classes/phing/tasks/system/ExecTask.php index 104f7697..f5a57948 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ExecTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ExecTask.php @@ -1,7 +1,7 @@  <?php -/* - *  $Id: ExecTask.php 59 2006-04-28 14:49:47Z mrook $ +/** + *  $Id: 3101d1403eeb4fe4fe8bae729b7d918b303de1cf $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,119 +25,223 @@ require_once 'phing/Task.php';  /**   * Executes a command on the shell.   * - * @author   Andreas Aderhold <andi@binarycloud.com> - * @author   Hans Lellelid <hans@xmpl.org> - * @version  $Revision: 1.17 $ - * @package  phing.tasks.system + * @author  Andreas Aderhold <andi@binarycloud.com> + * @author  Hans Lellelid <hans@xmpl.org> + * @author  Christian Weiske <cweiske@cweiske.de> + * @version $Id: 3101d1403eeb4fe4fe8bae729b7d918b303de1cf $ + * @package phing.tasks.system   */ -class ExecTask extends Task { +class ExecTask extends Task +{      /**       * Command to execute.       * @var string       */      protected $command; -     + +    /** +     * Commandline managing object +     * +     * @var Commandline +     */ +    protected $commandline; +      /**       * Working directory. -     * @var File +     * @var PhingFile       */      protected $dir; -     +      /**       * Operating system.       * @var string       */      protected $os; -     +      /**       * Whether to escape shell command using escapeshellcmd().       * @var boolean       */      protected $escape = false; -     +      /**       * Where to direct output.       * @var File       */      protected $output; -     +      /** -     * Whether to passthru the output +     * Whether to use PHP's passthru() function instead of exec()       * @var boolean       */      protected $passthru = false; + +    /** +     * Whether to log returned output as MSG_INFO instead of MSG_VERBOSE +     * @var boolean +     */ +    protected $logOutput = false;      /** +     * Logging level for status messages +     * @var integer +     */ +    protected $logLevel = Project::MSG_VERBOSE; + +    /**       * Where to direct error output.       * @var File       */      protected $error; -     -	/** -	 * If spawn is set then [unix] programs will redirect stdout and add '&'. -	 * @var boolean -	 */ -	protected $spawn = false; -	 + +    /** +     * If spawn is set then [unix] programs will redirect stdout and add '&'. +     * @var boolean +     */ +    protected $spawn = false; + +    /** +     * Property name to set with return value from exec call. +     * +     * @var string +     */ +    protected $returnProperty; + +    /** +     * Property name to set with output value from exec call. +     * +     * @var string +     */ +    protected $outputProperty; +      /**       * Whether to check the return code.       * @var boolean       */      protected $checkreturn = false; -     + + + +    public function __construct() +    { +        $this->commandline = new Commandline(); +    } +      /**       * Main method: wraps execute() command. +     *       * @return void       */ -    public function main() { -        $this->execute(); +    public function main() +    { +        if (!$this->isApplicable()) { +            return; +        } + +        $this->prepare(); +        $this->buildCommand(); +        list($return, $output) = $this->executeCommand(); +        $this->cleanup($return, $output);      } -     +      /** -     * Executes a program and returns the return code. -     * Output from command is logged at INFO level. -     * @return int Return code from execution. +     * Checks whether the command shall be executed +     * +     * @return boolean False if the exec command shall not be run       */ -    public function execute() { -     -         // test if os match -        $myos = Phing::getProperty("os.name"); -        $this->log("Myos = " . $myos, PROJECT_MSG_VERBOSE); -        if (($this->os !== null) && (strpos($os, $myos) === false)) { +    protected function isApplicable() +    { +        if ($this->os === null) { +            return true; +        } + +        $myos = Phing::getProperty('os.name'); +        $this->log('Myos = ' . $myos, Project::MSG_VERBOSE); + +        if (strpos($this->os, $myos) !== false) {              // this command will be executed only on the specified OS -            $this->log("Not found in " . $os, PROJECT_MSG_VERBOSE); -            return 0; +            // OS matches +            return true;          } -         -         if ($this->dir !== null) { -            if ($this->dir->isDirectory()) { -                $currdir = getcwd(); -                @chdir($this->dir->getPath()); -            } else { -                throw new BuildException("Can't chdir to:" . $this->dir->__toString()); -            } + +        $this->log( +            sprintf( +                'Operating system %s not found in %s', +                $myos, $this->os +            ), +            Project::MSG_VERBOSE +        ); +        return false; +    } + +    /** +     * Prepares the command building and execution, i.e. +     * changes to the specified directory. +     * +     * @return void +     */ +    protected function prepare() +    { +        if ($this->dir === null) { +            return;          } +        // expand any symbolic links first +        if (!$this->dir->getCanonicalFile()->isDirectory()) { +            throw new BuildException( +                "'" . (string) $this->dir . "' is not a valid directory" +            ); +        } +        $this->currdir = getcwd(); +        @chdir($this->dir->getPath()); +    } -        if ($this->escape == true) { -            // FIXME - figure out whether this is correct behavior -            $this->command = escapeshellcmd($this->command); +    /** +     * Builds the full command to execute and stores it in $command. +     * +     * @return void +     * @uses   $command +     */ +    protected function buildCommand() +    { +        if ($this->command === null && $this->commandline->getExecutable() === null) { +            throw new BuildException( +                'ExecTask: Please provide "command" OR "executable"' +            ); +        } else if ($this->command === null) { +            $this->command = Commandline::toString($this->commandline->getCommandline(), $this->escape); +        } else if ($this->commandline->getExecutable() === null) { +            //we need to escape the command only if it's specified directly +            // commandline takes care of "executable" already +            if ($this->escape == true) { +                $this->command = escapeshellcmd($this->command); +            } +        } else { +            throw new BuildException( +                'ExecTask: Either use "command" OR "executable"' +            );          } -         +          if ($this->error !== null) {              $this->command .= ' 2> ' . $this->error->getPath(); -            $this->log("Writing error output to: " . $this->error->getPath()); +            $this->log( +                "Writing error output to: " . $this->error->getPath(), +                $this->logLevel +            );          } -         +          if ($this->output !== null) {              $this->command .= ' 1> ' . $this->output->getPath(); -            $this->log("Writing standard output to: " . $this->output->getPath()); +            $this->log( +                "Writing standard output to: " . $this->output->getPath(), +                $this->logLevel +            );          } elseif ($this->spawn) { -			$this->command .= ' 1>/dev/null'; -			$this->log("Sending ouptut to /dev/null"); -		} -         +            $this->command .= ' 1>/dev/null'; +            $this->log("Sending output to /dev/null", $this->logLevel); +        } +          // If neither output nor error are being written to file          // then we'll redirect error to stdout so that we can dump          // it to screen below. @@ -145,104 +249,268 @@ class ExecTask extends Task {          if ($this->output === null && $this->error === null) {              $this->command .= ' 2>&1';          } -        		 -		// we ignore the spawn boolean for windows -		if ($this->spawn) { -		    $this->command .= ' &'; -		} -		$this->log("Executing command: " . $this->command); -				 +        // we ignore the spawn boolean for windows +        if ($this->spawn) { +            $this->command .= ' &'; +        } +    } + +    /** +     * Executes the command and returns return code and output. +     * +     * @return array array(return code, array with output) +     */ +    protected function executeCommand() +    { +        $this->log("Executing command: " . $this->command, $this->logLevel); +          $output = array();          $return = null; -        exec($this->command, $output, $return); +         +        if ($this->passthru) { +            passthru($this->command, $return); +        } else { +            exec($this->command, $output, $return); +        } +        return array($return, $output); +    } + +    /** +     * Runs all tasks after command execution: +     * - change working directory back +     * - log output +     * - verify return value +     * +     * @param integer $return Return code +     * @param array   $output Array with command output +     * +     * @return void +     */ +    protected function cleanup($return, $output) +    {          if ($this->dir !== null) { -            @chdir($currdir); +            @chdir($this->currdir);          } -        foreach($output as $line) { -            $this->log($line,  ($this->passthru ? PROJECT_MSG_INFO : PROJECT_MSG_VERBOSE)); +        $outloglevel = $this->logOutput ? Project::MSG_INFO : Project::MSG_VERBOSE; +        foreach ($output as $line) { +            $this->log($line, $outloglevel);          } -         -        if($return != 0 && $this->checkreturn) -        { -          throw new BuildException("Task exited with code $return"); + +        if ($this->returnProperty) { +            $this->project->setProperty($this->returnProperty, $return); +        } + +        if ($this->outputProperty) { +            $this->project->setProperty( +                $this->outputProperty, implode("\n", $output) +            ); +        } + +        if ($return != 0 && $this->checkreturn) { +            throw new BuildException("Task exited with code $return");          } -         -        return $return;      } +      /**       * The command to use. +     *       * @param mixed $command String or string-compatible (e.g. w/ __toString()). +     * +     * @return void       */ -    function setCommand($command) { +    public function setCommand($command) +    {          $this->command = "" . $command;      } -     + +    /** +     * The executable to use. +     * +     * @param mixed $executable String or string-compatible (e.g. w/ __toString()). +     * +     * @return void +     */ +    public function setExecutable($executable) +    { +        $this->commandline->setExecutable((string)$executable); +    } +      /**       * Whether to use escapeshellcmd() to escape command. -     * @param boolean $escape +     * +     * @param boolean $escape If the command shall be escaped or not +     * +     * @return void       */ -    function setEscape($escape) { +    public function setEscape($escape) +    {          $this->escape = (bool) $escape;      } -     +      /** -     * Specify the workign directory for executing this command. -     * @param PhingFile $dir +     * Specify the working directory for executing this command. +     * +     * @param PhingFile $dir Working directory +     * +     * @return void       */ -    function setDir(PhingFile $dir) { +    public function setDir(PhingFile $dir) +    {          $this->dir = $dir;      } -     +      /**       * Specify OS (or muliple OS) that must match in order to execute this command. -     * @param string $os +     * +     * @param string $os Operating system string (e.g. "Linux") +     * +     * @return void       */ -    function setOs($os) { +    public function setOs($os) +    {          $this->os = (string) $os;      } -     +      /**       * File to which output should be written. -     * @param PhingFile $output +     * +     * @param PhingFile $f Output log file +     * +     * @return void       */ -    function setOutput(PhingFile $f) { +    public function setOutput(PhingFile $f) +    {          $this->output = $f;      } -     +      /**       * File to which error output should be written. -     * @param PhingFile $output +     * +     * @param PhingFile $f Error log file +     * +     * @return void       */ -    function setError(PhingFile $f) { +    public function setError(PhingFile $f) +    {          $this->error = $f;      } -     +      /** -     * Whether to use passthru the output. -     * @param boolean $passthru +     * Whether to use PHP's passthru() function instead of exec() +     * +     * @param boolean $passthru If passthru shall be used +     * +     * @return void       */ -    function setPassthru($passthru) { +    public function setPassthru($passthru) +    {          $this->passthru = (bool) $passthru;      } -     -	/** -	 * Whether to suppress all output and run in the background. -	 * @param boolean $spawn -	 */ -	function setSpawn($spawn) { -		$this->spawn  = (bool) $spawn; -	} + +    /** +     * Whether to log returned output as MSG_INFO instead of MSG_VERBOSE +     * +     * @param boolean $logOutput If output shall be logged visibly +     * +     * @return void +     */ +    public function setLogoutput($logOutput) +    { +        $this->logOutput = (bool) $logOutput; +    } + +    /** +     * Whether to suppress all output and run in the background. +     * +     * @param boolean $spawn If the command is to be run in the background +     * +     * @return void +     */ +    public function setSpawn($spawn) +    { +        $this->spawn  = (bool) $spawn; +    }      /**       * Whether to check the return code. -     * @param boolean $checkreturn +     * +     * @param boolean $checkreturn If the return code shall be checked +     * +     * @return void +     */ +    public function setCheckreturn($checkreturn) +    { +        $this->checkreturn = (bool) $checkreturn; +    } +     +    /** +     * The name of property to set to return value from exec() call. +     * +     * @param string $prop Property name +     * +     * @return void +     */ +    public function setReturnProperty($prop) +    { +        $this->returnProperty = $prop; +    } + +    /** +     * The name of property to set to output value from exec() call. +     * +     * @param string $prop Property name +     * +     * @return void +     */ +    public function setOutputProperty($prop) +    { +        $this->outputProperty = $prop; +    } +     +    /** +     * Set level of log messages generated (default = verbose) +     * +     * @param string $level Log level +     * +     * @return void +     */ +    public function setLevel($level) +    { +        switch ($level) { +        case 'error': +            $this->logLevel = Project::MSG_ERR; +            break; +        case 'warning': +            $this->logLevel = Project::MSG_WARN; +            break; +        case 'info': +            $this->logLevel = Project::MSG_INFO; +            break; +        case 'verbose': +            $this->logLevel = Project::MSG_VERBOSE; +            break; +        case 'debug': +            $this->logLevel = Project::MSG_DEBUG; +            break; +        default: +            throw new BuildException( +                sprintf('Unknown log level "%s"', $level) +            ); +        } +    } + +    /** +     * Creates a nested <arg> tag. +     * +     * @return CommandlineArgument Argument object       */ -    function setCheckreturn($checkreturn) { -      $this->checkreturn = (bool) $checkreturn; +    public function createArg() +    { +        return $this->commandline->createArgument();      }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/ExitTask.php b/buildscripts/phing/classes/phing/tasks/system/FailTask.php index 7e08d369..92306842 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ExitTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/FailTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ExitTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 260a7f3caa499a33f0d3982f9a5cc9db222475a6 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,10 +27,10 @@ require_once 'phing/Task.php';   *   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Nico Seessle <nico@seessle.de> (Ant) - * @version   $Revision: 1.7 $ + * @version   $Id$   * @package   phing.tasks.system   */ -class ExitTask extends Task {  +class FailTask extends Task {       private $message;      private $ifCondition; diff --git a/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php b/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php index a2a42665..e9b556d3 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ForeachTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 7acb78ab792426fa7d4edec53496cff8da5923eb $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,6 +20,8 @@   */  require_once 'phing/Task.php'; +require_once 'phing/system/io/FileSystem.php'; +include_once 'phing/mappers/FileNameMapper.php';  include_once 'phing/tasks/system/PhingTask.php';  /** @@ -43,7 +45,7 @@ include_once 'phing/tasks/system/PhingTask.php';   *   * @author    Jason Hines <jason@greenhell.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.9 $ + * @version   $Id$   * @package   phing.tasks.system   */  class ForeachTask extends Task { @@ -54,7 +56,10 @@ class ForeachTask extends Task {      /** Name of parameter to pass to callee */      private $param; -    /** Delimter that separates items in $list */ +    /** Name of absolute path parameter to pass to callee */ +    private $absparam; +     +    /** Delimiter that separates items in $list */      private $delimiter = ',';      /** @@ -63,11 +68,36 @@ class ForeachTask extends Task {       */      private $callee; +    /** Array of filesets */ +    private $filesets = array(); +     +    /** Instance of mapper **/ +    private $mapperElement; +     +    /** +     * Array of filelists +     * @var array +     */ +    private $filelists = array(); +          /**       * Target to execute.       * @var string       */      private $calleeTarget; +     +    /** +     * Total number of files processed  +     * @var integer +     */ +    private $total_files = 0; +     +    /** +     * Total number of directories processed  +     * @var integer +     */ +    private $total_dirs  = 0; +          function init() {          $this->callee = $this->project->createTask("phingcall"); @@ -82,11 +112,8 @@ class ForeachTask extends Task {       * @return void       */         function main() { -        if ($this->list === null) { -            throw new BuildException("Missing list to iterate through"); -        } -        if (trim($this->list) === '') { -            return; +        if ($this->list === null && count($this->filesets) == 0 && count($this->filelists) == 0) { +            throw new BuildException("Need either list, nested fileset or nested filelist to iterate through");          }          if ($this->param === null) {              throw new BuildException("You must supply a property name to set on each iteration in param"); @@ -99,15 +126,135 @@ class ForeachTask extends Task {          $callee->setTarget($this->calleeTarget);          $callee->setInheritAll(true);          $callee->setInheritRefs(true); +        $mapper = null; +         +        if ($this->mapperElement !== null) { +            $mapper = $this->mapperElement->getImplementation(); +        } +         +        if (trim($this->list)) { +            $arr = explode($this->delimiter, $this->list); +         +            foreach ($arr as $value) { +                $value = trim($value); +                $premapped = ''; +                if ($mapper !== null) { +                    $premapped = $value; +                    $value = $mapper->main($value); +                    if ($value === null) { +                        continue; +                    } +                    $value = array_shift($value); +                } +                $this->log("Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''), Project::MSG_VERBOSE); +                $prop = $callee->createProperty(); +                $prop->setOverride(true); +                $prop->setName($this->param); +                $prop->setValue($value); +                $callee->main(); +            } +        } + +        // filelists +        foreach ($this->filelists as $fl) { +            $srcFiles = $fl->getFiles($this->project); + +            $this->process($callee, $fl->getDir($this->project), $srcFiles, array()); +        } + +        // filesets +        foreach ($this->filesets as $fs) { +            $ds       = $fs->getDirectoryScanner($this->project); +            $srcFiles = $ds->getIncludedFiles(); +            $srcDirs  = $ds->getIncludedDirectories(); + +            $this->process($callee, $fs->getDir($this->project), $srcFiles, $srcDirs); +        } + +        $this->log("Processed {$this->total_dirs} directories and {$this->total_files} files", Project::MSG_VERBOSE); +    } + +    /** +     * Processes a list of files & directories  +     *  +     * @param Task      $callee +     * @param PhingFile $fromDir +     * @param array     $srcFiles +     * @param array     $srcDirs +     */ +    protected function process(Task $callee, PhingFile $fromDir, $srcFiles, $srcDirs) +    { +        $mapper = null; -        $arr = explode($this->delimiter, $this->list); +        if ($this->mapperElement !== null) { +            $mapper = $this->mapperElement->getImplementation(); +        } +         +        $filecount = count($srcFiles); +        $this->total_files += $filecount; +         +        for ($j = 0; $j < $filecount; $j++) { +            $value = $srcFiles[$j]; +            $premapped = ""; + +            if ($this->absparam) { +                $prop = $callee->createProperty(); +                $prop->setOverride(true); +                $prop->setName($this->absparam); +                $prop->setValue($fromDir . FileSystem::getFileSystem()->getSeparator() . $value); +            } +             +            if ($mapper !== null) { +                $premapped = $value; +                $value = $mapper->main($value); +                if ($value === null) { +                    continue; +                } +                $value = array_shift($value); +            } +             +            if ($this->param) { +                $this->log("Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''), Project::MSG_VERBOSE); +                $prop = $callee->createProperty(); +                $prop->setOverride(true); +                $prop->setName($this->param); +                $prop->setValue($value); +            } + +            $callee->main(); +        } + +        $dircount = count($srcDirs); +        $this->total_dirs += $dircount; -        foreach ($arr as $value) { -            $this->log("Setting param '$this->param' to value '$value'", PROJECT_MSG_VERBOSE); -            $prop = $callee->createProperty(); -            $prop->setOverride(true); -            $prop->setName($this->param); -            $prop->setValue($value); +        for ($j = 0; $j <  $dircount; $j++) { +            $value = $srcDirs[$j]; +            $premapped = ""; + +            if ($this->absparam) { +                $prop = $callee->createProperty(); +                $prop->setOverride(true); +                $prop->setName($this->absparam); +                $prop->setValue($fromDir . FileSystem::getFileSystem()->getSeparator() . $value); +            } +             +            if ($mapper !== null) { +                $premapped = $value; +                $value = $mapper->main($value); +                if ($value === null) { +                    continue; +                } +                $value = array_shift($value); +            } +             +            if ($this->param) { +                $this->log("Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''), Project::MSG_VERBOSE); +                $prop = $callee->createProperty(); +                $prop->setOverride(true); +                $prop->setName($this->param); +                $prop->setValue($value); +            } +              $callee->main();          }      } @@ -124,15 +271,50 @@ class ForeachTask extends Task {          $this->param = (string) $param;      } +    function setAbsparam($absparam) { +        $this->absparam = (string) $absparam; +    } +      function setDelimiter($delimiter) {          $this->delimiter = (string) $delimiter;      }      /** +     * Nested creator, adds a set of files (nested fileset attribute). +     */ +    function createFileSet() { +        $num = array_push($this->filesets, new FileSet()); +        return $this->filesets[$num-1]; +    } + +    /** +     * Nested creator, creates one Mapper for this task +     * +     * @access  public +     * @return  object  The created Mapper type object +     * @throws  BuildException +     */ +    function createMapper() { +        if ($this->mapperElement !== null) { +            throw new BuildException("Cannot define more than one mapper", $this->location); +        } +        $this->mapperElement = new Mapper($this->project); +        return $this->mapperElement; +    } + +    /**       * @return Property       */      function createProperty() {          return $this->callee->createProperty();      } +    /** +     * Supports embedded <filelist> element. +     * @return FileList +     */ +    public function createFileList() { +        $num = array_push($this->filelists, new FileList()); +        return $this->filelists[$num-1]; +    }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/IfTask.php b/buildscripts/phing/classes/phing/tasks/system/IfTask.php index ab773355..cff06ce1 100644 --- a/buildscripts/phing/classes/phing/tasks/system/IfTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/IfTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: IfTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 4452f066ac71d51d3e2521d39cdee2caf4f7e9cc $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -67,7 +67,7 @@ require_once 'phing/tasks/system/SequentialTask.php';   * task before you use it the first time:</p>   *   * <pre><code> - *   <taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" /> + *   <taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" />   * </code></pre>   *   * <h3>Crude Example</h3> @@ -105,6 +105,7 @@ require_once 'phing/tasks/system/SequentialTask.php';   * </code>   *   * @author <a href="mailto:stefan.bodewig@freenet.de">Stefan Bodewig</a> + * @package phing.tasks.system   */  class IfTask extends ConditionBase { @@ -148,16 +149,16 @@ class IfTask extends ConditionBase {      }      public function main() { -	 +              if ($this->countConditions() > 1) {              throw new BuildException("You must not nest more than one condition into <if>");          }          if ($this->countConditions() < 1) {              throw new BuildException("You must nest a condition into <if>");          } -		$conditions = $this->getConditions(); -		$c = $conditions[0]; -		 +        $conditions = $this->getConditions(); +        $c = $conditions[0]; +                  if ($c->evaluate()) {              if ($this->thenTasks != null) {                  $this->thenTasks->main(); @@ -165,8 +166,8 @@ class IfTask extends ConditionBase {          } else {              $done = false;              $sz = count($this->elseIfTasks); -			for($i=0; $i < $sz && !$done; $i++) { -				$ei = $this->elseIfTasks[$i]; +            for($i=0; $i < $sz && !$done; $i++) { +                $ei = $this->elseIfTasks[$i];                  if ($ei->evaluate()) {                      $done = true;                      $ei->main(); @@ -183,6 +184,8 @@ class IfTask extends ConditionBase {  /**   * "Inner" class for IfTask.   * This class has same basic structure as the IfTask, although of course it doesn't support <else> tags. + * + * @package phing.tasks.system   */  class ElseIfTask extends ConditionBase { @@ -194,31 +197,31 @@ class ElseIfTask extends ConditionBase {              }              $this->thenTasks = $t;          } -	 -		/** -		 * @return boolean -		 */ +     +        /** +         * @return boolean +         */          public function evaluate() { -		 +                      if ($this->countConditions() > 1) {                  throw new BuildException("You must not nest more than one condition into <elseif>");              }              if ($this->countConditions() < 1) {                  throw new BuildException("You must nest a condition into <elseif>");              } -			 -			$conditions = $this->getConditions(); -			$c = $conditions[0]; +             +            $conditions = $this->getConditions(); +            $c = $conditions[0];              return $c->evaluate();          } -		 -		/** -		 *  -		 */ +         +        /** +         *  +         */          public function main() {              if ($this->thenTasks != null) {                  $this->thenTasks->main();              }          } -    }
\ No newline at end of file +    } diff --git a/buildscripts/phing/classes/phing/tasks/system/ImportTask.php b/buildscripts/phing/classes/phing/tasks/system/ImportTask.php new file mode 100755 index 00000000..760380eb --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/ImportTask.php @@ -0,0 +1,136 @@ +<?php +/* + *  $Id: 88eafadfcd59c0ce28f122926b7d5706b807a8e3 $ + * + * 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/Task.php'; +require_once 'phing/system/io/FileSystem.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/parser/ProjectConfigurator.php'; + +/** + * Imports another build file into the current project. + * + * Targets and properties of the imported file can be overrridden  + * by targets and properties of the same name declared in the importing file.  + * + * The imported file will have a new synthetic property of  + * "phing.file.<projectname>" declared which gives the full path to the  + * imported file. Additionally each target in the imported file will be  + * declared twice: once with the normal name and once with "<projectname>."  + * prepended. The "<projectname>.<targetname>" synthetic targets allow the  + * importing file a mechanism to call the imported files targets as  + * dependencies or via the <phing> or <phingcall> task mechanisms. + * + * @author Bryan Davis <bpd@keynetics.com> + * @version $Id: 88eafadfcd59c0ce28f122926b7d5706b807a8e3 $ + * @package phing.tasks.system + */ +class ImportTask extends Task { + +  /** +   * @var FileSystem +   */ +  protected $fs; + +  /** +   * @var PhingFile +   */ +  protected $file = null; + +  /** +   * @var bool +   */ +  protected $optional = false; + +  /** +   * Initialize task. +   * @return void +   */ +  public function init () { +    $this->fs = FileSystem::getFileSystem(); +  } //end init + + +  /** +   * Set the file to import. +   * @param string $f Path to file +   * @return void +   */ +  public function setFile ($f) { +    $this->file = $f; +  } + +  /** +   * Is this include optional? +   * @param bool $opt If true, do not stop the build if the file does not  +   * exist +   * @return void +   */ +  public function setOptional ($opt) { +    $this->optional = $opt; +  } + +  /** +   * Parse a Phing build file and copy the properties, tasks, data types and  +   * targets it defines into the current project. +   * +   * @return void +   */ +  public function main () { +    if (!isset($this->file)) { +      throw new BuildException("Missing attribute 'file'"); +    } + +    $file = new PhingFile($this->file); +    if (!$file->isAbsolute()) { +      $file = new PhingFile($this->project->getBasedir(), $this->file); +    } +    if (!$file->exists()) { +      $msg = "Unable to find build file: {$file->getPath()}"; +      if ($this->optional) { +        $this->log($msg . '... skipped'); +        return; +      } else { +        throw new BuildException($msg); +      } +    } + +    $ctx = $this->project->getReference("phing.parsing.context"); +    $cfg = $ctx->getConfigurator(); +    if (null !== $cfg && $cfg->isParsing()) { +      // because there isn't a top level implicit target in phing like there is  +      // in Ant 1.6, we will be called as soon as our xml is parsed. This isn't  +      // really what we want to have happen. Instead we will register ourself  +      // with the parse context to be called at the end of the current file's  +      // parse phase. +      $cfg->delayTaskUntilParseEnd($this); + +    } else { +      // Import xml file into current project scope +      // Since this is delayed until after the importing file has been  +      // processed, the properties and targets of this new file may not take  +      // effect if they have alreday been defined in the outer scope. +      $this->log("Importing configuration from {$file->getName()}", Project::MSG_VERBOSE); +      ProjectConfigurator::configureProject($this->project, $file); +      $this->log("Configuration imported.", Project::MSG_VERBOSE); +    } +  } //end main + +} //end ImportTask diff --git a/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php b/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php index ce9beee5..807a3cad 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: IncludePathTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: eaa0d6c5c7fb908d419cd6e22c7eccbf01506da7 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -34,7 +34,7 @@ include_once 'phing/types/Path.php';   * </code>   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.1 $ + * @version   $Id$   * @package   phing.tasks.system   */  class IncludePathTask extends Task { @@ -107,7 +107,7 @@ class IncludePathTask extends Task {          $new_parts = array_diff($add_parts, $curr_parts);          if ($new_parts) { -            $this->log("Prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts), PROJECT_MSG_VERBOSE); +            $this->log("Prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts), Project::MSG_VERBOSE);              set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));          } diff --git a/buildscripts/phing/classes/phing/tasks/system/InputTask.php b/buildscripts/phing/classes/phing/tasks/system/InputTask.php index a5e1fdb9..3c7168fd 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/InputTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/InputTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: InputTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: ae986f84ca9d952b0e14f2df9f21657213ef5e47 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/input/MultipleChoiceInputRequest.php';   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Ulrich Schmidt <usch@usch.net> (Ant)   * @author    Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version   $Revision: 1.6 $ + * @version   $Id: ae986f84ca9d952b0e14f2df9f21657213ef5e47 $   * @package   phing.tasks.system   */  class InputTask extends Task { @@ -104,6 +104,10 @@ class InputTask extends Task {              throw new BuildException("You must specify a value for propertyName attribute.");          } +        if ($this->message === "") { +            throw new BuildException("You must specify a message for input task."); +        } +                  if ($this->validargs !== null) {              $accept = preg_split('/[\s,]+/', $this->validargs); diff --git a/buildscripts/phing/classes/phing/tasks/system/LoadFileTask.php b/buildscripts/phing/classes/phing/tasks/system/LoadFileTask.php new file mode 100644 index 00000000..ff7b7d3b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/LoadFileTask.php @@ -0,0 +1,119 @@ +<?php +/* + * $Id: d4796a6eb57300eca59f8b6f79e3dbcb08d1e346 $ + * + * 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/Task.php'; + +/** + * LoadFileTask + * + * Loads a (text) file and stores the contents in a property. + * Supports filterchains. + * + * @author  Michiel Rook <mrook@php.net> + * @version $Id: d4796a6eb57300eca59f8b6f79e3dbcb08d1e346 $ + * @package phing.tasks.ext + */ +class LoadFileTask extends Task +{ +    /** +     * File to read +     * @var PhingFile file +     */ +    private $file; + +    /** +     * Property to be set +     * @var string $property +     */ +    private $property; +     +    /** +     * Array of FilterChain objects +     * @var FilterChain[] +     */ +    private $filterChains = array(); + +    /** +     * Set file to read +     * @param PhingFile $file +     */ +    public function setFile($file) +    { +        $this->file = $file; +    } + +    /** +     * Convenience setter to maintain Ant compatibility (@see setFile()) +     * @param PhingFile $file +     */ +    public function setSrcFile($srcFile) +    { +        $this->file = $srcFile; +    } +     +    /** +     * Set name of property to be set +     * @param $property +     * @return void +     */ +    public function setProperty($property) +    { +        $this->property = $property; +    } + +    /** +     * Creates a filterchain +     * +     * @return  object  The created filterchain object +     */ +    function createFilterChain() { +        $num = array_push($this->filterChains, new FilterChain($this->project)); +        return $this->filterChains[$num-1]; +    }                     +     +    /** +     * Main method +     * +     * @return  void +     * @throws  BuildException +     */ +    public function main() +    { +        if (empty($this->file)) { +            throw new BuildException("Attribute 'file' required", $this->getLocation()); +        } +         +        if (empty($this->property)) { +            throw new BuildException("Attribute 'property' required", $this->getLocation()); +        } +         +        // read file (through filterchains) +        $contents = ""; +         +        $reader = FileUtils::getChainedReader(new FileReader($this->file), $this->filterChains, $this->project); +        while(-1 !== ($buffer = $reader->read())) { +            $contents .= $buffer; +        } +        $reader->close(); +         +        // publish as property +        $this->project->setProperty($this->property, $contents); +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php b/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php index c5497fbd..b04be2e1 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: MatchingTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 1e1f6274f400b90c2344c8cdb5d3711030b8f44a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -38,7 +38,7 @@ include_once 'phing/util/DirectoryScanner.php';   * @author    Jon S. Stevens <jon@clearink.com> (Ant   * @author    Stefan Bodewig <stefan.bodewig@epost.de> (Ant)   * @author    Bruce Atherton <bruce@callenish.com> (Ant) - * @version   $Revision: 1.4 $ + * @version   $Id: 1e1f6274f400b90c2344c8cdb5d3711030b8f44a $   * @package   phing.tasks.system   */  abstract class MatchingTask extends Task implements SelectorContainer { @@ -59,7 +59,7 @@ abstract class MatchingTask extends Task implements SelectorContainer {      /**       * @see ProjectComponent::setProject()       */ -    public function setProject(Project $project) { +    public function setProject($project) {          parent::setProject($project);          $this->fileset->setProject($project);      } diff --git a/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php b/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php index 9d5c1f31..934b991f 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: MkdirTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: e7e3dbd896d8d46cd8694fca10d1d9a7b3ce54fc $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,13 +26,19 @@ include_once 'phing/system/io/PhingFile.php';   * Task to create a directory.   *   * @author   Andreas Aderhold, andi@binarycloud.com - * @version  $Revision: 1.8 $ + * @version  $Id$   * @package  phing.tasks.system   */  class MkdirTask extends Task {      /** directory to create*/      private $dir; +     +    /** +     * Mode to create directory with +     * @var integer +     */ +    private $mode = 0755;      /**       * create the directory and all parents @@ -47,7 +53,7 @@ class MkdirTask extends Task {              throw new BuildException("Unable to create directory as a file already exists with that name: " . $this->dir->getAbsolutePath());          }          if (!$this->dir->exists()) { -            $result = $this->dir->mkdirs(); +            $result = $this->dir->mkdirs($this->mode);              if (!$result) {                  $msg = "Directory " . $this->dir->getAbsolutePath() . " creation was not successful for an unknown reason";                  throw new BuildException($msg, $this->location); @@ -60,5 +66,14 @@ class MkdirTask extends Task {      function setDir(PhingFile $dir) {          $this->dir = $dir;      } +     +    /** +     * Sets mode to create directory with +     * @param mixed $mode +     */ +    function setMode($mode) +    { +        $this->mode = base_convert((int) $mode, 8, 10); +    }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/MoveTask.php b/buildscripts/phing/classes/phing/tasks/system/MoveTask.php index a3e94536..e7041464 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/MoveTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/MoveTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: MoveTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 01e6d627d455729bfed47d603188d8c56f54d9e5 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,7 +35,7 @@ include_once 'phing/system/io/IOException.php';   * Source files and directories are only deleted when the file or   * directory has been copied to the destination successfully.   * - * @version $Revision: 1.8 $ + * @version $Id$   * @package phing.tasks.system   */  class MoveTask extends CopyTask { @@ -45,7 +45,58 @@ class MoveTask extends CopyTask {          $this->forceOverwrite = true;      } +    /** +     * Validates attributes coming in from XML +     * +     * @access  private +     * @return  void +     * @throws  BuildException +     */ +    protected function validateAttributes() {     +        if ($this->file !== null && $this->file->isDirectory()) { +            if (($this->destFile !== null && $this->destDir !== null) +                || ($this->destFile === null && $this->destDir === null)) { +                    throw new BuildException("One and only one of tofile and todir must be set."); +            } +             +            if ($this->destFile === null) +            { +                $this->destFile = new PhingFile($this->destDir, $this->file->getName()); +            } +             +            if ($this->destDir === null) +            { +                $this->destDir = $this->destFile->getParentFile(); +            } +             +            $this->completeDirMap[$this->file->getAbsolutePath()] = $this->destFile->getAbsolutePath(); +             +            $this->file = null; +        } else { +            parent::validateAttributes(); +        } +    } +          protected function doWork() { +        if (count($this->completeDirMap) > 0) +        { +            foreach ($this->completeDirMap as $from => $to) +            { +                $f = new PhingFile($from); +                $d = new PhingFile($to); +                 +                $moved = false; +                try { // try to rename                     +                    $this->log("Attempting to rename $from to $to", $this->verbosity); +                    $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->mode); +                    $f->delete(true); +                    $moved = true; +                } catch (IOException $ioe) { +                    $moved = false; +                    $this->logError("Failed to rename $from to $to: " . $ioe->getMessage()); +                } +            } +        }          $copyMapSize = count($this->fileCopyMap);          if ($copyMapSize > 0) { @@ -58,33 +109,18 @@ class MoveTask extends CopyTask {                      continue;                  } -                $moved = false;                  $f = new PhingFile($from);                  $d = new PhingFile($to); -                $moved = false; -                try { // try to rename                     -                    $this->log("Attempting to rename $from to $to", $this->verbosity); -                    $this->renameFile($f, $d, $this->forceOverwrite); -                    $moved = true; -                } catch (IOException $ioe) { -                    $moved = false; -                    $this->log("Failed to rename $from to $to: " . $ioe->getMessage(), $this->verbosity); -                } - -                if (!$moved) {                     -                    try { // try to move -                        $this->log("Moving $from to $to", $this->verbosity); +                try { // try to move +                    $this->log("Moving $from to $to", $this->verbosity); -                        $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject());                         +                    $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->mode); -                        $f = new PhingFile($fromFile); -                        $f->delete(); -                    } catch (IOException $ioe) { -                        $msg = "Failed to move $from to $to: " . $ioe->getMessage(); -                        throw new BuildException($msg, $this->location); -                    } -                } // if !moved +                    $f->delete(); +                } catch (IOException $ioe) { +                    $this->logError("Failed to move $from to $to: " . $ioe->getMessage(), $this->location); +                }              } // foreach fileCopyMap          } // if copyMapSize @@ -96,7 +132,7 @@ class MoveTask extends CopyTask {                  $d = new PhingFile((string) $dir);                  if (!$d->exists()) {                      if (!$d->mkdirs()) { -                        $this->log("Unable to create directory " . $d->getAbsolutePath(), PROJECT_MSG_ERR); +                        $this->logError("Unable to create directory " . $d->getAbsolutePath());                      } else {                          $count++;                      } @@ -160,38 +196,7 @@ class MoveTask extends CopyTask {          try {              $d->delete();          } catch (Exception $e) { -            throw new BuildException("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage()); +            $this->logError("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage());          }      } - -    /** -     * Attempts to rename a file from a source to a destination. -     * If overwrite is set to true, this method overwrites existing file -     * even if the destination file is newer. -     * Otherwise, the source f -     * ile is renamed only if the destination file # -     * is older than it. -     */ -    private function renameFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite) { -        $renamed = true; - -        // ensure that parent dir of dest file exists! -        $parent = $destFile->getParentFile(); -        if ($parent !== null) { -            if (!$parent->exists()) { -                $parent->mkdirs(); -            } -        } -        if ($destFile->exists()) { -            try { -                $destFile->delete(); -            } catch (Exception $e) { -                throw new BuildException("Unable to remove existing file " . $destFile->__toString() . ": " . $e->getMessage()); -            } -        } -        $renamed = $sourceFile->renameTo($destFile); - -        return $renamed; -    }  } -?> diff --git a/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php b/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php index 34d4336d..2aec4db5 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: PhingCallTask.php 59 2006-04-28 14:49:47Z mrook $   - *  + *  $Id: 5d02fa25dc18b56093884ae756b1720aafb42937 $ + *   * 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 @@ -24,7 +24,7 @@ require_once 'phing/Task.php';  /**   * Call another target in the same project.   * - *   <pre> + * <samp>   *    <target name="foo">   *      <phingcall target="bar">   *        <property name="property1" value="aaaaa" /> @@ -35,24 +35,44 @@ require_once 'phing/Task.php';   *    <target name="bar" depends="init">   *      <echo message="prop is ${property1} ${foo}" />   *    </target> - *  </pre> + * </samp>   * - * <p>This only works as expected if neither property1 nor foo are - *  defined in the project itself. + * This only works as expected if neither property1 nor foo are defined in the project itself.   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @copyright 2001,2002 THYRELL. All rights reserved - * @version   $Revision: 1.9 $ + * @version   $Id: 5d02fa25dc18b56093884ae756b1720aafb42937 $   * @access    public   * @package   phing.tasks.system   */  class PhingCallTask extends Task { +    /** +     * The called Phing task. +     * +     * @var PhingTask +     */      private $callee; + +    /** +     * The target to call. +     * +     * @var string +     */      private $subTarget; -    // must match the default value of PhingTask#inheritAll + +    /** +     * Whether to inherit all properties from current project. +     * +     * @var boolean +     */      private $inheritAll = true; -    // must match the default value of PhingTask#inheritRefs + +    /** +     * Whether to inherit refs from current project. +     * +     * @var boolean +     */      private $inheritRefs = false;      /** @@ -67,7 +87,7 @@ class PhingCallTask extends Task {      /**       *  If true, pass all references to the new Phing project.       *  Defaults to false. Future use. -    * +     *       *  @param boolean new value       */      function setInheritRefs($inheritRefs) { @@ -75,6 +95,34 @@ class PhingCallTask extends Task {      }      /** +     * Alias for createProperty +     * @see createProperty() +     */ +    function createParam() { +        if ($this->callee === null) { +            $this->init(); +        } +        return $this->callee->createProperty(); +    } + +    /** +     * Property to pass to the invoked target. +     */ +    function createProperty() { +        if ($this->callee === null) { +            $this->init(); +        } +        return $this->callee->createProperty(); +    } + +    /** +     * Target to execute, required. +     */ +    function setTarget($target) { +        $this->subTarget = (string) $target; +    } + +    /**       *  init this task by creating new instance of the phing task and       *  configuring it's by calling its own init method.       */ @@ -82,6 +130,7 @@ class PhingCallTask extends Task {          $this->callee = $this->project->createTask("phing");          $this->callee->setOwningTarget($this->getOwningTarget());          $this->callee->setTaskName($this->getTaskName()); +        $this->callee->setHaltOnFailure(true);          $this->callee->setLocation($this->getLocation());          $this->callee->init();      } @@ -91,17 +140,17 @@ class PhingCallTask extends Task {       *  @throws BuildException on validation failure or if the target didn't       *  execute       */ -    function main() {         -             -        $this->log("Running PhingCallTask for target '" . $this->subTarget . "'", PROJECT_MSG_DEBUG); +    function main() { + +        $this->log("Running PhingCallTask for target '" . $this->subTarget . "'", Project::MSG_DEBUG);          if ($this->callee === null) {              $this->init();          }          if ($this->subTarget === null) { -            throw new BuildException("Attribute target is required.", $this->location); +            throw new BuildException("Attribute target is required.", $this->getLocation());          } -         +          $this->callee->setPhingfile($this->project->getProperty("phing.file"));          $this->callee->setTarget($this->subTarget);          $this->callee->setInheritAll($this->inheritAll); @@ -109,31 +158,4 @@ class PhingCallTask extends Task {          $this->callee->main();      } -    /** -     * Alias for createProperty -     * @see createProperty() -     */ -    function createParam() { -        if ($this->callee === null) { -            $this->init(); -        } -        return $this->callee->createProperty(); -    } -     -    /** -     * Property to pass to the invoked target. -     */ -    function createProperty() { -        if ($this->callee === null) { -            $this->init(); -        } -        return $this->callee->createProperty(); -    } - -    /** -     * Target to execute, required. -     */ -    function setTarget($target) { -        $this->subTarget = (string) $target; -    }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/PhingTask.php b/buildscripts/phing/classes/phing/tasks/system/PhingTask.php index e9883dd7..6ac0b5ac 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PhingTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PhingTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: PhingTask.php 59 2006-04-28 14:49:47Z mrook $   + *  $Id: 2eec26f6ebaaeceb4eca76644de88bde7515f5dc $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -41,7 +41,7 @@ include_once 'phing/tasks/system/PropertyTask.php';   * </pre>   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.20 $ + * @version   $Id: 2eec26f6ebaaeceb4eca76644de88bde7515f5dc $   * @package   phing.tasks.system   */  class PhingTask extends Task { @@ -151,46 +151,47 @@ class PhingTask extends Task {          }          // if no filesets are given stop here; else process filesets -        if (empty($this->filesets)) {  -            return; -        } -         -        // preserve old settings -        $savedDir = $this->dir; -        $savedPhingFile = $this->phingFile; -        $savedTarget = $this->newTarget; -        $buildFailed = false; - -        // set no specific target for files in filesets -        // [HL] I'm commenting this out; I don't know why this should not be supported! -        // $this->newTarget = null; -         -        foreach($this->filesets as $fs) { - -            $ds = $fs->getDirectoryScanner($this->project); - -            $fromDir  = $fs->getDir($this->project); -            $srcFiles = $ds->getIncludedFiles(); - -            foreach($srcFiles as $fname) {             -                $f = new PhingFile($ds->getbasedir(), $fname); -                $f = $f->getAbsoluteFile(); -                $this->phingFile = $f->getAbsolutePath(); -                $this->dir = $f->getParentFile(); -                $this->processFile();    // run Phing! +        if (!empty($this->filesets)) {  +            // preserve old settings +            $savedDir = $this->dir; +            $savedPhingFile = $this->phingFile; +            $savedTarget = $this->newTarget; +     +            // set no specific target for files in filesets +            // [HL] I'm commenting this out; I don't know why this should not be supported! +            // $this->newTarget = null; +             +            foreach($this->filesets as $fs) { +     +                $ds = $fs->getDirectoryScanner($this->project); +     +                $fromDir  = $fs->getDir($this->project); +                $srcFiles = $ds->getIncludedFiles(); +     +                foreach($srcFiles as $fname) {             +                    $f = new PhingFile($ds->getbasedir(), $fname); +                    $f = $f->getAbsoluteFile(); +                    $this->phingFile = $f->getAbsolutePath(); +                    $this->dir = $f->getParentFile(); +                    $this->processFile();    // run Phing! +                } +            }         +             +            // side effect free programming ;-) +            $this->dir = $savedDir;         +            $this->phingFile = $savedPhingFile; +            $this->newTarget = $savedTarget; +             +            // [HL] change back to correct dir +            if ($this->dir !== null) { +                chdir($this->dir->getAbsolutePath());              } -        }         -         -        // side effect free programming ;-) -        $this->dir = $savedDir;         -        $this->phingFile = $savedPhingFile; -        $this->newTarget = $savedTarget; -         -        // [HL] change back to correct dir -        if ($this->dir !== null) { -            chdir($this->dir->getAbsolutePath());          } +        // Remove any dangling references to help the GC +        foreach ($this->properties as $property) { +            $property->setFallback(null); +        }      }      /** @@ -199,27 +200,49 @@ class PhingTask extends Task {       * @return void       */      private function processFile()  { -             + +        $buildFailed = false;          $savedDir = $this->dir;          $savedPhingFile = $this->phingFile;          $savedTarget = $this->newTarget; +        $savedBasedirAbsPath = null; // this is used to save the basedir *if* we change it +                  try { +                      if ($this->newProject === null) {                  $this->reinit();              } -            if (($this->dir === null) && ($this->inheritAll)) { -                $this->dir = $this->getProject()->getBaseDir(); -            }              $this->initializeProject(); +                          if ($this->dir !== null) { -                $this->newProject->setBaseDir($this->dir); +                 +                $dirAbsPath = $this->dir->getAbsolutePath(); +                 +                // BE CAREFUL! -- when the basedir is changed for a project, +                // all calls to getAbsolutePath() on a relative-path dir will +                // be made relative to the project's basedir!  This means +                // that subsequent calls to $this->dir->getAbsolutePath() will be WRONG! +                 +                // We need to save the current project's basedir first. +                $savedBasedirAbsPath = $this->getProject()->getBasedir()->getAbsolutePath(); +                  +                $this->newProject->setBasedir($this->dir); +                 +                // Now we must reset $this->dir so that it continues to resolve to the same +                // path. +                $this->dir = new PhingFile($dirAbsPath); +                                  if ($savedDir !== null) { // has been set explicitly                      $this->newProject->setInheritedProperty("project.basedir", $this->dir->getAbsolutePath()); -                }                                 +                } +                              } else { -                $this->dir = $this->getProject()->getBaseDir(); +                 +                // Since we're not changing the basedir here (for file resolution), +                // we don't need to worry about any side-effects in this scanrio. +                $this->dir = $this->getProject()->getBasedir();                 }              $this->overrideProperties(); @@ -255,31 +278,37 @@ class PhingTask extends Task {          } catch (Exception $e) {              $buildFailed = true; -            $this->log($e->getMessage(), PROJECT_MSG_ERR); -             -            // important!!! continue on to perform cleanup -            // tasks.     -           } +            $this->log($e->getMessage(), Project::MSG_ERR); +            if (Phing::getMsgOutputLevel() <= Project::MSG_DEBUG) {  +                $lines = explode("\n", $e->getTraceAsString()); +                foreach($lines as $line) { +                    $this->log($line, Project::MSG_DEBUG); +                } +            } +            // important!!! continue on to perform cleanup tasks.     +        } +         +         +        // reset environment values to prevent side-effects. -        //  } finally { -        // restore values (prevent side-effects) -        // !this must match code in catch () {}  block!          $this->newProject = null;          $pkeys = array_keys($this->properties);          foreach($pkeys as $k) {              $this->properties[$k]->setProject(null); -        }         +        } +                  $this->dir = $savedDir;                  $this->phingFile = $savedPhingFile;          $this->newTarget = $savedTarget; -        // [HL] change back to correct dir -        if ($this->dir !== null) { -            chdir($this->dir->getAbsolutePath()); +        // If the basedir for any project was changed, we need to set that back here. +        if ($savedBasedirAbsPath !== null) { +            chdir($savedBasedirAbsPath);          } -        if ($this->haltOnFailure == true && $buildFailed == true) +        if ($this->haltOnFailure && $buildFailed) {              throw new BuildException("Execution of the target buildfile failed. Aborting."); +        }      }      /** @@ -392,7 +421,7 @@ class PhingTask extends Task {                  if (!isset($projReferences[$refid])) {                      $this->log("Parent project doesn't contain any reference '"                          . $refid . "'", -                        PROJECT_MSG_WARN); +                        Project::MSG_WARN);                      continue;                  } @@ -449,8 +478,8 @@ class PhingTask extends Task {              $copy->setProject($this->newProject);          } elseif (in_array('setProject', get_class_methods(get_class($copy)))) {              $copy->setProject($this->newProject); -		} elseif ($copy instanceof Project) { -			// don't copy the old "Project" itself +        } elseif ($copy instanceof Project) { +            // don't copy the old "Project" itself          } else {              $msg = "Error setting new project instance for "                  . "reference with id " . $oldKey; @@ -569,6 +598,8 @@ class PhingTask extends Task {  /**   * Helper class that implements the nested <reference>   * element of <phing> and <phingcall>. + * + * @package   phing.tasks.system   */  class PhingReference extends Reference { diff --git a/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php b/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php index f1b72815..99316f7b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PhpEvalTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 8c46403ac685f362e310ffcceff5d4193bf09ef0 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ require_once 'phing/Task.php';   *        modify internal Phing classes unless you know what you are doing.   *   * @author   Hans Lellelid <hans@xmpl.org> - * @version  $Revision: 1.7 $ + * @version  $Id$   * @package  phing.tasks.system   *   * @todo Add support for evaluating expressions @@ -39,9 +39,27 @@ class PhpEvalTask extends Task {      protected $expression; // Expression to evaluate      protected $function; // Function to execute      protected $class; // Class containing function to execute -    protected $returnProperty; // name of property to set to return value  +    protected $returnProperty = null; // name of property to set to return value       protected $params = array(); // parameters for function calls +    protected $logLevel = Project::MSG_INFO; +     +    /** +     * Set level of log messages generated (default = info) +     * @param string $level +     */ +    public function setLevel($level) +    { +        switch ($level) +        { +            case "error": $this->logLevel = Project::MSG_ERR; break; +            case "warning": $this->logLevel = Project::MSG_WARN; break; +            case "info": $this->logLevel = Project::MSG_INFO; break; +            case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; +            case "debug": $this->logLevel = Project::MSG_DEBUG; break; +        } +    } +          /** Main entry point. */      function main() { @@ -57,15 +75,10 @@ class PhpEvalTask extends Task {              throw new BuildException("You cannot use nested <param> tags when evaluationg a PHP expression.", $this->location);          } -        $retval = null;          if ($this->function !== null) { -            $retval = $this->callFunction();                                     +            $this->callFunction();                                              } elseif ($this->expression !== null) { -            $retval = $this->evalExpression(); -        } -         -        if ($this->returnProperty !== null) { -            $this->project->setProperty($this->returnProperty, $retval); +            $this->evalExpression();          }      } @@ -92,13 +105,16 @@ class PhpEvalTask extends Task {              $params[] = $p->getValue();          } -        $this->log("Calling PHP function: " . $h_func . "()"); +        $this->log("Calling PHP function: " . $h_func . "()", $this->logLevel);          foreach($params as $p) { -            $this->log("  param: " . $p, PROJECT_MSG_VERBOSE); +            $this->log("  param: " . $p, Project::MSG_VERBOSE);          }           $return = call_user_func_array($user_func, $params); -        return $return; +         +        if ($this->returnProperty !== null) { +            $this->project->setProperty($this->returnProperty, $return); +        }      }      /** @@ -106,13 +122,18 @@ class PhpEvalTask extends Task {       * @return mixed       */      protected function evalExpression() { -        $this->log("Evaluating PHP expression: " . $this->expression); +        $this->log("Evaluating PHP expression: " . $this->expression, $this->logLevel);          if (!StringHelper::endsWith(';', trim($this->expression))) {              $this->expression .= ';';          } -        $retval = null; -        eval('$retval = ' . $this->expression); -        return $retval; + +        if ($this->returnProperty !== null) { +            $retval = null; +            eval('$retval = ' . $this->expression); +            $this->project->setProperty($this->returnProperty, $retval); +        } else { +            eval($this->expression); +        }      }      /** Set function to execute */ @@ -150,6 +171,8 @@ class PhpEvalTask extends Task {  /**   * Supports the <param> nested tag for PhpTask. + * + * @package  phing.tasks.system   */  class FunctionParam { diff --git a/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php b/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php index e7e12f33..7a337764 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PropertyPromptTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: d2de9371732599b179facb97ef937b2cfbfbead2 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,39 +31,63 @@ include_once 'phing/system/io/ConsoleReader.php';   *    * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Anthony J. Young-Garner <ajyoung@alum.mit.edu> (Ant) - * @version   $Revision: 1.4 $ + * @version   $Id$   * @package   phing.tasks.system   * @deprecated - in favor of the more capable InputTask   */   class PropertyPromptTask extends Task { - +     +    /** +     * The property name to set with the output. +     * @var string +     */      private $propertyName;        // required +     +    /** +     * The default value to use if no input is entered. +     * @var string +     */      private $defaultValue; -    private $proposedValue;        // required -    private $promptText;        // required +     +    /** +     * The entered value. +     * @var string +     */ +    private $proposedValue; +     +    /** +     * The text to use for the prompt. +     * @var string +     */ +    private $promptText; +     +    /** +     * The character to put after the text. +     * @var string +     */      private $promptCharacter; -    private $useExistingValue; - +          /** -     * Sets the prompt text that will be presented to the user. -     * @param string $prompt -     * @return void +     *        */ -    public function addText($prompt) { -        $this->setPromptText($prompt); -    } +    private $useExistingValue;      /**       * Run the PropertyPrompt task.       * @throws BuildException       */      public function main() { +                  $this->proposedValue = $this->project->getProperty($this->propertyName);          $currentValue = $this->defaultValue; -        if ($currentValue == "" && $this->proposedValue !== null) { $currentValue = $this->proposedValue; } -        if (! (($this->useExistingValue === true) && ($this->proposedValue !== null))) { +         +        if ($currentValue == "" && $this->proposedValue !== null) { +                $currentValue = $this->proposedValue; +        } +         +        if ($this->useExistingValue !== true || $this->proposedValue === null) { -            $this->log("Prompting user for " . $this->propertyName . ". " . $this->getDefaultMessage(), PROJECT_MSG_VERBOSE); +            $this->log("Prompting user for " . $this->propertyName . ". " . $this->getDefaultMessage(), Project::MSG_VERBOSE);              print "\n" . $this->promptText . " [" . $currentValue . "] " . $this->promptCharacter . " "; @@ -77,12 +101,12 @@ class PropertyPromptTask extends Task {                  $this->proposedValue = $this->defaultValue;              } -            if (empty($this->proposedValue)) { -                $this->log("No value specified, using default.", PROJECT_MSG_VERBOSE); +            if ($this->proposedValue === "") { +                $this->log("No value specified, using default.", Project::MSG_VERBOSE);                  $this->proposedValue = $this->defaultValue;              } -            if (!empty($this->proposedValue)) {                     +            if (isset($this->proposedValue)) {                                      $this->project->setProperty($this->propertyName, $this->proposedValue);              } @@ -166,7 +190,7 @@ class PropertyPromptTask extends Task {      /**       * Sets the terminating character used to        * punctuate the prompt text (default is "?"). -     * @param newPromptcharacter java.lang.String +     * @param string $newPromptcharacter       */      public function setPromptCharacter($newPromptcharacter) {          $this->promptCharacter = $newPromptcharacter; @@ -174,7 +198,7 @@ class PropertyPromptTask extends Task {      /**       * Sets text of the prompt. -     * @param newPrompttext java.lang.String +     * @param string $newPrompttext       */      public function setPromptText($newPrompttext) {          $this->promptText = $newPrompttext; @@ -191,11 +215,20 @@ class PropertyPromptTask extends Task {      /**       *  -     *  -     * @param boolean newUseExistingValue +     * @param boolean $newUseExistingValue       */      public function setUseExistingValue($newUseExistingValue) {          $this->useExistingValue = $newUseExistingValue;      } +    /** +     * Sets the prompt text that will be presented to the user. +     * @param string $prompt +     * @return void +     */ +    public function addText($prompt) { +        $this->setPromptText($prompt); +    } +     +      } diff --git a/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php b/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php index d6168e44..0d8854c8 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: PropertyTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: e6d7123b6331d5032ad1e67967cf54ef2aae3f7f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@ include_once 'phing/system/util/Properties.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision$ + * @version   $Id: e6d7123b6331d5032ad1e67967cf54ef2aae3f7f $   * @package   phing.tasks.system   */  class PropertyTask extends Task { @@ -71,15 +71,15 @@ class PropertyTask extends Task {      function setValue($value) {          $this->value = (string) $value;      } -	 -	/** -	 * Sets value of property to CDATA tag contents. -	 * @param string $values -	 * @since 2.2.0 -	 */ -	public function addText($value) { -		$this->setValue($value); -	} +     +    /** +     * Sets value of property to CDATA tag contents. +     * @param string $values +     * @since 2.2.0 +     */ +    public function addText($value) { +        $this->setValue($value); +    }      /** Get the value of current property component. */      function getValue() { @@ -182,9 +182,9 @@ class PropertyTask extends Task {          return (string) $this->value;      } -	/** -	 * @param Project $p -	 */ +    /** +     * @param Project $p +     */      function setFallback($p) {          $this->fallback = $p;      } @@ -248,7 +248,7 @@ class PropertyTask extends Task {          if ( substr($prefix, strlen($prefix)-1) == '.' ) {              $prefix .= ".";          } -        $this->log("Loading Environment $prefix", PROJECT_MSG_VERBOSE); +        $this->log("Loading Environment $prefix", Project::MSG_VERBOSE);          foreach($_ENV as $key => $value) {              $props->setProperty($prefix . '.' . $key, $value);          } @@ -281,7 +281,7 @@ class PropertyTask extends Task {              if ($this->project->getUserProperty($name) === null || $this->override) {                  $this->project->setInheritedProperty($name, $value);              } else { -                $this->log("Override ignored for " . $name, PROJECT_MSG_VERBOSE); +                $this->log("Override ignored for " . $name, Project::MSG_VERBOSE);              }          } else {              if ($this->override) { @@ -298,13 +298,13 @@ class PropertyTask extends Task {       */      protected function loadFile(PhingFile $file) {          $props = new Properties(); -        $this->log("Loading ". $file->getAbsolutePath(), PROJECT_MSG_INFO); +        $this->log("Loading ". $file->getAbsolutePath(), Project::MSG_INFO);          try { // try to load file              if ($file->exists()) {                  $props->load($file);                  $this->addProperties($props);              } else { -                $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", PROJECT_MSG_WARN); +                $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", Project::MSG_WARN);              }          } catch (IOException $ioe) {              throw new BuildException("Could not load properties from file.", $ioe); @@ -356,7 +356,7 @@ class PropertyTask extends Task {                              if ($propertyName === $name) {                                  // Should we maybe just log this as an error & move on? -                                // $this->log("Property ".$name." was circularly defined.", PROJECT_MSG_ERR); +                                // $this->log("Property ".$name." was circularly defined.", Project::MSG_ERR);                                  throw new BuildException("Property ".$name." was circularly defined.");                              } @@ -373,7 +373,7 @@ class PropertyTask extends Task {                          $sb .= $fragment;                      } -                    $this->log("Resolved Property \"$value\" to \"$sb\"", PROJECT_MSG_DEBUG); +                    $this->log("Resolved Property \"$value\" to \"$sb\"", Project::MSG_DEBUG);                      $value = $sb;                                          $props->setProperty($name, $value); diff --git a/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php b/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php index dc7cfeb7..d49c47f2 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ReflexiveTask.php 59 2006-04-28 14:49:47Z mrook $   + *  $Id: 3dcb1ad6e9fd3b2801c1fe3bcbaf2fcab8ea6018 $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -43,7 +43,7 @@ require_once 'phing/Task.php';   * </code>   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.11 $ + * @version   $Id$   * @package   phing.tasks.system   */  class ReflexiveTask extends Task { @@ -105,24 +105,24 @@ class ReflexiveTask extends Task {                          $files[] = new PhingFile($dir, $fname);                      }                  } catch (BuildException $be) { -                    $this->log($be->getMessage(), PROJECT_MSG_WARN); +                    $this->log($be->getMessage(), Project::MSG_WARN);                  }              }                                  }          $this->log("Applying reflexive processing to " . count($files) . " files."); -		// These "slots" allow filters to retrieve information about the currently-being-process files		 -		$slot = $this->getRegisterSlot("currentFile"); -		$basenameSlot = $this->getRegisterSlot("currentFile.basename");	 +        // These "slots" allow filters to retrieve information about the currently-being-process files       +        $slot = $this->getRegisterSlot("currentFile"); +        $basenameSlot = $this->getRegisterSlot("currentFile.basename");           foreach($files as $file) { -			// set the register slots -			 -			$slot->setValue($file->getPath()); -			$basenameSlot->setValue($file->getName()); -			 +            // set the register slots +             +            $slot->setValue($file->getPath()); +            $basenameSlot->setValue($file->getName()); +                          // 1) read contents of file, pulling through any filters              $in = null;              try {                 @@ -134,7 +134,7 @@ class ReflexiveTask extends Task {                  $in->close();              } catch (Exception $e) {                  if ($in) $in->close(); -                $this->log("Erorr reading file: " . $e->getMessage(), PROJECT_MSG_WARN); +                $this->log("Erorr reading file: " . $e->getMessage(), Project::MSG_WARN);              }              try { @@ -142,14 +142,14 @@ class ReflexiveTask extends Task {                  $out = new FileWriter($file);                  $out->write($contents);                  $out->close(); -                $this->log("Applying reflexive processing to " . $file->getPath(), PROJECT_MSG_VERBOSE); +                $this->log("Applying reflexive processing to " . $file->getPath(), Project::MSG_VERBOSE);              } catch (Exception $e) {                  if ($out) $out->close(); -                $this->log("Error writing file back: " . $e->getMessage(), PROJECT_MSG_WARN); +                $this->log("Error writing file back: " . $e->getMessage(), Project::MSG_WARN);              }          }      }    -}
\ No newline at end of file +} diff --git a/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php b/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php index b468afb5..bdd707a2 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ResolvePathTask.php 59 2006-04-28 14:49:47Z mrook $   + *  $Id: 9635ed3f6605f5ed64b74e85731dbcd3ad43ce0f $     *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -39,7 +39,7 @@ require_once 'phing/Task.php';   *      - Possibly integrate this with PackageAsPath, for handling/resolving dot-path paths.   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.6 $ + * @version   $Id$   * @package   phing.tasks.system   */  class ResolvePathTask extends Task { @@ -54,6 +54,11 @@ class ResolvePathTask extends Task {      private $dir;      /** +     * Log level +     */ +    private $logLevel = Project::MSG_VERBOSE; +     +    /**       * Set the name of the property to set.       * @param string $v Property name       * @return void @@ -90,6 +95,38 @@ class ResolvePathTask extends Task {      }      /** +     * Set level of log messages generated (default = verbose) +     * +     * @param string $level Log level +     * +     * @return void +     */ +    public function setLevel($level) +    { +        switch ($level) { +        case 'error': +            $this->logLevel = Project::MSG_ERR; +            break; +        case 'warning': +            $this->logLevel = Project::MSG_WARN; +            break; +        case 'info': +            $this->logLevel = Project::MSG_INFO; +            break; +        case 'verbose': +            $this->logLevel = Project::MSG_VERBOSE; +            break; +        case 'debug': +            $this->logLevel = Project::MSG_DEBUG; +            break; +        default: +            throw new BuildException( +                sprintf('Unknown log level "%s"', $level) +            ); +        } +    } + +    /**       * Perform the resolution & set property.       */      public function main() {         @@ -103,11 +140,11 @@ class ResolvePathTask extends Task {              throw new BuildException("You must specify a path to resolve", $this->getLocation());          } -		$fs = FileSystem::getFileSystem(); -		 +        $fs = FileSystem::getFileSystem(); +                  // if dir attribute was specified then we should          // use that as basedir to which file was relative. -		// -- unless the file specified is an absolute path +        // -- unless the file specified is an absolute path          if ($this->dir !== null && !$fs->isAbsolute(new PhingFile($this->file))) {              $resolved = new PhingFile($this->dir->getPath(), $this->file);          } else { @@ -115,7 +152,7 @@ class ResolvePathTask extends Task {              $resolved = $this->project->resolveFile($this->file);          } -        $this->log("Resolved " . $this->file . " to " . $resolved->getAbsolutePath(), PROJECT_MSG_INFO); +        $this->log("Resolved " . $this->file . " to " . $resolved->getAbsolutePath(), $this->logLevel);          $this->project->setProperty($this->propertyName, $resolved->getAbsolutePath());      } diff --git a/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php b/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php index 50327e3f..d080deda 100644 --- a/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: SequentialTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: e6be0ff54ade0fb900d101759d8788590e769831 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,11 +31,12 @@ require_once 'phing/TaskContainer.php';   * sequential task.   *   * @since 2.1.2 + * @package phing.tasks.system   */  class SequentialTask extends Task implements TaskContainer {      /** Optional Vector holding the nested tasks */ -    private $nestedTasks = array(); +    protected $nestedTasks = array();      /**       * Add a nested task to Sequential. @@ -50,8 +51,8 @@ class SequentialTask extends Task implements TaskContainer {       * @throws BuildException if one of the nested tasks fails.       */      public function main() { -		foreach($this->nestedTasks as $task) { -			$task->perform(); -		} +        foreach($this->nestedTasks as $task) { +            $task->perform(); +        }      }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php b/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php index 4a90e106..84552d69 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: TaskdefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: df52def0bb44ce1b0909f5e8858e79b2ef88ca0f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,6 +21,7 @@   */  require_once 'phing/Task.php'; +include_once 'phing/system/io/PhingFile.php';  /**   * Register a task for use within a buildfile. @@ -42,7 +43,7 @@ require_once 'phing/Task.php';   *      (right now these are just too simple to really justify creating an abstract class)   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.11 $ + * @version   $Id: df52def0bb44ce1b0909f5e8858e79b2ef88ca0f $   * @package   phing.tasks.system   */  class TaskdefTask extends Task { @@ -68,11 +69,17 @@ class TaskdefTask extends Task {       * Refid to already defined classpath       */      private $classpathId; + +    /** +     * Name of file to load multiple definitions from. +     * @var string +     */ +    private $typeFile;      /**       * Set the classpath to be used when searching for component being defined       *  -     * @param Path $classpath An Path object containing the classpath. +     * @param Path $classpath A Path object containing the classpath.       */      public function setClasspath(Path $classpath) {          if ($this->classpath === null) { @@ -84,6 +91,8 @@ class TaskdefTask extends Task {      /**       * Create the classpath to be used when searching for component being defined +     *  +     * @return Path       */       public function createClasspath() {          if ($this->classpath === null) { @@ -116,12 +125,41 @@ class TaskdefTask extends Task {          $this->classname = $class;      } +    /** +     * Sets the file of definitionas to use to use. +     * @param string $file +     */ +    public function setFile($file) { +        $this->typeFile = $file; +    } +          /** Main entry point */      public function main() { -        if ($this->name === null || $this->classname === null) { +        if ($this->typeFile === null &&  +            ($this->name === null || $this->classname === null)) {              throw new BuildException("You must specify name and class attributes for <taskdef>.");          } -        $this->log("Task " . $this->name . " will be handled by class " . $this->classname, PROJECT_MSG_VERBOSE); -        $this->project->addTaskDefinition($this->name, $this->classname, $this->classpath); +        if ($this->typeFile == null) { +            $this->log("Task " . $this->name . " will be handled by class " . $this->classname, Project::MSG_VERBOSE); +            $this->project->addTaskDefinition($this->name, $this->classname, $this->classpath); +        } else { +            try { // try to load taskdefs given in file +                $props = new Properties(); +                $in = new PhingFile((string) $this->typeFile); + +                if ($in === null) { +                    throw new BuildException("Can't load task list {$this->typeFile}"); +                } +                $props->load($in); + +                $enum = $props->propertyNames(); +                foreach($enum as $key) { +                    $value = $props->getProperty($key); +                    $this->project->addTaskDefinition($key, $value, $this->classpath); +                } +            } catch (IOException $ioe) { +                throw new BuildException("Can't load task list {$this->typeFile}"); +            } +        }      }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/TouchTask.php b/buildscripts/phing/classes/phing/tasks/system/TouchTask.php index 6c6c4080..3c45d0d3 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TouchTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TouchTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TouchTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: e581b40ff4e3eac5f62a32b48b4a22285cbc51c1 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/system/io/IOException.php';   *   * If the file to touch doesn't exist, an empty one is created.   * - * @version $Revision: 1.12 $ + * @version $Id$   * @package phing.tasks.system   */  class TouchTask extends Task { @@ -117,7 +117,7 @@ class TouchTask extends Task {      function _touch() {          if ($this->file !== null) {              if (!$this->file->exists()) { -                $this->log("Creating " . $this->file->__toString(), PROJECT_MSG_INFO); +                $this->log("Creating " . $this->file->__toString(), Project::MSG_INFO);                  try { // try to create file                      $this->file->createNewFile();                  } catch(IOException  $ioe) { diff --git a/buildscripts/phing/classes/phing/tasks/system/TryCatchTask.php b/buildscripts/phing/classes/phing/tasks/system/TryCatchTask.php new file mode 100644 index 00000000..b27d829b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/TryCatchTask.php @@ -0,0 +1,123 @@ +<?php +/* + *  $Id: acc9e5d431141ae13ea43c1ed1d3177a4fb60bf9 $ + * + * 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>. + */ +  +include_once 'phing/Task.php'; + +/** + * A wrapper task that lets you run tasks(s) when another set + * of tasks fails. + * + * Inspired by {@link http://ant-contrib.sourceforge.net/tasks/tasks/trycatch.html} + * + * @author   Michiel Rook <mrook@php.net> + * @version  $Id: acc9e5d431141ae13ea43c1ed1d3177a4fb60bf9 $ + * @package  phing.tasks.system + */ +class TryCatchTask extends Task +{ +    protected $propertyName = ""; +     +    protected $tryContainer = null; +    protected $catchContainer = null; +    protected $finallyContainer = null; + +    /** +     * Main method +     * +     * @throws BuildException +     * @return void +     */     +    public function main() +    { +        $exc = null; +         +        if (empty($this->tryContainer)) { +            throw new BuildException('A nested <try> element is required'); +        } +         +        try { +            $this->tryContainer->perform(); +        } catch (BuildException $e) { +            if (!empty($this->propertyName)) { +                $this->project->setProperty($this->propertyName, $e->getMessage()); +            } +             +            if (!empty($this->referenceName)) { +                $this->project->addReference($this->referenceName, $e); +            } +             +            if (!empty($this->catchContainer)) { +                $this->catchContainer->perform(); +            } else { +                $exc = $e; +            } +        } +         +        if (!empty($this->finallyContainer)) { +            $this->finallyContainer->perform(); +        } +         +        if (!empty($exc)) { +            throw $exc; +        } +    } + +    /** +     * Sets the name of the property that will +     * contain the exception message. +     * +     * @param string $property +     */ +    public function setProperty($property) +    { +        $this->propertyName = (string) $property; +    } +     +    /** +     * Add nested <try> element +     * +     * @param SequentialTask $container +     */ +    public function addTry(SequentialTask $container) +    { +        $this->tryContainer = $container; +    } + +    /** +     * Add nested <catch> element +     * +     * @param SequentialTask $container +     */ +    public function addCatch(SequentialTask $container) +    { +        $this->catchContainer = $container; +    } + +    /** +     * Add nested <finally> element +     * +     * @param SequentialTask $container +     */ +    public function addFinally(SequentialTask $container) +    { +        $this->finallyContainer = $container; +    } +} diff --git a/buildscripts/phing/classes/phing/tasks/system/TstampTask.php b/buildscripts/phing/classes/phing/tasks/system/TstampTask.php index 9341c3dd..44f2c3f0 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TstampTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TstampTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TstampTask.php 58 2006-04-28 14:41:04Z mrook $ + *  $Id: c0693134153e6095ab198edb5cf204f53bb7ba69 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,41 +27,41 @@ require_once 'phing/Task.php';   *   * Based on Ant's Tstamp task.   *  - * @author   Michiel Rook <michiel@trendserver.nl> - * @version  $Revision: 1.6 $ + * @author   Michiel Rook <mrook@php.net> + * @version  $Id$   * @package  phing.tasks.system   * @since    2.2.0   */  class TstampTask extends Task  { -	private $customFormats = array(); -	 -	private $prefix = ""; -	 -	/** -	 * Set a prefix for the properties. If the prefix does not end with a "." -	 * one is automatically added. -	 * @param prefix the prefix to use. -	 */ -	public function setPrefix($prefix) -	{ -		$this->prefix = $prefix; -		 -		if (!empty($this->prefix)) -		{ -			$this->prefix.= "."; -		} -	} -	 +    private $customFormats = array(); +     +    private $prefix = ""; +     +    /** +     * Set a prefix for the properties. If the prefix does not end with a "." +     * one is automatically added. +     * @param prefix the prefix to use. +     */ +    public function setPrefix($prefix) +    { +        $this->prefix = $prefix; +         +        if (!empty($this->prefix)) +        { +            $this->prefix.= "."; +        } +    } +          /**       * Adds a custom format       * -	 * @param TstampCustomFormat custom format +     * @param TstampCustomFormat custom format       */ -	public function addFormat(TstampCustomFormat $cf) -	{ -		$this->customFormats[] = $cf; -	} +    public function addFormat(TstampCustomFormat $cf) +    { +        $this->customFormats[] = $cf; +    }      /**       * Create the timestamps. Custom ones are done before @@ -71,21 +71,21 @@ class TstampTask extends Task       */      public function main()      { -		foreach ($this->customFormats as $cf) -		{ -			$cf->execute($this); -		} -		 -		$dstamp = strftime('%Y%m%d'); -		$this->prefixProperty('DSTAMP', $dstamp); -		 -		$tstamp = strftime('%H%M'); -		$this->prefixProperty('TSTAMP', $tstamp); -		 -		$today = strftime('%B %d %Y'); -		$this->prefixProperty('TODAY', $today); -	} -	 +        foreach ($this->customFormats as $cf) +        { +            $cf->execute($this); +        } +         +        $dstamp = strftime('%Y%m%d'); +        $this->prefixProperty('DSTAMP', $dstamp); +         +        $tstamp = strftime('%H%M'); +        $this->prefixProperty('TSTAMP', $tstamp); +         +        $today = strftime('%B %d %Y'); +        $this->prefixProperty('TODAY', $today); +    } +          /**       * helper that encapsulates prefix logic and property setting       * policy (i.e. we use setNewProperty instead of setProperty). @@ -96,73 +96,76 @@ class TstampTask extends Task      }  } +/** + * @package  phing.tasks.system + */  class TstampCustomFormat  { -	private $propertyName = ""; -	private $pattern = ""; -	private $locale = ""; -	 -	/** -	 * The property to receive the date/time string in the given pattern -	 * -	 * @param propertyName the name of the property. -	 */ -	public function setProperty($propertyName) -	{ -		$this->propertyName = $propertyName; -	} +    private $propertyName = ""; +    private $pattern = ""; +    private $locale = ""; +     +    /** +     * The property to receive the date/time string in the given pattern +     * +     * @param propertyName the name of the property. +     */ +    public function setProperty($propertyName) +    { +        $this->propertyName = $propertyName; +    } -	/** -	 * The date/time pattern to be used. The values are as -	 * defined by the PHP strftime() function. -	 * -	 * @param pattern -	 */ -	public function setPattern($pattern) -	{ -		$this->pattern = $pattern; -	} -	 -	/** -	 * The locale used to create date/time string. -	 * -	 * @param locale -	 */ -	public function setLocale($locale) -	{ -		$this->locale = $locale; -	} -	 -	/** -	 * validate parameter and execute the format. -	 * -	 * @param TstampTask reference to task -	 */ -	public function execute(TstampTask $tstamp) -	{ -		if (empty($this->propertyName)) -		{ -			throw new BuildException("property attribute must be provided"); -		} +    /** +     * The date/time pattern to be used. The values are as +     * defined by the PHP strftime() function. +     * +     * @param pattern +     */ +    public function setPattern($pattern) +    { +        $this->pattern = $pattern; +    } +     +    /** +     * The locale used to create date/time string. +     * +     * @param locale +     */ +    public function setLocale($locale) +    { +        $this->locale = $locale; +    } +     +    /** +     * validate parameter and execute the format. +     * +     * @param TstampTask reference to task +     */ +    public function execute(TstampTask $tstamp) +    { +        if (empty($this->propertyName)) +        { +            throw new BuildException("property attribute must be provided"); +        } -		if (empty($this->pattern)) -		{ -			throw new BuildException("pattern attribute must be provided"); -		} -		 -		if (!empty($this->locale)) -		{ -			setlocale(LC_ALL, $this->locale); -		} -		 -		$value = strftime($this->pattern); -		$tstamp->prefixProperty($this->propertyName, $value); -		 -		if (!empty($this->locale)) -		{ -			// reset locale -			setlocale(LC_ALL, NULL); -		} -	} +        if (empty($this->pattern)) +        { +            throw new BuildException("pattern attribute must be provided"); +        } +         +        if (!empty($this->locale)) +        { +            setlocale(LC_ALL, $this->locale); +        } +         +        $value = strftime($this->pattern); +        $tstamp->prefixProperty($this->propertyName, $value); +         +        if (!empty($this->locale)) +        { +            // reset locale +            setlocale(LC_ALL, NULL); +        } +    }  } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php b/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php index de058c90..c03e716d 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TypedefTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 6122dcb36b79ffe3c3fb430a0b4586d9d145410b $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -43,7 +43,7 @@ require_once 'phing/Task.php';   *      (right now these are just too simple to really justify creating an abstract class)   *    * @author    Hans Lellelid <hans@xmpl.org> - * @version   $Revision: 1.7 $ + * @version   $Id$   * @package   phing.tasks.system   */  class TypedefTask extends Task { @@ -71,7 +71,7 @@ class TypedefTask extends Task {      /**       * Set the classpath to be used when searching for component being defined       *  -     * @param Path $classpath An Path object containing the classpath. +     * @param Path $classpath A Path object containing the classpath.       */      public function setClasspath(Path $classpath) {          if ($this->classpath === null) { @@ -83,6 +83,8 @@ class TypedefTask extends Task {      /**       * Create the classpath to be used when searching for component being defined +     *  +     * @return Path       */       public function createClasspath() {          if ($this->classpath === null) { diff --git a/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php b/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php index 720fae12..1954fe88 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: UpToDateTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 5b0af63dfa9acb85374dcdd2d7fd866ce81391d0 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,6 +21,7 @@  require_once 'phing/Task.php';  include_once 'phing/tasks/system/condition/Condition.php'; +include_once 'phing/tasks/system/PropertyTask.php';  include_once 'phing/util/DirectoryScanner.php';  include_once 'phing/util/SourceFileScanner.php';  include_once 'phing/mappers/MergeMapper.php'; @@ -33,7 +34,7 @@ include_once 'phing/mappers/MergeMapper.php';   * @author    William Ferguson <williamf@mincom.com> (Ant)   * @author    Hiroaki Nakamura <hnakamur@mc.neweb.ne.jp> (Ant)   * @author    Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version   $Revision: 1.6 $ + * @version   $Id$   * @package   phing.tasks.system   */  class UpToDateTask extends Task implements Condition { @@ -43,6 +44,7 @@ class UpToDateTask extends Task implements Condition {      private $_sourceFile;      private $_targetFile;      private $sourceFileSets = array(); +    private $_filelists = array();      protected $mapperElement = null; @@ -57,6 +59,14 @@ class UpToDateTask extends Task implements Condition {      }      /** +     * Get property name +     * @param property the name of the property to set if Target is up-to-date. +     */ +    public function getProperty() { +        return $this->_property; +    } + +    /**       * The value to set the named property to if the target file is more       * up-to-date than (each of) the source file(s). Defaults to 'true'.       * @@ -101,6 +111,8 @@ class UpToDateTask extends Task implements Condition {      /**       * Nested <srcfiles> element. +     * +     * @deprecated Deprecated since Phing 2.4.0       */      public function createSrcfiles() {          $fs = new FileSet(); @@ -109,6 +121,22 @@ class UpToDateTask extends Task implements Condition {      }      /** +     * Nested <fileset> element. +     */ +    public function addFileset(FileSet $fs) { +        $this->sourceFileSets[] = $fs; +    } +     +    /** +     * Supports embedded <filelist> element. +     * @return FileList +     */ +    public function createFileList() { +        $num = array_push($this->_filelists, new FileList()); +        return $this->_filelists[$num-1]; +    } +    +    /**       * Defines the FileNameMapper to use (nested mapper element).       */      public function createMapper() { @@ -126,15 +154,15 @@ class UpToDateTask extends Task implements Condition {       * @return boolean       */      public function evaluate() { -        if (count($this->sourceFileSets) === 0 && $this->_sourceFile === null) { +        if (count($this->sourceFileSets) == 0 && count($this->_filelists) == 0 && $this->_sourceFile === null) {              throw new BuildException("At least one srcfile or a nested " -                                     . "<srcfiles> element must be set."); +                                     . "<fileset> or <filelist> element must be set.");          } -        if (count($this->sourceFileSets) > 0 && $this->_sourceFile !== null) { +        if ((count($this->sourceFileSets) > 0 || count($this->_filelists) > 0) && $this->_sourceFile !== null) {              throw new BuildException("Cannot specify both the srcfile " -                                     . "attribute and a nested <srcfiles> " -                                     . "element."); +                                     . "attribute and a nested <fileset> " +                                     . "or <filelist> element.");          }          if ($this->_targetFile === null && $this->mapperElement === null) { @@ -161,6 +189,13 @@ class UpToDateTask extends Task implements Condition {                                             $ds->getIncludedFiles());          } +        for($i=0,$size=count($this->_filelists); $i < $size && $upToDate; $i++) { +            $fl = $this->_filelists[$i]; +            $srcFiles = $fl->getFiles($this->project); +            $upToDate = $upToDate && $this->scanDir($fs->getDir($this->project), +                                           $srcFiles); +        } +          if ($this->_sourceFile !== null) {              if ($this->mapperElement === null) {                  $upToDate = $upToDate && @@ -189,13 +224,18 @@ class UpToDateTask extends Task implements Condition {          }          $upToDate = $this->evaluate();          if ($upToDate) { -            $this->project->setNewProperty($this->_property, $this->getValue()); +            $property = $this->project->createTask('property'); +            $property->setName($this->getProperty()); +            $property->setValue($this->getValue()); +            $property->setOverride(true); +            $property->main(); // execute +              if ($this->mapperElement === null) {                  $this->log("File \"" . $this->_targetFile->getAbsolutePath()  -                    . "\" is up-to-date.", PROJECT_MSG_VERBOSE); +                    . "\" is up-to-date.", Project::MSG_VERBOSE);              } else {                  $this->log("All target files are up-to-date.", -                    PROJECT_MSG_VERBOSE); +                    Project::MSG_VERBOSE);              }          }      } diff --git a/buildscripts/phing/classes/phing/tasks/system/WaitForTask.php b/buildscripts/phing/classes/phing/tasks/system/WaitForTask.php new file mode 100755 index 00000000..00bcff1e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/WaitForTask.php @@ -0,0 +1,188 @@ +<?php +/* + * $Id: dae67bf2b9c154d4614f30e9ba85c16782550bb3 $ + * + * 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/Task.php'; + +/** + *  Based on Apache Ant Wait For: + * + *  Licensed to the Apache Software Foundation (ASF) under one or more + *  contributor license agreements.  See the NOTICE file distributed with + *  this work for additional information regarding copyright ownership. + *  The ASF licenses this file to You under the Apache License, Version 2.0 + *  (the "License"); you may not use this file except in compliance with + *  the License.  You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + *  Unless required by applicable law or agreed to in writing, software + *  distributed under the License is distributed on an "AS IS" BASIS, + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *  See the License for the specific language governing permissions and + *  limitations under the License. + * + * @author    Michiel Rook <mrook@php.net> + * @version   $Id$ + * @package   phing.tasks.system + */ +class WaitForTask extends ConditionBase +{ +    const ONE_MILLISECOND = 1; +    const ONE_SECOND      = 1000; +    const ONE_MINUTE      = 60000; +    const ONE_HOUR        = 3600000; +    const ONE_DAY         = 86400000; +    const ONE_WEEK        = 604800000; +     +    const DEFAULT_MAX_WAIT_MILLIS = 180000; +    const DEFAULT_CHECK_MILLIS    = 500; +     +    protected $maxWait           = self::DEFAULT_MAX_WAIT_MILLIS; +    protected $maxWaitMultiplier = self::ONE_MILLISECOND; +     +    protected $checkEvery           = self::DEFAULT_CHECK_MILLIS; +    protected $checkEveryMultiplier = self::ONE_MILLISECOND; +     +    protected $timeoutProperty = null; +     +    /** +     * Set the maximum length of time to wait. +     * @param int $maxWait +     */ +    public function setMaxWait($maxWait) +    { +        $this->maxWait = (int) $maxWait; +    } +     +    /** +     * Set the max wait time unit +     * @param string $maxWaitUnit +     */ +    public function setMaxWaitUnit($maxWaitUnit) +    { +        $this->maxWaitMultiplier = $this->_convertUnit($maxWaitUnit); +    } +     +    /** +     * Set the time between each check +     * @param int $checkEvery +     */ +    public function setCheckEvery($checkEvery) +    { +        $this->checkEvery = (int) $checkEvery; +    } +     +    /** +     * Set the check every time unit +     * @param string $checkEveryUnit +     */ +    public function setCheckEveryUnit($checkEveryUnit) +    { +        $this->checkEveryMultiplier = $this->_convertUnit($checkEveryUnit); +    } +     +    /** +     * Name of the property to set after a timeout. +     * @param string $timeoutProperty +     */ +    public function setTimeoutProperty($timeoutProperty) +    { +        $this->timeoutProperty = $timeoutProperty; +    } +     +    /** +     * Convert the unit to a multipler. +     * @param string $unit +     */ +    protected function _convertUnit($unit) +    { +        switch ($unit) { +            case "week": { +                return self::ONE_WEEK; +            } +             +            case "day": { +                return self::ONE_DAY; +            } +             +            case "hour": { +                return self::ONE_HOUR; +            } +             +            case "minute": { +                return self::ONE_MINUTE; +            } +             +            case "second": { +                return self::ONE_SECOND; +            } +             +            case "millisecond": { +                return self::ONE_MILLISECOND; +            } +             +            default: { +                throw new BuildException("Illegal unit '$unit'"); +            } +        } +    } +     +    /** +     * Check repeatedly for the specified conditions until they become +     * true or the timeout expires. +     * @throws BuildException +     */ +    public function main() +    { +        if ($this->countConditions() > 1) { +            throw new BuildException("You must not nest more than one condition into <waitfor>"); +        } +         +        if ($this->countConditions() < 1) { +            throw new BuildException("You must nest a condition into <waitfor>"); +        } +         +        $cs = $this->getIterator(); +        $condition = $cs->current(); +         +        $maxWaitMillis = $this->maxWait * $this->maxWaitMultiplier; +        $checkEveryMillis = $this->checkEvery * $this->checkEveryMultiplier; +         +        $start = microtime(true) * 1000; +        $end = $start + $maxWaitMillis; +         +        while (microtime(true) * 1000 < $end) { +            if ($condition->evaluate()) { +                $this->log("waitfor: condition was met", Project::MSG_VERBOSE); +                 +                return; +            } +             +            usleep($checkEveryMillis * 1000); +        } +         +        $this->log("waitfor: timeout", Project::MSG_VERBOSE); +         +        if ($this->timeoutProperty != null) { +            $this->project->setNewProperty($this->timeoutProperty, "true"); +        } +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/system/WarnTask.php b/buildscripts/phing/classes/phing/tasks/system/WarnTask.php index 50318e71..28f0ad92 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/WarnTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/WarnTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: WarnTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: a2192433abbea9c5fe4b4ddb518cde8c09a643da $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,14 +22,14 @@  require_once 'phing/tasks/system/EchoTask.php';  /** - * Simple task to echo a warning message (PROJECT_MSG_WARN) to all output devices. + * Simple task to echo a warning message (Project::MSG_WARN) to all output devices.   *   * @author   Hans Lellelid <hans@xmpl.org> - * @version  $Revision: 1.1 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @version  $Id$   * @package  phing.tasks.system   */  class WarnTask extends EchoTask {      function main() { -        $this->log($this->msg, PROJECT_MSG_WARN); +        $this->log($this->msg, Project::MSG_WARN);      }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/XsltTask.php b/buildscripts/phing/classes/phing/tasks/system/XsltTask.php index 0374aa59..7155caf8 100644 --- a/buildscripts/phing/classes/phing/tasks/system/XsltTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/XsltTask.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: XsltTask.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 8f87e1c7908c06223382baf628d018c3a0f10824 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/filters/XsltFilter.php';   * in the <filterchains> section.   *    * @author    Andreas Aderhold, andi@binarycloud.com - * @version   $Revision: 1.8 $ + * @version   $Id: 8f87e1c7908c06223382baf628d018c3a0f10824 $   * @package   phing.tasks.system   */  class XsltTask extends CopyTask { @@ -57,7 +57,7 @@ class XsltTask extends CopyTask {       * @see CopyTask::main()       */      function main() {         -        $this->log("Doing XSLT transformation using stylesheet " . $this->xsltFilter->getStyle(), PROJECT_MSG_VERBOSE); +        $this->log("Doing XSLT transformation using stylesheet " . $this->xsltFilter->getStyle(), Project::MSG_VERBOSE);          $this->xsltFilter->setParams($this->parameters);          parent::main();      } @@ -71,6 +71,28 @@ class XsltTask extends CopyTask {      }      /** +     * Whether to resolve entities in the XML document. +     *  +     * @param bool $resolveExternals +     *  +     * @since 2.4 +     */ +    function setResolveDocumentExternals($resolveExternals) { +        $this->xsltFilter->setResolveDocumentExternals((bool)$resolveExternals); +    } +     +    /** +     * Whether to resolve entities in the stylesheet. +     *  +     * @param bool $resolveExternals +     *  +     * @since 2.4 +     */ +    function setResolveStylesheetExternals($resolveExternals) { +        $this->xsltFilter->setResolveStylesheetExternals((bool)$resolveExternals); +    } +     +    /**       * Support nested <param> tags useing XSLTParam class.       * @return XSLTParam       */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php index c16ce499..41b57a8e 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: AndCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 69074307e3d1aae5fbfaa03842f5a8fc14b49625 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,8 +29,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php';   *    *  @author    Hans Lellelid <hans@xmpl.org>   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.7 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @package   phing.tasks.system.condition   */  class AndCondition extends ConditionBase implements Condition { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php b/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php index 73e0c232..9c9d90e5 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: Condition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: c971532805c4ac4c3d3cbf05a5c53abe7279b336 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@   * Each condition must implement a method applying to this prototye:   *   * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.4 $ + * @version $Id$   * @package phing.tasks.system.condition   */  interface Condition { @@ -36,4 +36,3 @@ interface Condition {       */      public function evaluate();  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php b/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php index 1c09fe49..e21ce4e4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ConditionBase.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 8721880badf6aee475a8cb87c88ca3dc4299efb8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,10 +29,10 @@ include_once 'phing/tasks/system/condition/Condition.php';   *  conditions - ensures that the types of conditions inside the task   *  and the "container" conditions are in sync.   *  - *    @author    Hans Lellelid <hans@xmpl.org> + *  @author  Hans Lellelid <hans@xmpl.org>   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.16 $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @package   phing.tasks.system.condition   */  abstract class ConditionBase extends ProjectComponent implements IteratorAggregate { @@ -156,6 +156,8 @@ abstract class ConditionBase extends ProjectComponent implements IteratorAggrega  /**   * "Inner" class for handling enumerations.   * Uses build-in PHP5 iterator support. + * + * @package   phing.tasks.system.condition   */  class ConditionEnumeration implements Iterator { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php index 95849cd8..d7fb80ac 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: ContainsCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 6cdecc53a715fce4601b1ceb64c8ec95d29c1468 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/tasks/system/condition/Condition.php';   *   * @author Hans Lellelid <hans@xmpl.org> (Phing)   * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.3 $ + * @version $Id: 6cdecc53a715fce4601b1ceb64c8ec95d29c1468 $   * @package phing.tasks.system.condition   */  class ContainsCondition implements Condition { @@ -71,6 +71,6 @@ class ContainsCondition implements Condition {          return $this->caseSensitive               ? strpos($this->string, $this->subString) !== false -            : substr(strtolower($this->string), strtolower($this->subString)) !== false; +            : strpos(strtolower($this->string), strtolower($this->subString)) !== false;      }  } diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php index 32d51380..4be4e8fe 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: EqualsCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: faec716501a00cdeb84b8c893b5bbe5c76064dec $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,8 +26,8 @@ require_once 'phing/tasks/system/condition/Condition.php';   *  binary safe manner. Implements the condition interface specification.   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.7 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id: faec716501a00cdeb84b8c893b5bbe5c76064dec $   *  @access    public   *  @package   phing.tasks.system.condition   */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php index ebbd1a3d..8a1b3dcf 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: IsFalseCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: f7d355bdf8f7aa539afb572e2fe033ffd3bcd89b $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/tasks/system/condition/Condition.php';   *    * @author Hans Lellelid (Phing)   * @author Steve Loughran (Ant) - * @version $Revision: 1.4 $ + * @version $Id: f7d355bdf8f7aa539afb572e2fe033ffd3bcd89b $   * @package phing.tasks.system.condition   */  class IsFalseCondition extends ProjectComponent implements Condition { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php index 4f81c50f..24f3f609 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: IsSetCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: 5c5924da5cff2626af09b4908703a21eec79c777 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/tasks/system/condition/Condition.php';   *   * @author Hans Lellelid <hans@xmpl.org> (Phing)   * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.4 $ + * @version $Id$   * @package phing.tasks.system.condition   */  class IsSetCondition extends ProjectComponent implements Condition { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php index 4affefc5..8c6d19fc 100644 --- a/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: IsTrueCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: d567f7c477e075a5c06d3f8e07ff8a7412cf31cd $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php index c76ef2b8..081876af 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: NotCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: d8c985da7c759357135cf717b1f4b52a1bd50cb6 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,8 +28,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php';   *  and vice versa.   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.6 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @access    public   *  @package   phing.tasks.system.condition   */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php index 778abfd0..d88df271 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: OrCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: adcd6785a85304a0860cc3dd9a0146d965c1cb0c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ require_once 'phing/tasks/system/condition/ConditionBase.php';   *   *  @author    Andreas Aderhold <andi@binarycloud.com>   *  @copyright  2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.8 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + *  @version   $Id$   *  @access    public   *  @package   phing.tasks.system.condition   */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php index d80729e7..50a7174f 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: OsCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: d63246e2d25230f5ba6e45a651497e3ba01abe2c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,8 +25,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php';   *  Condition that tests the OS type.   *   *  @author    Andreas Aderhold <andi@binarycloud.com> - *  @copyright © 2001,2002 THYRELL. All rights reserved - *  @version   $Revision: 1.8 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + *  @copyright 2001,2002 THYRELL. All rights reserved + *  @version   $Id$   *  @access    public   *  @package   phing.tasks.system.condition   */ @@ -40,20 +40,20 @@ class OsCondition implements Condition {      function evaluate() {          $osName = strtolower(Phing::getProperty("os.name")); -		 +                  if ($this->family !== null) {              if ($this->family === "windows") {                  return StringHelper::startsWith("win", $osName);              } elseif ($this->family === "mac") {                  return (strpos($osName, "mac") !== false || strpos($osName, "darwin") !== false);              } elseif ($this->family === ("unix")) { -				return ( -					StringHelper::endsWith("ix", $osName) || -					StringHelper::endsWith("ux", $osName) || -					StringHelper::endsWith("bsd", $osName) || -					StringHelper::startsWith("sunos", $osName) || -					StringHelper::startsWith("darwin", $osName) -				); +                return ( +                    StringHelper::endsWith("ix", $osName) || +                    StringHelper::endsWith("ux", $osName) || +                    StringHelper::endsWith("bsd", $osName) || +                    StringHelper::startsWith("sunos", $osName) || +                    StringHelper::startsWith("darwin", $osName) +                );              }              throw new BuildException("Don't know how to detect os family '" . $this->family . "'");          } diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php index 09324fb8..08e291e3 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: ReferenceExistsCondition.php 59 2006-04-28 14:49:47Z mrook $ + *  $Id: e62ed1e00cc6ed859746760c89bc0f873db4620a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ require_once 'phing/ProjectComponent.php'; require_once 'phing/tasks/system/cond   * Condition that tests whether a given reference exists.   *   * @author Matthias Pigulla <mp@webfactory.de> (Phing) - * @version $Revision: 1.1 $ + * @version $Id$   * @package phing.tasks.system.condition  */  class ReferenceExistsCondition extends ProjectComponent implements Condition { diff --git a/buildscripts/phing/classes/phing/types/AbstractFileSet.php b/buildscripts/phing/classes/phing/types/AbstractFileSet.php index 6d640705..60ca4d04 100644..100755 --- a/buildscripts/phing/classes/phing/types/AbstractFileSet.php +++ b/buildscripts/phing/classes/phing/types/AbstractFileSet.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: AbstractFileSet.php,v 1.15 2005/05/26 13:10:53 mrook Exp $ + *  $Id: b7d8ccab6ed556e74626d880dcc09be20ea8bd58 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -62,7 +62,7 @@ include_once 'phing/util/DirectoryScanner.php';   *   * @author    Andreas Aderhold <andi@binarycloud.com>   * @author    Hans Lellelid <hans@xmpl.org> - * @version    $Revision: 1.15 $ $Date: 2005/05/26 13:10:53 $ + * @version    $Id$   * @see        ProjectComponent   * @package    phing.types   */ @@ -75,6 +75,12 @@ class AbstractFileSet extends DataType implements SelectorContainer {       */      public $useDefaultExcludes = true; +    /**  +     * Whether to expand/dereference symbolic links, default is false +     * @var boolean +     */ +    protected $expandSymbolicLinks = false; +          /**       * @var PatternSet       */ @@ -96,7 +102,15 @@ class AbstractFileSet extends DataType implements SelectorContainer {          }          $this->defaultPatterns = new PatternSet();      } - +     +    /**  +     * Sets whether to expand/dereference symbolic links, default is false +     * @var boolean +     */ +    function setExpandSymbolicLinks($expandSymbolicLinks) +    { +        $this->expandSymbolicLinks = $expandSymbolicLinks; +    }      /**      * Makes this instance in effect a reference to another PatternSet @@ -268,10 +282,13 @@ class AbstractFileSet extends DataType implements SelectorContainer {          if (!$this->dir->exists()) {              throw new BuildException("Directory ".$this->dir->getAbsolutePath()." not found.");          } -        if (!$this->dir->isDirectory()) { -            throw new BuildException($this->dir->getAbsolutePath()." is not a directory."); +        if (!$this->dir->isLink() || !$this->expandSymbolicLinks) { +            if (!$this->dir->isDirectory()) { +                throw new BuildException($this->dir->getAbsolutePath()." is not a directory."); +            }          }          $ds = new DirectoryScanner(); +        $ds->setExpandSymbolicLinks($this->expandSymbolicLinks);          $this->setupDirectoryScanner($ds, $p);          $ds->scan();          return $ds; @@ -292,7 +309,7 @@ class AbstractFileSet extends DataType implements SelectorContainer {          $ds->setIncludes($this->defaultPatterns->getIncludePatterns($p));          $ds->setExcludes($this->defaultPatterns->getExcludePatterns($p)); -        $p->log("FileSet: Setup file scanner in dir " . $this->dir->__toString() . " with " . $this->defaultPatterns->toString(), PROJECT_MSG_DEBUG); +        $p->log("FileSet: Setup file scanner in dir " . $this->dir->__toString() . " with " . $this->defaultPatterns->toString(), Project::MSG_DEBUG);          if ($ds instanceof SelectorScanner) {              $ds->setSelectors($this->getSelectors($p)); diff --git a/buildscripts/phing/classes/phing/types/Commandline.php b/buildscripts/phing/classes/phing/types/Commandline.php index 877179d0..d6b36e14 100644..100755 --- a/buildscripts/phing/classes/phing/types/Commandline.php +++ b/buildscripts/phing/classes/phing/types/Commandline.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Commandline.php,v 1.11 2005/05/26 13:10:53 mrook Exp $ + *  $Id: 891b349dcd88b825ae99edf53ed4c7ac2c1c2467 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -41,6 +41,7 @@   *   * @author thomas.haas@softwired-inc.com   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> + * @package phing.types   */  class Commandline { @@ -156,8 +157,10 @@ class Commandline {       * @exception BuildException if the argument contains both, single       *                           and double quotes.       */ -    public static function quoteArgument($argument) { -        if (strpos($argument, "\"") !== false) { +    public static function quoteArgument($argument, $escape = false) { +        if ($escape) { +            return escapeshellarg($argument); +        } elseif (strpos($argument, "\"") !== false) {              if (strpos($argument, "'") !== false) {                  throw new BuildException("Can't handle single and double quotes in same argument");              } else { @@ -175,7 +178,7 @@ class Commandline {       * Quotes the parts of the given array in way that makes them       * usable as command line arguments.       */ -    public static function toString($lines) { +    public static function toString($lines, $escape = false) {          // empty path return empty string          if (!$lines) {              return ""; @@ -187,7 +190,7 @@ class Commandline {              if ($i > 0) {                  $result .= ' ';              } -            $result .= self::quoteArgument($lines[$i]); +            $result .= self::quoteArgument($lines[$i], $escape);          }          return $result;      } @@ -307,7 +310,7 @@ class Commandline {      /**       * Returns a String that describes the command and arguments       * suitable for verbose output before a call to -     * <code>Runtime.exec(String[])<code>. +     * <code>Runtime.exec(String[])</code>.       *       * <p>This method assumes that the first entry in the array is the       * executable to run.</p> @@ -339,7 +342,7 @@ class Commandline {      /**       * Returns a String that describes the arguments suitable for       * verbose output before a call to -     * <code>Runtime.exec(String[])<code> +     * <code>Runtime.exec(String[])</code>       * @param $args arguments to use (default is to use current class args)       * @param $offset ignore entries before this index       * @return string @@ -357,9 +360,9 @@ class Commandline {          if (count($args) > $offset) {              $buf .= "s";          } -        $buf .= ":" . Phing::getProperty("line.separator"); +        $buf .= ":" . PHP_EOL;          for ($i = $offset, $alen=count($args); $i < $alen; $i++) { -            $buf .= "'" . $args[$i] . "'" . Phing::getProperty("line.separator"); +            $buf .= "'" . $args[$i] . "'" . PHP_EOL;          }          $buf .= self::DISCLAIMER;          return $buf; @@ -369,6 +372,8 @@ class Commandline {  /**   * "Inner" class used for nested xml command line definitions. + * + * @package phing.types   */  class CommandlineArgument { @@ -432,10 +437,13 @@ class CommandlineArgument {  /**   * Class to keep track of the position of an Argument. + * + * <p>This class is there to support the srcfile and targetfile + * elements of <execon> and <transform> - don't know + * whether there might be additional use cases.</p> --SB + * + * @package phing.types   */ -// <p>This class is there to support the srcfile and targetfile -// elements of <execon> and <transform> - don't know -// whether there might be additional use cases.</p> --SB  class CommandlineMarker {      private $position; diff --git a/buildscripts/phing/classes/phing/types/DataType.php b/buildscripts/phing/classes/phing/types/DataType.php index 2c06b80d..8aa3b487 100644 --- a/buildscripts/phing/classes/phing/types/DataType.php +++ b/buildscripts/phing/classes/phing/types/DataType.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: DataType.php,v 1.9 2005/11/02 13:55:34 hlellelid Exp $ + *  $Id: 3b15630144c62dda1f447d8eed1e5eda7ac8a466 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -75,9 +75,9 @@ class DataType extends ProjectComponent {       * Subclasses may need to check whether any other attributes       * have been set as well or child elements have been created and       * thus override this method. if they do they must call parent::setRefid() -	 *  -	 * @param Reference $r -	 * @return void +     *  +     * @param Reference $r +     * @return void       */      function setRefid(Reference $r) {          $this->ref = $r; diff --git a/buildscripts/phing/classes/phing/types/Description.php b/buildscripts/phing/classes/phing/types/Description.php index e69f8da4..85b2c529 100644 --- a/buildscripts/phing/classes/phing/types/Description.php +++ b/buildscripts/phing/classes/phing/types/Description.php @@ -1,7 +1,7 @@  <?php  /* - *  $Id: Description.php,v 1.4 2003/12/24 12:38:42 hlellelid Exp $ + *  $Id: bb303eb742207be6958c8107e21ec7c964c09dee $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/DirSet.php b/buildscripts/phing/classes/phing/types/DirSet.php index 45bcc636..527127bb 100644 --- a/buildscripts/phing/classes/phing/types/DirSet.php +++ b/buildscripts/phing/classes/phing/types/DirSet.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: DirSet.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $ + * $Id: 1ab2ec4f1b43daee6cf4c247b4b18b78d87052bc $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/Excludes.php b/buildscripts/phing/classes/phing/types/Excludes.php new file mode 100644 index 00000000..2d45b593 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Excludes.php @@ -0,0 +1,208 @@ +<?php +/* + *  $Id: 0c22f261d1984da235c6cf4993d1275c225a33ba $ + * + * 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>. + */ + +include_once 'phing/types/DataType.php'; +include_once 'phing/types/FileSet.php'; +require_once 'phing/types/ExcludesNameEntry.php'; + +/** + * Datatype which handles excluded files, classes and methods. + * + * @package phing.types + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 0c22f261d1984da235c6cf4993d1275c225a33ba $ + * @since   2.4.6 + */ +class Excludes extends DataType +{ +    /** +     * The directory scanner for getting the excluded files +     * +     * @var DirectoryScanner +     */ +    private $_directoryScanner = null; + +    /** +     * Holds the excluded file patterns +     * +     * @var array +     */ +    private $_files = array(); + +    /** +     * Holds the excluded classes +     * +     * @var array +     */ +    private $_classes = array(); + +    /** +     * Holds the excluded methods +     * +     * @var array +     */ +    private $_methods = array(); + +    /** +     * ctor +     * +     * @param Project $project +     */ +    public function __construct(Project $project) +    { +        $this->_directoryScanner = new DirectoryScanner(); +        $this->_directoryScanner->setBasedir($project->getBasedir()); +    } + +    /** +     * Add a name entry on the exclude file list +     * +     * @return ExcludesNameEntry Reference to object +     */ +    public function createFile() +    { +        return $this->_addFile($this->_files); +    } + +    /** +     * Add a name entry on the exclude class list +     * +     * @return ExcludesNameEntry Reference to object +     */ +    public function createClass() +    { +        return $this->_addClass($this->_classes); +    } + +    /** +     * Add a name entry on the exclude method list +     * +     * @return ExcludesNameEntry Reference to object +     */ +    public function createMethod() +    { +        return $this->_addMethod($this->_methods); +    } + +    /** +     * Adds a file to the exclusion list +     * +     * @param FileSet $fileSet The FileSet into which the nameentry should be added +     * +     * @return ExcludesNameEntry Reference to the created ExcludesNameEntry instance +     */ +    private function _addFile(&$fileList) +    { +        $file       = new ExcludesNameEntry(); +        $fileList[] = $file; + +        return $file; +    } + +    /** +     * Adds a class to the exclusion list +     * +     * @return ExcludesNameEntry Reference to the created ExcludesNameEntry instance +     */ +    private function _addClass(&$classList) +    { +        $excludedClass = new ExcludesNameEntry(); +        $classList[]   = $excludedClass; + +        return $excludedClass; +    } + +    /** +     * Adds a method to the exclusion list +     * +     * @return ExcludesNameEntry Reference to the created ExcludesNameEntry instance +     */ +    private function _addMethod(&$methodList) +    { +        $excludedMethod = new ExcludesNameEntry(); +        $methodList[]   = $excludedMethod; + +        return $excludedMethod; +    } + +    /** +     * Returns the excluded files +     * +     * @return array +     */ +    public function getExcludedFiles() +    { +        $includes = array(); + +        foreach ($this->_files as $file) { +            $includes[] = $file->getName(); +        } + +        $this->_directoryScanner->setIncludes($includes); +        $this->_directoryScanner->scan(); + +        $files    = $this->_directoryScanner->getIncludedFiles(); +        $dir      = $this->_directoryScanner->getBasedir(); +        $fileList = array(); + +        foreach ($files as $file) { +            $fileList[] = $dir . DIRECTORY_SEPARATOR . $file; +        } + +        return $fileList; +    } + +    /** +     * Returns the excluded class names +     * +     * @return array +     */ +    public function getExcludedClasses() +    { +        $excludedClasses = array(); + +        foreach ($this->_classes as $excludedClass) { +            $excludedClasses[] = $excludedClass->getName(); +        } + +        return $excludedClasses; +    } + +    /** +     * Returns the excluded method names +     * +     * @return array +     */ +    public function getExcludedMethods() +    { +        $excludedMethods = array(); + +        foreach ($this->_methods as $excludedMethod) { +            $classAndMethod = explode('::', $excludedMethod->getName()); +            $className      = $classAndMethod[0]; +            $methodName     = $classAndMethod[1]; + +            $excludedMethods[$className][] = $methodName; +        } + +        return $excludedMethods; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/types/ExcludesNameEntry.php b/buildscripts/phing/classes/phing/types/ExcludesNameEntry.php new file mode 100644 index 00000000..1aa6aae5 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/ExcludesNameEntry.php @@ -0,0 +1,81 @@ +<?php +/* + *  $Id: a1098700b4f205baacfd5adf5434e5a4803a6a3f $ + * + * 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>. + */ + +/** + * Class for holding nested excludes elements (file, class, method). + * + * @package phing.types + * @author  Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: a1098700b4f205baacfd5adf5434e5a4803a6a3f $ + * @since   2.4.6 + */ +class ExcludesNameEntry +{ +    /** +     * Holds the name of a file, class or method or a file pattern +     * +     * @var string +     */ +    private $_name; + +    /** +     * An alias for the setName() method. +     * Set the name of a file pattern. +     * +     * @see setName() +     * +     * @param string $pattern The file pattern +     */ +    public function addText($pattern) +    { +        $this->setName($pattern); +    } + +    /** +     * Set the name of a file, class or method +     * +     * @param string $name +     */ +    public function setName($name) +    { +        $this->_name = (string) $name; +    } + +    /** +     * Get the name of a file, class or method or the file pattern +     * +     * @return string The name of a file, class or method or the file pattern +     */ +    public function getName() +    { +        return $this->_name; +    } + +    /** +     * Gets a string representation of this name or pattern. +     * +     * @return string +     */ +    public function toString() +    { +        return $this->_name; +    } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/types/FileList.php b/buildscripts/phing/classes/phing/types/FileList.php index 1ec1273f..bc7c6b18 100644..100755 --- a/buildscripts/phing/classes/phing/types/FileList.php +++ b/buildscripts/phing/classes/phing/types/FileList.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FileList.php,v 1.10 2005/11/01 15:26:09 hlellelid Exp $ + *  $Id: aab0ffb8e2266923f6cdaf165741dc38931a2aed $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -41,7 +41,7 @@ include_once 'phing/system/io/PhingFile.php';   * (or a mixture of files="" and listfile="" can be used)   *    * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.10 $ + * @version $Id$   * @package phing.types   */  class FileList extends DataType { @@ -142,9 +142,10 @@ class FileList extends DataType {      /**       * Get the source "list" file that contains file names. +     * @param Project $p       * @return PhingFile       */ -    function getListFile() { +    function getListFile(Project $p) {          if ($this->isReference()) {              $ref = $this->getRef($p);              return $ref->getListFile($p); diff --git a/buildscripts/phing/classes/phing/types/FileSet.php b/buildscripts/phing/classes/phing/types/FileSet.php index 8cfb54dc..229e4419 100644 --- a/buildscripts/phing/classes/phing/types/FileSet.php +++ b/buildscripts/phing/classes/phing/types/FileSet.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: FileSet.php,v 1.5 2003/12/24 12:38:42 hlellelid Exp $ + * $Id: 1fbeb217059bb26788059dd46affde1428d5a52e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/FilterChain.php b/buildscripts/phing/classes/phing/types/FilterChain.php index 4f2d702b..e6575c33 100644..100755 --- a/buildscripts/phing/classes/phing/types/FilterChain.php +++ b/buildscripts/phing/classes/phing/types/FilterChain.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FilterChain.php,v 1.11 2005/12/08 16:03:49 hlellelid Exp $ + *  $Id: ec2362b430c0a863a77968e9003b09c4b9a78d7e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,6 +21,7 @@  include_once 'phing/types/DataType.php';  include_once 'phing/filters/HeadFilter.php'; +include_once 'phing/filters/IconvFilter.php';  include_once 'phing/filters/TailFilter.php';  include_once 'phing/filters/LineContains.php';  include_once 'phing/filters/LineContainsRegexp.php'; @@ -28,27 +29,33 @@ include_once 'phing/filters/ExpandProperties.php';  include_once 'phing/filters/PrefixLines.php';  include_once 'phing/filters/ReplaceRegexp.php';  include_once 'phing/filters/ReplaceTokens.php'; +include_once 'phing/filters/ReplaceTokensWithFile.php';  include_once 'phing/filters/StripPhpComments.php';  include_once 'phing/filters/StripLineBreaks.php';  include_once 'phing/filters/StripLineComments.php'; +include_once 'phing/filters/StripWhitespace.php';  include_once 'phing/filters/TabToSpaces.php';  include_once 'phing/filters/TidyFilter.php';  include_once 'phing/filters/TranslateGettext.php'; +include_once 'phing/filters/XincludeFilter.php';  include_once 'phing/filters/XsltFilter.php'; -/* +/**   * FilterChain may contain a chained set of filter readers.   *   * @author    Yannick Lecaillez <yl@seasonfive.com> - * @version   $Revision: 1.11 $ + * @version   $Id$   * @package   phing.types   */  class FilterChain extends DataType {      private $filterReaders = array(); -    function __construct(Project $project) { -        $this->project = $project; +    function __construct($project = null) { +        if ($project) +        { +            $this->project = $project; +        }      }      function getFilterReaders() { @@ -64,90 +71,110 @@ class FilterChain extends DataType {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addHeadFilter(HeadFilter $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     + +    function addIconvFilter(IconvFilter $o) { +        $o->setProject($this->project); +        $this->filterReaders[] = $o; +    } +      function addTailFilter(TailFilter $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addLineContains(LineContains $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addLineContainsRegExp(LineContainsRegExp $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addPrefixLines(PrefixLines $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addReplaceTokens(ReplaceTokens $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } +    function addReplaceTokensWithFile(ReplaceTokensWithFile $o) {  +        $o->setProject($this->project);  +        $this->filterReaders[] = $o;  +    }  +      function addReplaceRegexp(ReplaceRegexp $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addStripPhpComments(StripPhpComments $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addStripLineBreaks(StripLineBreaks $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addStripLineComments(StripLineComments $o) {          $o->setProject($this->project); -        $this->filterReaders[] = $o;         +        $this->filterReaders[] = $o; +    } + +    function addStripWhitespace(StripWhitespace $o) { +        $o->setProject($this->project); +        $this->filterReaders[] = $o;      } -     -	function addTidyFilter(TidyFilter $o) { + +    function addTidyFilter(TidyFilter $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -	 +      function addTabToSpaces(TabToSpaces $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     + +    function addXincludeFilter(XincludeFilter $o) { +        $o->setProject($this->project); +        $this->filterReaders[] = $o; +    } +      function addXsltFilter(XsltFilter $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      } -     +      function addFilterReader(PhingFilterReader $o) {          $o->setProject($this->project);          $this->filterReaders[] = $o;      }      /* -     * Makes this instance in effect a reference to another FilterChain  +     * Makes this instance in effect a reference to another FilterChain       * instance.       *       * <p>You must not set another attribute or nest elements inside       * this element if you make it a reference.</p>       * -     * @param r the reference to which this instance is associated -     * @throw BuildException if this instance already has been configured. +     * @param  $r the reference to which this instance is associated +     * @throws BuildException if this instance already has been configured.      */      function setRefid(Reference $r) { -     -        if ( count($this->filterReaders) === 0 ) { + +        if ( count($this->filterReaders) !== 0 ) {              throw $this->tooManyAttributes();          } @@ -160,5 +187,5 @@ class FilterChain extends DataType {          }          parent::setRefid($r);      } -     +  } diff --git a/buildscripts/phing/classes/phing/types/IterableFileSet.php b/buildscripts/phing/classes/phing/types/IterableFileSet.php new file mode 100644 index 00000000..bc800bbe --- /dev/null +++ b/buildscripts/phing/classes/phing/types/IterableFileSet.php @@ -0,0 +1,56 @@ +<?php +/* + * $Id: a607a54aa4e434c01a1f36600274fb31041549e2 $ + * + * 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>. + */ + +/** + * FileSet adapter to SPL's Iterator. + * + * @package phing.types + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + * @internal + */ +class IterableFileSet +    extends FileSet +    implements IteratorAggregate +{ +    /** +     * @return Iterator +     */ +    public function getIterator() +    { +        return new ArrayIterator($this->getFiles()); +    } +    /** +     * @return array +     */ +    private function getFiles() +    { +        $directoryScanner   = $this->getDirectoryScanner($this->getProject()); +        $files              = $directoryScanner->getIncludedFiles(); + +        $baseDirectory = $directoryScanner->getBasedir(); +        foreach ($files as $index => $file) { +            $files[$index] = realpath($baseDirectory.'/'.$file); +        } + +        return $files; +    } +} diff --git a/buildscripts/phing/classes/phing/types/Mapper.php b/buildscripts/phing/classes/phing/types/Mapper.php index f0df6d24..03042c64 100644 --- a/buildscripts/phing/classes/phing/types/Mapper.php +++ b/buildscripts/phing/classes/phing/types/Mapper.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Mapper.php,v 1.11 2004/03/15 17:11:16 hlellelid Exp $ + *  $Id: bab760877500c0bb1ed4d6879c7e31c60c3fd307 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -134,7 +134,7 @@ class Mapper extends DataType {       *       * You must not set any other attribute if you make it a reference.       */ -    function setRefid($r) { +    function setRefid(Reference $r) {          if ($this->type !== null || $this->from !== null || $this->to !== null) {              throw DataType::tooManyAttributes();          } @@ -204,4 +204,4 @@ class Mapper extends DataType {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/types/Parameter.php b/buildscripts/phing/classes/phing/types/Parameter.php index 6892ed7e..cbba153c 100644 --- a/buildscripts/phing/classes/phing/types/Parameter.php +++ b/buildscripts/phing/classes/phing/types/Parameter.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Parameter.php,v 1.6 2005/10/05 20:23:22 hlellelid Exp $ + *  $Id: 725ec7b7d585219471bb8793da0210c7ab1452c0 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,7 +21,7 @@  include_once 'phing/types/DataType.php'; -/* +/**   * A parameter is composed of a name, type and value. Nested   * Parameters are also possible, but the using task/type has   * to support them @@ -29,7 +29,7 @@ include_once 'phing/types/DataType.php';   * @author    Manuel Holtgrewe   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>   * @package   phing.types -*/ + */  class Parameter extends DataType {      /** Parameter name */ @@ -52,14 +52,14 @@ class Parameter extends DataType {          $this->type = (string) $type;      } -	/** +    /**       * Sets value to dynamic register slot.       * @param RegisterSlot $value       */      public function setListeningValue(RegisterSlot $value) {          $this->value = $value;      } -	 +          function setValue($value) {          $this->value = (string) $value;      } @@ -73,7 +73,7 @@ class Parameter extends DataType {      }      function getValue() { -		if ($this->value instanceof RegisterSlot) { +        if ($this->value instanceof RegisterSlot) {              return $this->value->getValue();          } else {              return $this->value; @@ -96,4 +96,4 @@ class Parameter extends DataType {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/types/Parameterizable.php b/buildscripts/phing/classes/phing/types/Parameterizable.php index b24aa38b..7efe790a 100644 --- a/buildscripts/phing/classes/phing/types/Parameterizable.php +++ b/buildscripts/phing/classes/phing/types/Parameterizable.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: Parameterizable.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $ + * $Id: e0d41388dad173e2dd61527524d6c3958683171b $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/Path.php b/buildscripts/phing/classes/phing/types/Path.php index 196fe9c4..b8525628 100644 --- a/buildscripts/phing/classes/phing/types/Path.php +++ b/buildscripts/phing/classes/phing/types/Path.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: Path.php,v 1.13 2005/05/26 13:10:53 mrook Exp $ + *  $Id: 762715ec83a12704f4ab528e507c28396c159083 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -16,7 +16,7 @@   *   * This software consists of voluntary contributions made by many individuals   * and is licensed under the LGPL. For more information please see - * <http://phing.info>.  + * <http://phing.info>.   */  require_once 'phing/types/DataType.php'; @@ -37,7 +37,7 @@ include_once 'phing/types/FileSet.php';   * PHP include_path, and will try to load dependent classes accordingly).  The other option is   * to provide a way for this class to add paths to the include path, if desired -- or to create   * an IncludePath subclass.  Once added, though, when would a path be removed from the include path? - *  + *   * <p>   * <code>   * <sometask><br> @@ -65,8 +65,8 @@ include_once 'phing/types/FileSet.php';   */  class Path extends DataType { -    private $elements = array();     -     +    private $elements = array(); +      /**       * Constructor for internally instantiated objects sets project.       * @param Project $project @@ -78,7 +78,7 @@ class Path extends DataType {          }          if ($path !== null) {              $this->createPathElement()->setPath($path); -        }         +        }      }      /** @@ -90,7 +90,7 @@ class Path extends DataType {      public function setDir(PhingFile $location) {          if ($this->isReference()) {              throw $this->tooManyAttributes(); -        }         +        }          $this->createPathElement()->setDir($location);      } @@ -123,7 +123,7 @@ class Path extends DataType {      /**       * Creates the nested <code><pathelement></code> element. -     * @throws BuildException  +     * @throws BuildException       */      public function createPathElement() {          if ($this->isReference()) { @@ -136,7 +136,7 @@ class Path extends DataType {      /**       * Adds a nested <code><fileset></code> element. -     * @throws BuildException  +     * @throws BuildException       */      public function addFileset(FileSet $fs) {          if ($this->isReference()) { @@ -148,7 +148,7 @@ class Path extends DataType {      /**       * Adds a nested <code><dirset></code> element. -     * @throws BuildException  +     * @throws BuildException       */      public function addDirset(DirSet $dset) {          if ($this->isReference()) { @@ -206,8 +206,8 @@ class Path extends DataType {              if ($f->exists()) {                  $this->setDir($f);              } else { -                $this->log("dropping " . $f->__toString() . " from path as it doesn't exist",  -                    PROJECT_MSG_VERBOSE); +                $this->log("dropping " . $f->__toString() . " from path as it doesn't exist", +                    Project::MSG_VERBOSE);              }          }      } @@ -235,13 +235,13 @@ class Path extends DataType {                      throw new BuildException($msg);                  }              } -             +              if (is_string($o)) {                  $result[] = $o;              } elseif ($o instanceof PathElement) {                  $parts = $o->getParts();                  if ($parts === null) { -                    throw new BuildException("You must either set location or"  +                    throw new BuildException("You must either set location or"                          . " path on <pathelement>");                  }                  foreach($parts as $part) { @@ -261,13 +261,10 @@ class Path extends DataType {                  $ds = $dset->getDirectoryScanner($this->project);                  $dirstrs = $ds->getIncludedDirectories();                  $dir = $dset->getDir($this->project); -                $this->addUnlessPresent($result, $dir, $s);   -                                  foreach($dirstrs as $dstr) {                      $d = new PhingFile($dir, $dstr);                      $result[] = $d->getAbsolutePath(); -                }                 -                      +                }              } elseif ($o instanceof FileList) {                  $fl = $o;                  $dirstrs = $fl->getFiles($this->project); @@ -278,7 +275,7 @@ class Path extends DataType {                  }              }          } -         +          return array_unique($result);      } @@ -289,14 +286,14 @@ class Path extends DataType {       * @return string A textual representation of the path.       */      public function __toString() { -         +          $list = $this->listPaths();          // empty path return empty string          if (empty($list)) {              return "";          } -         +          return implode(PATH_SEPARATOR, $list);      } @@ -312,29 +309,27 @@ class Path extends DataType {          }          $tok = new PathTokenizer($source); -        $element = ""; -        while ($tok->hasMoreTokens()) {             +        while ($tok->hasMoreTokens()) {              $pathElement = $tok->nextToken();              try { -                $element .= self::resolveFile($project, $pathElement); +                $element = self::resolveFile($project, $pathElement); +                for ($i = 0, $_i=strlen($element); $i < $_i; $i++) { +                    self::translateFileSep($element, $i); +                } +                $result[] = $element;              } catch (BuildException $e) { -                $this->project->log("Dropping path element " . $pathElement  -                    . " as it is not valid relative to the project",  -                    PROJECT_MSG_VERBOSE); -            } -             -            for ($i = 0, $_i=strlen($element); $i < $_i; $i++) { -                self::translateFileSep($element, $i); +                $this->project->log("Dropping path element " . $pathElement +                    . " as it is not valid relative to the project", +                    Project::MSG_VERBOSE);              } -            $result[] = $element;          } -         +          return $result;      }      /**       * Returns its argument with all file separator characters -     * replaced so that they match the local OS conventions.   +     * replaced so that they match the local OS conventions.       */      public static function translateFile($source) {          if ($source == null) { @@ -345,14 +340,14 @@ class Path extends DataType {          for ($i = 0, $_i=strlen($source); $i < $_i; $i++) {              self::translateFileSep($result, $i);          } -         +          return $result;      }      /**       * Translates all occurrences of / or \ to correct separator of the       * current platform and returns whether it had to do any -     * replacements.   +     * replacements.       */      protected static function translateFileSep(&$buffer, $pos) {          if ($buffer{$pos} == '/' || $buffer{$pos} == '\\') { @@ -383,7 +378,7 @@ class Path extends DataType {      /**       * Overrides the version of DataType to recurse on all DataType -     * child elements that may have been added.   +     * child elements that may have been added.       * @throws BuildException       */      public function dieOnCircularReference(&$stk, Project $p) { @@ -391,10 +386,10 @@ class Path extends DataType {          if ($this->checked) {              return;          } -     +          // elements can contain strings, FileSets, Reference, etc.          foreach($this->elements as $o) { -             +              if ($o instanceof Reference) {                  $o = $o->getReferencedObject($p);              } @@ -409,7 +404,7 @@ class Path extends DataType {                  }              }          } -         +          $this->checked = true;      } @@ -424,23 +419,25 @@ class Path extends DataType {              return $f->getAbsolutePath();          }          return $relativeName; -    }     +    }  }  /**   * Helper class, holds the nested <code><pathelement></code> values. + * + * @package phing.types   */  class PathElement {      private $parts = array();      private $outer; -     +      public function __construct(Path $outer) {          $this->outer = $outer;      } -     +      public function setDir(PhingFile $loc) {          $this->parts = array(Path::translateFile($loc->getAbsolutePath()));      } @@ -453,4 +450,3 @@ class PathElement {          return $this->parts;      }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/types/PatternSet.php b/buildscripts/phing/classes/phing/types/PatternSet.php index 2963ab9e..32967d62 100644..100755 --- a/buildscripts/phing/classes/phing/types/PatternSet.php +++ b/buildscripts/phing/classes/phing/types/PatternSet.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PatternSet.php,v 1.8 2005/05/26 13:10:53 mrook Exp $ + *  $Id: af3bd3709d79ad0299bf6ec0130a8a244ee325ab $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -16,7 +16,7 @@   *   * This software consists of voluntary contributions made by many individuals   * and is licensed under the LGPL. For more information please see - * <http://phing.info>.  + * <http://phing.info>.   */  include_once 'phing/system/io/FileReader.php'; @@ -27,7 +27,7 @@ include_once 'phing/types/DataType.php';   * for the patternset stuff.   *   * @author   Andreas Aderhold, andi@binarycloud.com - * @version  $Revision: 1.8 $ + * @version  $Id: af3bd3709d79ad0299bf6ec0130a8a244ee325ab $   * @package  phing.types   */  class PatternSet extends DataType { @@ -54,8 +54,8 @@ class PatternSet extends DataType {      /**      * Add a name entry on the include list      * -    * @returns PatternSetNameEntry Reference to object -    * @throws  BuildException +    * @return PatternSetNameEntry Reference to object +    * @throws BuildException      */      function createInclude() {          if ($this->isReference()) { @@ -68,8 +68,8 @@ class PatternSet extends DataType {      /**      * Add a name entry on the include files list      * -    * @returns PatternSetNameEntry Reference to object -    * @throws  BuildException +    * @return PatternSetNameEntry Reference to object +    * @throws BuildException      */      function createIncludesFile() {          if ($this->isReference()) { @@ -81,8 +81,8 @@ class PatternSet extends DataType {      /**      * Add a name entry on the exclude list      * -    * @returns PatternSetNameEntry Reference to object -    * @throws  BuildException +    * @return PatternSetNameEntry Reference to object +    * @throws BuildException      */      function createExclude() {          if ($this->isReference()) { @@ -93,11 +93,10 @@ class PatternSet extends DataType {      /**       * add a name entry on the exclude files list -    * -    * @returns PatternSetNameEntry Reference to object -    * @throws  BuildException +     * +     * @return PatternSetNameEntry Reference to object +     * @throws BuildException       */ -      function createExcludesFile() {          if ($this->isReference()) {              throw $this->noChildrenAllowed(); @@ -111,9 +110,9 @@ class PatternSet extends DataType {       * Sets the set of include patterns. Patterns may be separated by a comma       * or a space.       * -     * @param   string the string containing the include patterns -     * @returns void -     * @throws  BuildException +     * @param  string the string containing the include patterns +     * @return void +     * @throws BuildException       */      function setIncludes($includes) {          if ($this->isReference()) { @@ -134,11 +133,10 @@ class PatternSet extends DataType {       * Sets the set of exclude patterns. Patterns may be separated by a comma       * or a space.       * -     * @param string the string containing the exclude patterns -    * @returns void -    * @throws  BuildException +     * @param  string the string containing the exclude patterns +     * @return void +     * @throws BuildException       */ -      function setExcludes($excludes) {          if ($this->isReference()) {              throw $this->tooManyAttributes(); @@ -156,8 +154,8 @@ class PatternSet extends DataType {      /**       * add a name entry to the given list       * -     * @param array List onto which the nameentry should be added -     * @returns PatternSetNameEntry  Reference to the created PsetNameEntry instance +     * @param  array List onto which the nameentry should be added +     * @return PatternSetNameEntry  Reference to the created PsetNameEntry instance       */      private function addPatternToList(&$list) {          $num = array_push($list, new PatternSetNameEntry()); @@ -191,7 +189,7 @@ class PatternSet extends DataType {          }          if ($excludesFile instanceof File) {              $excludesFile = $excludesFile->getPath(); -        }         +        }          $o = $this->createExcludesFile();          $o->setName($excludesFile);      } @@ -205,9 +203,9 @@ class PatternSet extends DataType {          $patternReader = null;          try {              // Get a FileReader -            $patternReader = new BufferedReader(new FileReader($patternfile));  -         -            // Create one NameEntry in the appropriate pattern list for each  +            $patternReader = new BufferedReader(new FileReader($patternfile)); + +            // Create one NameEntry in the appropriate pattern list for each              // line in the file.              $line = $patternReader->readLine();              while ($line !== null) { @@ -217,14 +215,14 @@ class PatternSet extends DataType {                  }                  $line = $patternReader->readLine();              } -             +          } catch (IOException $ioe)  { -            $msg = "An error occured while reading from pattern file: " . $patternfile->__toString();  -            if($patternReader) $patternReader->close();             +            $msg = "An error occured while reading from pattern file: " . $patternfile->__toString(); +            if($patternReader) $patternReader->close();              throw new BuildException($msg, $ioe); -        }  -         -        $patternReader->close();                 +        } + +        $patternReader->close();      } @@ -276,7 +274,7 @@ class PatternSet extends DataType {      /** helper for FileSet. */      function hasPatterns() {          return (boolean) count($this->includesFileList) > 0 || count($this->excludesFileList) > 0 -               || count($this->includeList) > 0 || count($this->excludeList) > 0; +        || count($this->includeList) > 0 || count($this->excludeList) > 0;      }      /** @@ -332,7 +330,7 @@ class PatternSet extends DataType {          }          if (!empty($this->excludesFileList)) { -            foreach($this->excludesFileList as $ne) {                +            foreach($this->excludesFileList as $ne) {                  $fileName = (string) $ne->evalName($p);                  if ($fileName !== null) {                      $exclFile = $p->resolveFile($fileName); @@ -349,13 +347,13 @@ class PatternSet extends DataType {      function toString() { -         +          // We can't compile includeList into array because, toString() does          // not know about project:          //          // $includes = $this->makeArray($this->includeList, $this->project);          // $excludes = $this->makeArray($this->excludeList, $this->project); -             +          if (empty($this->includeList)) {              $includes = "empty";          } else { @@ -365,7 +363,7 @@ class PatternSet extends DataType {              }              $includes = rtrim($includes, ",");          } -         +          if (empty($this->excludeList)) {              $excludes = "empty";          } else { @@ -375,52 +373,95 @@ class PatternSet extends DataType {              }              $excludes = rtrim($excludes, ",");          } -                +          return "patternSet{ includes: $includes  excludes: $excludes }";      }  } -/* - * Note, this class here should become a nested class to - * PatternSet (PatternSet:NameEntry) as it is only needed - * internally. - * This is not possible with php 4.x right now so we place - * this class (against good style) in this file. +/** + * "Internal" class for holding an include/exclude pattern. + * + * @package  phing.types   */ -  class PatternSetNameEntry { -    private $name       = null; -    private $ifCond     = null; -    private $unlessCond = null; +    /** +     * The pattern. +     * @var string +     */ +    private $name; + +    /** +     * The if-condition property for this pattern to be applied. +     * @var string +     */ +    private $ifCond; -    function setName($name) { -        $this->name = (string) $name; +    /** +     * The unless-condition property for this pattern to be applied. +     * @var string  +     */ +    private $unlessCond; + +    /** +     * An alias for the setName() method. +     * @see setName() +     * @param string $pattern +     */ +    public function setPattern($pattern) { +        $this->setName($pattern);      } +    /** +     * Set the pattern text. +     * @param string $name The pattern +     */ +    public function setName($name) { +        $this->name = (string) $name; +    } -    function setIf($cond) { +    /** +     * Sets an if-condition property for this pattern to match. +     * @param string $cond +     */ +    public function setIf($cond) {          $this->ifCond = (string) $cond;      } -    function setUnless($cond) { +    /** +     * Sets an unless-condition property for this pattern to match. +     * @param string $cond +     */ +    public function setUnless($cond) {          $this->unlessCond = (string) $cond;      } - -    function getName() { +    /** +     * Get the pattern text. +     * @return string The pattern. +     */ +    public function getName() {          return $this->name;      } - -    function evalName($project) { +    /** +     * Evaluates the pattern. +     * @return string The pattern or null if it is ruled out by a condition.  +     */ +    public function evalName(Project $project) {          return $this->valid($project) ? $this->name : null;      } -    function valid($project) { +    /** +     * Checks whether pattern should be applied based on whether the if and unless +     * properties are set in project. +     * @param Project $project +     * @return boolean +     */ +    public function valid(Project $project) {          if ($this->ifCond !== null && $project->getProperty($this->ifCond) === null) {              return false;          } else if ($this->unlessCond !== null && $project->getProperty($this->unlessCond) !== null) { @@ -429,8 +470,11 @@ class PatternSetNameEntry {          return true;      } - -    function toString() { +    /** +     * Gets a string representation of this pattern. +     * @return string +     */ +    public function toString() {          $buf = $this->name;          if (($this->ifCond !== null) || ($this->unlessCond !== null)) {              $buf .= ":"; diff --git a/buildscripts/phing/classes/phing/types/PearPackageFileSet.php b/buildscripts/phing/classes/phing/types/PearPackageFileSet.php new file mode 100644 index 00000000..8cf99b28 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/PearPackageFileSet.php @@ -0,0 +1,179 @@ +<?php +/** + * Part of phing, the PHP build tool + * + * PHP version 5 + * + * @category Types + * @package  phing.types + * @author   Christian Weiske <cweiske@cweiske.de> + * @license  LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @version  SVN: $Id: 5ba010b83645d0ea709761a3d8260fc013239458 $ + * @link     http://www.phing.info/ + */ +require_once 'phing/types/FileSet.php'; +require_once 'PEAR/Config.php'; +require_once 'phing/util/PearPackageScanner.php'; + +/** + * Fileset that contains files of an installed PEAR package. + * It can be used to package up PEAR package dependencies in own + * release files (zip, tgz, phar). + * + * @internal + * A normal fileset is used that way in CopyTask, rSTTask: + * <code> + *  $ds = $fs->getDirectoryScanner($project); + *  $fromDir  = $fs->getDir($project); + *  $srcFiles = $ds->getIncludedFiles(); + *  $srcDirs  = $ds->getIncludedDirectories(); + * </code> + * The scanner is used as follows: + * <code> + *  $ds->getBaseDir() + *  $ds->scan() + * </code> + * + * @category Types + * @package  phing.types + * @author   Christian Weiske <cweiske@cweiske.de> + * @license  LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link     http://www.phing.info/ + */ +class PearPackageFileSet extends FileSet +{ +    /** +     * Name of channel the package is from, e.g. "pear.php.net". +     * +     * @var string +     */ +    protected $channel; + +    /** +     * Package name to get files from, e.g. "Console_CommandLine" +     * +     * @var string +     */ +    protected $package; + +    /** +     * Use files of that role only. +     * Multiple roles are not supported, and you always have to specify one. +     * +     * @var string +     */ +    protected $role = 'php'; + +    /** +     * Prefix to prepend to the file paths in the zip +     */ +    protected $prefix; + +    /** +     * Full path to a PEAR config file. +     * If none provided, default one is used. +     */ +    protected $config; + +    /** +     * @var PearPackageScanner instance +     */ +    protected $pps; + + +    /** +     * Creates and returns the pear package scanner. +     * Scanner already has scan() called. +     * +     * @param Project $project Current phing project +     * +     * @return PearPackageScanner +     */ +    public function getDirectoryScanner(Project $project) +    { +        if ($this->isReference()) { +            $obj = $this->getRef($project); +            return $obj->getDirectoryScanner($project); +        } + +        $this->loadPearPackageScanner(); +        return $this->pps; +    } + +    /** +     * Returns the base directory all package files are relative to +     * +     * @return PhingFile Base directory +     */ +    public function getDir() +    { +        if ($this->pps === null) { +            $this->loadPearPackageScanner(); +        } +        return new PhingFile((string) $this->pps->getBaseDir()); +    } + +    /** +     * Loads the package scanner instance into $this->pps +     * +     * @return void +     */ +    protected function loadPearPackageScanner() +    { +        $this->pps = new PearPackageScanner(); +        $this->pps->setPackage($this->package); +        $this->pps->setChannel($this->channel); +        $this->pps->setRole($this->role); +        $this->pps->setConfig($this->config); +        $this->pps->scan(); +    } + +    /** +     * Sets the package name. +     * If no channel is given, "pear.php.net" is used. +     * +     * @param string $package Single package name, or "channel/name" combination +     * +     * @return void +     */ +    public function setPackage($package) +    { +        $parts = explode('/', $package); +        if (count($parts) > 2) { +            throw new BuildException('Invalid package name: ' . $package); +        } + +        if (count($parts) == 1) { +            $this->channel = 'pear.php.net'; +            $this->package = $parts[0]; +        } else { +            $this->channel = $parts[0]; +            $this->package = $parts[1]; +        } +    } + +    /** +     * Sets the role of files that should be included. +     * Examples are php,doc,script +     * +     * @param string $role PEAR file role +     * +     * @return void +     */ +    public function setRole($role) +    { +        $this->role = $role; +    } + +    /** +     * Sets the full path to the PEAR configuration file +     * +     * @param string $config Configuration file +     * +     * @return void +     */ +    public function setConfig($config) +    { +        $this->config = $config; +    } +} diff --git a/buildscripts/phing/classes/phing/types/PhingFilterReader.php b/buildscripts/phing/classes/phing/types/PhingFilterReader.php index eb45f894..2337977a 100644..100755 --- a/buildscripts/phing/classes/phing/types/PhingFilterReader.php +++ b/buildscripts/phing/classes/phing/types/PhingFilterReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PhingFilterReader.php,v 1.9 2005/10/05 20:23:22 hlellelid Exp $ + *  $Id: fee06c9abce6700d773004bd83a5312d94c5aa29 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,15 +22,15 @@  include_once 'phing/types/DataType.php';  include_once 'phing/types/Parameter.php'; -/* +/**   * A PhingFilterReader is a wrapper class that encloses the className   * and configuration of a Configurable FilterReader.   *   * @author    Yannick Lecaillez <yl@seasonfive.com> - * @version   $Revision: 1.9 $ + * @version   $Id$   * @see       FilterReader   * @package   phing.types -*/ + */  class PhingFilterReader extends DataType {      private $className; @@ -84,16 +84,16 @@ class PhingFilterReader extends DataType {          $o = $this->createClasspath();          $o->setRefid($r);      } -	 -	function addParam(Parameter $param) { -		$this->parameters[] = $param; -	} +     +    function addParam(Parameter $param) { +        $this->parameters[] = $param; +    }      function createParam() {          $num = array_push($this->parameters, new Parameter());          return $this->parameters[$num-1];      } -		 +              function getParams() {          // We return a COPY          $ret = array(); @@ -133,4 +133,4 @@ class PhingFilterReader extends DataType {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/types/Reference.php b/buildscripts/phing/classes/phing/types/Reference.php index c226917d..5f490b3f 100644 --- a/buildscripts/phing/classes/phing/types/Reference.php +++ b/buildscripts/phing/classes/phing/types/Reference.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: Reference.php,v 1.4 2003/12/24 12:38:42 hlellelid Exp $ + * $Id: 48c142f41717a31654d5cbfdb37f339e84adf391 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -53,4 +53,4 @@ class Reference {          return $o;      }  } -?> + diff --git a/buildscripts/phing/classes/phing/types/RegularExpression.php b/buildscripts/phing/classes/phing/types/RegularExpression.php index 67850c23..84a25591 100644..100755 --- a/buildscripts/phing/classes/phing/types/RegularExpression.php +++ b/buildscripts/phing/classes/phing/types/RegularExpression.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: RegularExpression.php,v 1.6 2003/12/24 12:38:42 hlellelid Exp $ + *  $Id: 257bd788b6185a3561f10a8de40502473076b6dd $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,7 +23,7 @@ include_once 'phing/types/DataType.php';  include_once 'phing/Project.php';  include_once 'phing/util/regexp/Regexp.php'; -/* +/**   * A regular expression datatype.  Keeps an instance of the   * compiled expression for speed purposes.  This compiled   * expression is lazily evaluated (it is compiled the first @@ -31,7 +31,7 @@ include_once 'phing/util/regexp/Regexp.php';   * regular expression type you are using.   *   * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> - * @version   $Revision: 1.6 $ $Date: 2003/12/24 12:38:42 $ + * @version   $Id$   * @access    public   * @see       phing.util.regex.RegexMatcher   * @package   phing.types @@ -39,7 +39,14 @@ include_once 'phing/util/regexp/Regexp.php';  class RegularExpression extends DataType {      private $regexp   = null; +    /** +     * @todo Probably both $ignoreCase and $multiline should be removed +     * from attribute list of RegularExpression class:  +     * actual values are preserved on regexp *engine* level, not expression +     * object itself. +     */      private $ignoreCase = false; +    private $multiline = false;      function __construct() {          $this->regexp  = new Regexp(); @@ -52,7 +59,7 @@ class RegularExpression extends DataType {      function setReplace($replace) {          $this->regexp->setReplace($replace);      } -     +      function getPattern($p) {          if ( $this->isReference() ) {              $ref = $this->getRef($p); @@ -69,6 +76,14 @@ class RegularExpression extends DataType {          return $this->regexp->getReplace();      } + +    function setModifiers($modifiers) { +        $this->regexp->setModifiers($modifiers); +    } + +    function getModifiers() { +        return $this->regexp->getModifiers(); +    }      function setIgnoreCase($bit) {          $this->regexp->setIgnoreCase($bit); @@ -77,6 +92,14 @@ class RegularExpression extends DataType {      function getIgnoreCase() {          return $this->regexp->getIgnoreCase();      } + +    function setMultiline($multiline) { +        $this->regexp->setMultiline($multiline); +    } + +    function getMultiline() { +        return $this->regexp->getMultiline(); +    }      function getRegexp(Project $p) {          if ( $this->isReference() ) { @@ -102,4 +125,4 @@ class RegularExpression extends DataType {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/types/TokenReader.php b/buildscripts/phing/classes/phing/types/TokenReader.php index acd7d616..98ed3083 100644..100755 --- a/buildscripts/phing/classes/phing/types/TokenReader.php +++ b/buildscripts/phing/classes/phing/types/TokenReader.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TokenReader.php,v 1.5 2003/12/24 12:38:42 hlellelid Exp $ + *  $Id: c267e1935c57a372e5b8fc07eef73bd084195e82 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ include_once 'phing/filters/ReplaceTokens.php'; // For class Token   * Abstract class for TokenReaders.   *    * @author    Manuel Holtgewe - * @version   $Revision: 1.5 $ + * @version   $Id$   * @package   phing.filters.util   */  abstract class TokenReader { @@ -63,4 +63,4 @@ abstract class TokenReader {  } -?> + diff --git a/buildscripts/phing/classes/phing/types/TokenSource.php b/buildscripts/phing/classes/phing/types/TokenSource.php index c073ece0..0ca0367a 100644 --- a/buildscripts/phing/classes/phing/types/TokenSource.php +++ b/buildscripts/phing/classes/phing/types/TokenSource.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: TokenSource.php,v 1.7 2004/03/18 20:44:26 hlellelid Exp $ + *  $Id: 1bc91e925ce194c2e7a615e8f8c950d2057a9cb5 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -93,9 +93,9 @@ class TokenSource extends DataType {                  $this->tokens[] = $token;              }          } catch (BuildException $e) { -            $this->log("Error reading TokenSource: " . $e->getMessage(), PROJECT_MSG_WARN); +            $this->log("Error reading TokenSource: " . $e->getMessage(), Project::MSG_WARN);          } catch (IOException $e) { -            $this->log("Error reading TokenSource: " . $e->getMessage(), PROJECT_MSG_WARN); +            $this->log("Error reading TokenSource: " . $e->getMessage(), Project::MSG_WARN);          }      } @@ -154,4 +154,4 @@ class TokenSource extends DataType {  } -?> + diff --git a/buildscripts/phing/classes/phing/types/selectors/AndSelector.php b/buildscripts/phing/classes/phing/types/selectors/AndSelector.php index 3801091f..1a27829d 100644 --- a/buildscripts/phing/classes/phing/types/selectors/AndSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/AndSelector.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: AndSelector.php,v 1.9 2005/05/26 13:10:53 mrook Exp $ + * $Id: f36556afb9487cce2e56d5c174e3ce4c43ef968f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php b/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php index 5acc54dd..d8ae0444 100644 --- a/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: BaseExtendSelector.php,v 1.5 2004/02/16 05:28:40 hlellelid Exp $ + * $Id: 0c36c2b00f8ab8d20025b9ad38043c762b6fc7f9 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php b/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php index e229fc24..c463fa33 100644 --- a/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: BaseSelector.php,v 1.4 2004/02/16 04:56:24 hlellelid Exp $ + * $Id: e1f8e20eb87ea465d29ba3add6fada790642bcf8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php b/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php index 19b84b00..3b2a10b1 100644 --- a/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php +++ b/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: BaseSelectorContainer.php,v 1.9 2004/02/16 04:56:24 hlellelid Exp $ + * $Id: 9dd90d3e78d751562859bbe5179db148ee5b025c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php b/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php index 39afd2fa..5b45bac8 100644..100755 --- a/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: ContainsRegexpSelector.php,v 1.3 2005/05/26 13:10:53 mrook Exp $ + * $Id: 2a891d7cc3fb1b710b72d51e6a8cf2d0b553f91a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ include_once 'phing/types/RegularExpression.php';   *    * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Bruce Atherton <bruce@callenish.com> (Ant) - * @version   $Revision: 1.3 $ + * @version   $Id$   * @package   phing.types.selectors   */  class ContainsRegexpSelector extends BaseExtendSelector { diff --git a/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php b/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php index d00ce995..5e270583 100644 --- a/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: ContainsSelector.php,v 1.9 2005/05/26 13:10:53 mrook Exp $ + * $Id: ab2c641c048573b0a9976b7cb92138b8ceda511f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/DateSelector.php b/buildscripts/phing/classes/phing/types/selectors/DateSelector.php index 96e5c3ba..0f8c28a8 100644..100755 --- a/buildscripts/phing/classes/phing/types/selectors/DateSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/DateSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: DateSelector.php,v 1.10 2005/05/26 13:10:53 mrook Exp $ + * $Id: f05cee91082616c66b2e109157b1d2f2298a66f8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,8 +29,8 @@ require_once 'phing/types/selectors/BaseExtendSelector.php';   *   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Bruce Atherton <bruce@callenish.com> (Ant) - * @version   $Revision: 1.10 $ - * @package   phing.types.selecctors + * @version   $Id: f05cee91082616c66b2e109157b1d2f2298a66f8 $ + * @package   phing.types.selectors   */  class DateSelector extends BaseExtendSelector { @@ -203,7 +203,7 @@ class DateSelector extends BaseExtendSelector {          if ($this->cmp === 0) {              return (($file->lastModified() - $this->granularity) < $this->seconds);          } elseif ($this->cmp === 1) { -            return (($file->lastModified() . $this->granularity) > $this->seconds); +            return (($file->lastModified() - $this->granularity) > $this->seconds);          } else {              return (abs($file->lastModified() -  $this->seconds) <= $this->granularity);          } diff --git a/buildscripts/phing/classes/phing/types/selectors/DependSelector.php b/buildscripts/phing/classes/phing/types/selectors/DependSelector.php index db73c512..3b869199 100644..100755 --- a/buildscripts/phing/classes/phing/types/selectors/DependSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/DependSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: DependSelector.php,v 1.8 2005/05/26 13:10:53 mrook Exp $ + * $Id: eac9e808c89c2a8f414f86afc589eda4f218dd6e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -30,7 +30,7 @@ require_once 'phing/types/selectors/BaseSelector.php';   *   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Bruce Atherton <bruce@callenish.com> (Ant) - * @version   $Revision: 1.8 $ + * @version   $Id$   * @package   phing.types.selectors   */  class DependSelector extends BaseSelector { diff --git a/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php b/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php index 3faafe96..0ad6c8eb 100644..100755 --- a/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: DepthSelector.php,v 1.7 2005/05/26 13:10:53 mrook Exp $ + * $Id: 9c244177a7f95995cd30c67c9fee47c1e977e4e2 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/types/selectors/BaseExtendSelector.php';   *   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Bruce Atherton <bruce@callenish.com> (Ant) - * @version   $Revision: 1.7 $ + * @version   $Id$   * @package   phing.types.selectors   */  class DepthSelector extends BaseExtendSelector { diff --git a/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php b/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php index 84a3ee5b..8394387c 100644 --- a/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: ExtendFileSelector.php,v 1.5 2004/02/16 05:28:40 hlellelid Exp $ + * $Id: dc3c5cb2a3043b7a3f7600591ce825b6563ec0ce $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php b/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php index cc939254..1204ef12 100644 --- a/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: ExtendSelector.php,v 1.10 2005/05/26 13:10:53 mrook Exp $ + * $Id: 1683a0a93b4bb5486f3cffbe40e8260f886c6258 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,11 +25,11 @@ include_once 'phing/util/StringHelper.php';  /**   * Selector that selects files by forwarding the request on to other classes.   * - * TODO: - *        Consider adding Path (org.apache.tools.ant.types.Path) support to this class + * TODO - Consider adding Path (phing.types.Path) support to this class   *         and to the Mappers class.  See Ant versions for implimentation details. - * - * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> + *  + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant)   * @package phing.types.selectors   */  class ExtendSelector extends BaseSelector { @@ -105,10 +105,7 @@ class ExtendSelector extends BaseSelector {      /**       * Allows the custom selector to choose whether to select a file. This -     * is also where the Parameters are passed to the custom selector, -     * since we know we must have them all by now. And since we must know -     * both classpath and classname, creating the class is deferred to here -     * as well. +     * is also where the Parameters are passed to the custom selector.       *       * @throws BuildException       */ diff --git a/buildscripts/phing/classes/phing/types/selectors/FileSelector.php b/buildscripts/phing/classes/phing/types/selectors/FileSelector.php index 05926c86..3c014d61 100644 --- a/buildscripts/phing/classes/phing/types/selectors/FileSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/FileSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: FileSelector.php,v 1.4 2005/05/26 13:10:53 mrook Exp $ + * $Id: 26b8712469a798faf79d1c877aad89d64880f061 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php b/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php index 2315c888..04abbe2e 100644 --- a/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: FilenameSelector.php,v 1.8 2005/05/26 13:10:53 mrook Exp $ + * $Id: d0a6af11eeda50b911bad3717528a9ea72291185 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php b/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php index 19e0fb76..5ad2629e 100644 --- a/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: MajoritySelector.php,v 1.6 2005/05/26 13:10:53 mrook Exp $ + * $Id: 9071d88eb880abe5a299f7c5db707d4439ccaa6c $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php b/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php index 844078a5..f8941208 100644 --- a/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: NoneSelector.php,v 1.6 2005/05/26 13:10:53 mrook Exp $ + * $Id: a085187a008c4d8e8ba25fd6f1315b3dee92ec27 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/NotSelector.php b/buildscripts/phing/classes/phing/types/selectors/NotSelector.php index 90237084..08e70a5a 100644 --- a/buildscripts/phing/classes/phing/types/selectors/NotSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/NotSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: NotSelector.php,v 1.4 2003/12/24 17:43:26 hlellelid Exp $ + * $Id: 8dcce9d2d304b7a8d4be0ef5b5111b582846840d $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/OrSelector.php b/buildscripts/phing/classes/phing/types/selectors/OrSelector.php index 6a8778fa..56e6df1e 100644 --- a/buildscripts/phing/classes/phing/types/selectors/OrSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/OrSelector.php @@ -1,6 +1,6 @@  <?php  /* - * $Id: OrSelector.php,v 1.7 2005/05/26 13:10:53 mrook Exp $ + * $Id: bfed3cc534a3e1ab8789f0ed4a6e64419979e21a $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php b/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php index f5f4c880..462d3927 100644 --- a/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: PresentSelector.php,v 1.9 2005/05/26 13:10:53 mrook Exp $ + * $Id: db4c8bc8217483d4150b2d9e62d2ef5129038b4e $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -92,8 +92,8 @@ class PresentSelector extends BaseSelector {       * that already exist in the source directory, hence the lack of       * a <code>destonly</code> option.       * -     * @param string $fp An attribute set to either <code>srconly</code or -     *           ><code>both</code>. +     * @param string $fp An attribute set to either <code>srconly</code> or +     *           <code>both</code>.       */      public function setPresent($fp) {          $idx = array_search($fp, self::$filePresence, true); diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php b/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php index a7644447..0db73e5d 100644..100755 --- a/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: SelectSelector.php,v 1.6 2003/12/24 17:43:26 hlellelid Exp $ + * $Id: aa3a5cceea362713959333bda113e0ca5428a530 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -32,7 +32,7 @@ require_once 'phing/types/selectors/AndSelector.php';   *   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Bruce Atherton <bruce@callenish.com> (Ant) - * @version   $Revision: 1.6 $ + * @version   $Id$   * @package   phing.types.selectors   */  class SelectSelector extends AndSelector { diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php b/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php index 4a73b113..0ee42237 100644 --- a/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php +++ b/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: SelectorContainer.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $ + * $Id: 6fedde4695e4838f435f336b7936190b16429706 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php b/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php index f5bb898a..91fc3f4c 100644 --- a/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php +++ b/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: SelectorScanner.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $ + * $Id: 3c28c4c2e4c41cf4507870e472ed9f278e2d9c9f $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php b/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php index 87247e97..2d7e5068 100644 --- a/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php +++ b/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: SelectorUtils.php,v 1.5 2005/05/26 13:10:53 mrook Exp $ + * $Id: 4a682bbe8751f6e09a725af7cfdf2bd17ab00645 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -43,7 +43,7 @@ class SelectorUtils {       /**        * Retrieves the instance of the Singleton.        */ -    public function getInstance() { +    public static function getInstance() {          if (!isset(self::$instance)) {              self::$instance = new SelectorUtils();          } @@ -68,7 +68,7 @@ class SelectorUtils {       * @return whether or not a given path matches the start of a given       * pattern up to the first "**".       */ -    public function matchPatternStart($pattern, $str, $isCaseSensitive = true) { +    public static function matchPatternStart($pattern, $str, $isCaseSensitive = true) {          // When str starts with a DIRECTORY_SEPARATOR, pattern has to start with a          // DIRECTORY_SEPARATOR. @@ -126,120 +126,22 @@ class SelectorUtils {       * @return <code>true</code> if the pattern matches against the string,       *         or <code>false</code> otherwise.       */ -    public function matchPath($pattern, $str, $isCaseSensitive = true) { +    public static function matchPath($pattern, $str, $isCaseSensitive = true) { -        // When str starts with a DIRECTORY_SEPARATOR, pattern has to start with a -        // DIRECTORY_SEPARATOR. -        // When pattern starts with a DIRECTORY_SEPARATOR, str has to start with a -        // DIRECTORY_SEPARATOR. -        if (StringHelper::startsWith(DIRECTORY_SEPARATOR, $str) !== -            StringHelper::startsWith(DIRECTORY_SEPARATOR, $pattern)) { -            return false; -        } - -        $patDirs = explode(DIRECTORY_SEPARATOR, $pattern); -        $strDirs = explode(DIRECTORY_SEPARATOR, $str); - -        $patIdxStart = 0; -        $patIdxEnd   = count($patDirs)-1; -        $strIdxStart = 0; -        $strIdxEnd   = count($strDirs)-1; -         -        // up to first '**' -        while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) { -            $patDir = $patDirs[$patIdxStart]; -            if ($patDir == "**") { -                break; -            } -            if (!self::match($patDir, $strDirs[$strIdxStart], $isCaseSensitive)) { -                return false; -            } -            $patIdxStart++; -            $strIdxStart++; -        } -        if ($strIdxStart > $strIdxEnd) { -            // String is exhausted -            for ($i=$patIdxStart; $i <= $patIdxEnd; $i++) { -                if ($patDirs[$i] != "**") { -                    return false; -                } -            } -            return true; -        } elseif ($patIdxStart > $patIdxEnd) { -            // String not exhausted, but pattern is. Failure. -            return false; -        } - -        // up to last '**' -        while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) { -            $patDir = $patDirs[$patIdxEnd]; -            if ($patDir == "**") { -                break; -            } -            if (!self::match($patDir, $strDirs[$strIdxEnd], $isCaseSensitive)) { -                return false; -            } -            $patIdxEnd--; -            $strIdxEnd--; -        } -         -        if ($strIdxStart > $strIdxEnd) { -            // String is exhausted -            for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { -                if ($patDirs[$i] != "**") { -                    return false; -                } -            } -            return true; -        } - -        while ($patIdxStart != $patIdxEnd && $strIdxStart <= $strIdxEnd) { -            $patIdxTmp = -1; -            for ($i = $patIdxStart+1; $i <= $patIdxEnd; $i++) { -                if ($patDirs[$i] == "**") { -                    $patIdxTmp = $i; -                    break; -                } -            } -            if ($patIdxTmp == $patIdxStart+1) { -                // '**/**' situation, so skip one -                $patIdxStart++; -                continue; -            } -            // Find the pattern between padIdxStart & padIdxTmp in str between -            // strIdxStart & strIdxEnd -            $patLength = ($patIdxTmp-$patIdxStart-1); -            $strLength = ($strIdxEnd-$strIdxStart+1); -            $foundIdx  = -1; - -            //strLoop:    (start of outer loop) -            for ($i=0; $i <= $strLength - $patLength; $i++) {                 -                for ($j = 0; $j < $patLength; $j++) { -                    $subPat = $patDirs[$patIdxStart+$j+1]; -                    $subStr = $strDirs[$strIdxStart+$i+$j]; -                    if (!self::match($subPat, $subStr, $isCaseSensitive)) { -                        continue 2; // continue up two levels (to strLoop:) -                    } -                }                                 -                $foundIdx = $strIdxStart+$i; // only reached if all sub patterns matched -                break; -            } - -            if ($foundIdx == -1) { -                return false; -            } - -            $patIdxStart = $patIdxTmp; -            $strIdxStart = $foundIdx + $patLength; -        } - -        for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { -            if ($patDirs[$i] != "**") { -                return false; -            } -        } - -        return true; +        $rePattern = preg_quote($pattern, '/'); +        $dirSep = preg_quote(DIRECTORY_SEPARATOR, '/'); +        $trailingDirSep = '(('.$dirSep.')?|('.$dirSep.').+)'; +        $patternReplacements = array( +            $dirSep.'\*\*'.$dirSep => $dirSep.'.*'.$trailingDirSep, +            $dirSep.'\*\*' => $trailingDirSep, +            '\*\*'.$dirSep => '.*'.$trailingDirSep, +            '\*\*' => '.*', +            '\*' => '[^'.$dirSep.']*', +            '\?' => '[^'.$dirSep.']' +        ); +        $rePattern = str_replace(array_keys($patternReplacements), array_values($patternReplacements), $rePattern); +        $rePattern = '/^'.$rePattern.'$/'.($isCaseSensitive ? '' : 'i'); +        return (bool) preg_match($rePattern, $str);      }      /** @@ -259,154 +161,12 @@ class SelectorUtils {       * @return <code>true</code> if the string matches against the pattern,       *         or <code>false</code> otherwise.       */ -    public function match($pattern, $str, $isCaseSensitive = true) { +    public static function match($pattern, $str, $isCaseSensitive = true) { -        $patArr = StringHelper::toCharArray($pattern); -        $strArr = StringHelper::toCharArray($str); -        $patIdxStart = 0; -        $patIdxEnd   = count($patArr)-1; -        $strIdxStart = 0; -        $strIdxEnd   = count($strArr)-1; -         -        $containsStar = false; -        for ($i = 0, $size=count($patArr); $i < $size; $i++) { -            if ($patArr[$i] == '*') { -                $containsStar = true; -                break; -            } -        } - -        if (!$containsStar) { -            // No '*'s, so we make a shortcut -            if ($patIdxEnd != $strIdxEnd) { -                return false; // Pattern and string do not have the same size -            } -            for ($i = 0; $i <= $patIdxEnd; $i++) { -                $ch = $patArr[$i]; -                if ($ch != '?') { -                    if ($isCaseSensitive && $ch !== $strArr[$i]) { -                        return false;// Character mismatch -                    } -                    if (!$isCaseSensitive && strtoupper($ch) !== -                        strtoupper($strArr[$i])) { -                        return false; // Character mismatch -                    } -                } -            } -            return true; // String matches against pattern -        } - -        if ($patIdxEnd == 0) { -            return true; // Pattern contains only '*', which matches anything -        } - -        // Process characters before first star -        while(($ch = $patArr[$patIdxStart]) != '*' && $strIdxStart <= $strIdxEnd) { -            if ($ch != '?') { -                if ($isCaseSensitive && $ch !== $strArr[$strIdxStart]) { -                    return false;// Character mismatch -                } -                if (!$isCaseSensitive && strtoupper($ch) !== -                    strtoupper($strArr[$strIdxStart])) { -                    return false;// Character mismatch -                } -            } -            $patIdxStart++; -            $strIdxStart++; -        } -         -        if ($strIdxStart > $strIdxEnd) { -            // All characters in the string are used. Check if only '*'s are -            // left in the pattern. If so, we succeeded. Otherwise failure. -            for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { -                if ($patArr[$i] != '*') { -                    return false; -                } -            } -            return true; -        } - -        // Process characters after last star -        while(($ch = $patArr[$patIdxEnd]) != '*' && $strIdxStart <= $strIdxEnd) { -            if ($ch != '?') { -                if ($isCaseSensitive && $ch !== $strArr[$strIdxEnd]) { -                    return false;// Character mismatch -                } -                if (!$isCaseSensitive && strtoupper($ch) !== -                    strtoupper($strArr[$strIdxEnd])) { -                    return false;// Character mismatch -                } -            } -            $patIdxEnd--; -            $strIdxEnd--; -        } -        if ($strIdxStart > $strIdxEnd) { -            // All characters in the string are used. Check if only '*'s are -            // left in the pattern. If so, we succeeded. Otherwise failure. -            for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { -                if ($patArr[$i] != '*') { -                    return false; -                } -            } -            return true; -        } - -        // process pattern between stars. padIdxStart and patIdxEnd point -        // always to a '*'. -        while ($patIdxStart !== $patIdxEnd && $strIdxStart <= $strIdxEnd) { -            $patIdxTmp = -1; -            for ($i = $patIdxStart+1; $i <= $patIdxEnd; $i++) { -                if ($patArr[$i] == '*') { -                    $patIdxTmp = $i; -                    break; -                } -            } -            if ($patIdxTmp === $patIdxStart + 1) { -                // Two stars next to each other, skip the first one. -                $patIdxStart++; -                continue; -            } -            // Find the pattern between padIdxStart & padIdxTmp in str between -            // strIdxStart & strIdxEnd -            $patLength = ($patIdxTmp - $patIdxStart - 1); -            $strLength = ($strIdxEnd - $strIdxStart + 1); -            $foundIdx  = -1; -             -            //strLoop: -            for ($i = 0; $i <= $strLength - $patLength; $i++) { -                for ($j = 0; $j < $patLength; $j++) { -                    $ch = $patArr[$patIdxStart+$j+1]; -                    if ($ch != '?') { -                        if ($isCaseSensitive && $ch !== $strArr[$strIdxStart+$i+$j]) { -                               continue 2; //continue to strLoop: -                        } -                        if (!$isCaseSensitive && strtoupper($ch) !== -                            strtoupper($strArr[$strIdxStart+$i+$j])) { -                               continue 2; //continue to strLoop: -                        } -                    } -                } -                // only reached if sub loop completed w/o invoking continue 2 -                $foundIdx = $strIdxStart + $i; -                break; -            } - -            if ($foundIdx == -1) { -                return false; -            } - -            $patIdxStart = $patIdxTmp; -            $strIdxStart = $foundIdx + $patLength; -        } - -        // All characters in the string are used. Check if only '*'s are left -        // in the pattern. If so, we succeeded. Otherwise failure. -        for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { -            if ($patArr[$i] != '*') { -                return false; -            } -        } -        return true; +        $rePattern = preg_quote($pattern, '/'); +        $rePattern = str_replace(array("\*", "\?"), array('.*', '.'), $rePattern); +        $rePattern = '/^'.$rePattern.'$/'.($isCaseSensitive ? '' : 'i'); +        return (bool) preg_match($rePattern, $str);      }      /** @@ -423,7 +183,7 @@ class SelectorUtils {       *        determining out of dateness       * @return whether the target is out of date       */ -    public function isOutOfDate(PhingFile $src, PhingFile $target, $granularity) { +    public static function isOutOfDate(PhingFile $src, PhingFile $target, $granularity) {          if (!$src->exists()) {              return false;          } diff --git a/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php b/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php index bbc26423..3aaf8a92 100644 --- a/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: SizeSelector.php,v 1.8 2005/05/26 13:10:53 mrook Exp $ + * $Id: 4969c98a4e03305a23770e2afd5da641999f6174 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php b/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php index f1532308..6ff024e8 100644..100755 --- a/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php +++ b/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php @@ -1,7 +1,7 @@  <?php  /* - * $Id: TypeSelector.php,v 1.3 2005/05/26 13:10:53 mrook Exp $ + * $Id: 95c34bb6a364dc0131e9e9c5c124d5074b4a2a21 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,10 +24,10 @@ require_once 'phing/types/selectors/BaseExtendSelector.php';  /**   * Selector that selects a certain kind of file: directory or regular file. - *  + *   * @author    Hans Lellelid <hans@xmpl.org> (Phing)   * @author    Jeff Turner <jefft@apache.org> (Ant) - * @version   $Revision: 1.3 $ + * @version   $Id: 95c34bb6a364dc0131e9e9c5c124d5074b4a2a21 $   * @package   phing.types.selectors   */  class TypeSelector extends BaseExtendSelector { @@ -36,10 +36,10 @@ class TypeSelector extends BaseExtendSelector {      /** Key to used for parameterized custom selector */      const TYPE_KEY = "type"; -     +      /** Valid types */ -    private static $types = array('file', 'dir'); -     +    private static $types = array('file', 'dir', 'link'); +      /**       * @return string A string describing this object       */ @@ -52,7 +52,7 @@ class TypeSelector extends BaseExtendSelector {       * Set the type of file to require.       * @param string $type The type of file - 'file' or 'dir'       */ -    public function setType($type) {        +    public function setType($type) {          $this->type = $type;      } @@ -99,11 +99,18 @@ class TypeSelector extends BaseExtendSelector {       * @return boolean Whether the file should be selected or not       */      public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { -          // throw BuildException on error          $this->validate(); -        if ($file->isDirectory()) { +		if ($file->isLink()) { +			if ($this->type == 'link') +				return true; + +			$this->log($file->getAbsolutePath() . " is a link, proceeding with " . $file->getCanonicalPath() . " instead.", Project::MSG_DEBUG); +			$file = new PhingFile($file->getCanonicalPath()); +		} + +		if ($file->isDirectory()) {              return $this->type === 'dir';          } else {              return $this->type === 'file'; diff --git a/buildscripts/phing/classes/phing/util/DataStore.php b/buildscripts/phing/classes/phing/util/DataStore.php new file mode 100755 index 00000000..af696697 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/DataStore.php @@ -0,0 +1,151 @@ +<?php + +/* + *  $Id: 77f24d8b9d8082b4c23cb4cd5d23a06a3be88e2d $ + * + * 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/system/io/PhingFile.php'; +require_once 'phing/system/io/FileWriter.php'; + +/** + * An abstract representation of file and directory pathnames. + * + * @package phing.util + * @author  Michiel Rook <mrook@php.net> + * @version $Id$ + */ +class DataStore +{ +    private $data = array();     +    private $file = null; +     +    /** +     * Constructs a new data store +     * +     * @param PhingFile $file object pointing to the data store on disk +     */ +    function __construct(PhingFile $file) +    { +        $this->file = $file; +         +        if ($this->file->exists()) +        { +            $this->read(); +        } +    } +     +    /** +     * Destructor +     */ +    function __destruct() +    { +        $this->commit(); +    } +     +    /** +     * Retrieves a value from the data store +     * +     * @param string $key the key +     * +     * @return mixed the value +     */ +    public function get($key) +    { +        if (!isset($this->data[$key])) +        { +            return null; +        } +        else +        { +            return $this->data[$key]; +        } +    } +     +    /** +     * Adds a value to the data store +     * +     * @param string  $key        the key +     * @param mixed   $value      the value +     * @param boolean $autocommit whether to auto-commit (write)  +     *                            the data store to disk +     * +     * @return none +     */ +    public function put($key, $value, $autocommit = false) +    { +        $this->data[$key] = $value; +         +        if ($autocommit) +        { +            $this->commit(); +        } +    } +     +    /** +     * Commits data store to disk +     * +     * @return none +     */ +    public function commit() +    { +        $this->write(); +    } +     +    /** +     * Internal function to read data store from file +     * +     * @return none +     */ +    private function read() +    { +        if (!$this->file->canRead()) +        { +            throw new BuildException("Can't read data store from '" .  +                $file->getPath() . "'"); +        } +        else +        { +            $serializedData = $this->file->contents(); +             +            $this->data = unserialize($serializedData); +        } +    } + +    /** +     * Internal function to write data store to file +     * +     * @return none +     */ +    private function write() +    { +        if (!$this->file->canWrite()) +        { +            throw new BuildException("Can't write data store to '" .  +                $file->getPath() . "'"); +        } +        else +        { +            $serializedData = serialize($this->data); + +            $writer = new FileWriter($this->file); +            $writer->write($serializedData); +            $writer->close(); +        } +    }     +}; diff --git a/buildscripts/phing/classes/phing/util/DirectoryScanner.php b/buildscripts/phing/classes/phing/util/DirectoryScanner.php index e04c4880..02d5be88 100644..100755 --- a/buildscripts/phing/classes/phing/util/DirectoryScanner.php +++ b/buildscripts/phing/classes/phing/util/DirectoryScanner.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: DirectoryScanner.php,v 1.15 2005/12/13 21:56:26 hlellelid Exp $ + *  $Id: 7aef4b4e372e89055248ab063660dbee92a98cc3 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -110,7 +110,7 @@ include_once 'phing/types/selectors/SelectorUtils.php';   *  @author   Magesh Umasankar, umagesh@rediffmail.com   *  @author   Andreas Aderhold, andi@binarycloud.com   * - *  @version   $Revision: 1.15 $ + *  @version   $Id: 7aef4b4e372e89055248ab063660dbee92a98cc3 $   *  @package   phing.util   */  class DirectoryScanner implements SelectorScanner { @@ -127,10 +127,17 @@ class DirectoryScanner implements SelectorScanner {          "**/SCCS",          "**/SCCS/**",          "**/vssver.scc", -		"**/.svn", -		"**/.svn/**", -		"**/._*", -		"**/.DS_Store", +        "**/.svn", +        "**/.svn/**", +        "**/._*", +        "**/.DS_Store", +    	"**/.darcs", +    	"**/.darcs/**", +    	"**/.git", +    	"**/.git/**", +    	"**/.gitattributes", +    	"**/.gitignore", +    	"**/.gitmodules",      );      /** The base directory which should be scanned. */ @@ -141,6 +148,9 @@ class DirectoryScanner implements SelectorScanner {      /** The patterns for the files that should be excluded. */      protected $excludes = null; +     +    /** Whether to expand/dereference symbolic links, default is false */ +    protected $expandSymbolicLinks = false;      /**       * The files that where found and matched at least one includes, and matched @@ -319,6 +329,16 @@ class DirectoryScanner implements SelectorScanner {              }          }      } +     +    /** +     * Sets whether to expand/dereference symbolic links +     * +     * @param expandSymbolicLinks boolean value +     */ +    function setExpandSymbolicLinks($expandSymbolicLinks) +    { +        $this->expandSymbolicLinks = $expandSymbolicLinks; +    }      /**       * Scans the base directory for files that match at least one include @@ -409,7 +429,7 @@ class DirectoryScanner implements SelectorScanner {      function listDir($_dir) {          $d = dir($_dir);          $list = array(); -        while($entry = $d->read()) { +        while(($entry = $d->read()) !== false) {              if ($entry != "." && $entry != "..") {                  $list[] = $entry;              } @@ -449,6 +469,26 @@ class DirectoryScanner implements SelectorScanner {              $file = $_rootdir . DIRECTORY_SEPARATOR . $newfiles[$i];              $name = $_vpath . $newfiles[$i]; +            if (@is_link($file) && !$this->expandSymbolicLinks) +            { +                if ($this->isIncluded($name)) { +                    if (!$this->isExcluded($name)) { +                        if ($this->isSelected($name, $file)) { +                            $this->filesIncluded[] = $name; +                        } else { +                            $this->everythingIncluded = false; +                            $this->filesDeselected[] = $name; +                        }                         +                    } else { +                        $this->everythingIncluded = false; +                        $this->filesExcluded[] = $name; +                    } +                } else { +                    $this->everythingIncluded = false; +                    $this->filesNotIncluded[] = $name; +                } +            } +            else              if (@is_dir($file)) {                  if ($this->isIncluded($name)) {                      if (!$this->isExcluded($name)) { @@ -698,8 +738,13 @@ class DirectoryScanner implements SelectorScanner {       */      protected function isSelected($name, $file) {          if ($this->selectors !== null) { -            for ($i=0,$size=count($this->selectors); $i < $size; $i++) { -                if (($this->selectors[$i]->isSelected(new PhingFile($this->basedir), $name, new PhingFile($file))) === false) { +            $basedir = new PhingFile($this->basedir); +            $file = new PhingFile($file); +            if (!$file->canRead()) +                return false; +             +            foreach($this->selectors as $selector) { +                if (!$selector->isSelected($basedir, $name, $file)) {                      return false;                  }              } diff --git a/buildscripts/phing/classes/phing/util/ExtendedFileStream.php b/buildscripts/phing/classes/phing/util/ExtendedFileStream.php index 5fdcae47..9c09b56f 100644..100755 --- a/buildscripts/phing/classes/phing/util/ExtendedFileStream.php +++ b/buildscripts/phing/classes/phing/util/ExtendedFileStream.php @@ -1,133 +1,129 @@  <?php -	include_once 'phing/system/io/PhingFile.php'; +    include_once 'phing/system/io/PhingFile.php'; -	/** -	 * $Id: ExtendedFileStream.php,v 1.5 2005/12/27 15:51:26 hlellelid Exp $ -	 * -	 * 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>. -	 */ +    /** +     * $Id: f7e4641c758d5e781ad209d3eaf653a20404bf56 $ +     * +     * 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>. +     */ -	/** -	 * Extended file stream wrapper class which auto-creates directories -	 * -	 * @author Michiel Rook <michiel@trendserver.nl> -	 * @version $Id: ExtendedFileStream.php,v 1.5 2005/12/27 15:51:26 hlellelid Exp $ -	 * @package phing.util -	 */ -	class ExtendedFileStream -	{ -		private $fp = NULL; -		 -		static function registerStream() -		{ -			if (!in_array("efile", stream_get_wrappers())) -			{ -				stream_wrapper_register("efile", "ExtendedFileStream"); -			} -		} -		 -		private function createDirectories($path) -		{ -			$f = new PhingFile($path); -			if (!$f->exists()) { -				$f->mkdirs(); -			} -		} -		 -		function stream_open($path, $mode, $options, &$opened_path) -		{ -			/** Small fix for Windows */ -			if ($path[8] == DIRECTORY_SEPARATOR) -			{ -				$filepath = substr($path, 7); -			} -			else -			{ -				$filepath = substr($path, 8); -			} -			 -			$this->createDirectories(dirname($filepath)); -			 -			$this->fp = fopen($filepath, $mode); -			 -			return true; -		} -		 -		function stream_close() -		{ -			fclose($this->fp); -			$this->fp = NULL; -		} -		 -		function stream_read($count) -		{ -			return fread($this->fp, $count); -		} -		 -		function stream_write($data) -		{ -			return fwrite($this->fp, $data); -		} -		 -		function stream_eof() -		{ -			return feof($this->fp); -		} -		 -		function stream_tell() -		{ -			return ftell($this->fp); -		} -		 -		function stream_seek($offset, $whence) -		{ -			return fseek($this->fp, $offset, $whence); -		} -		 -		function stream_flush() -		{ -			return fflush($this->fp); -		} -		 -		function stream_stat() -		{ -			return fstat($this->fp); -		} -		 -		function unlink($path) -		{ -			return FALSE; -		} -		 -		function rename($path_from, $path_to) -		{ -			return FALSE; -		} -		 -		function mkdir($path, $mode, $options) -		{ -			return FALSE; -		} -		 -		function rmdir($path, $options) -		{ -			return FALSE; -		}		 -	}; +    /** +     * Extended file stream wrapper class which auto-creates directories +     * +     * @author Michiel Rook <mrook@php.net> +     * @version $Id: f7e4641c758d5e781ad209d3eaf653a20404bf56 $ +     * @package phing.util +     */ +    class ExtendedFileStream +    { +        private $fp = NULL; +         +        static function registerStream() +        { +            if (!in_array("efile", stream_get_wrappers())) +            { +                stream_wrapper_register("efile", "ExtendedFileStream"); +            } +        } +         +        static function unregisterStream() +        { +            stream_wrapper_unregister("efile"); +        } +         +        private function createDirectories($path) +        { +            $f = new PhingFile($path); +            if (!$f->exists()) { +                $f->mkdirs(); +            } +        } +         +        function stream_open($path, $mode, $options, &$opened_path) +        { +            $filepath = substr($path, 8); +             +            $this->createDirectories(dirname($filepath)); +             +            $this->fp = fopen($filepath, $mode); +             +            return true; +        } +         +        function stream_close() +        { +            fclose($this->fp); +            $this->fp = NULL; +        } +         +        function stream_read($count) +        { +            return fread($this->fp, $count); +        } +         +        function stream_write($data) +        { +            return fwrite($this->fp, $data); +        } +         +        function stream_eof() +        { +            return feof($this->fp); +        } +         +        function stream_tell() +        { +            return ftell($this->fp); +        } +         +        function stream_seek($offset, $whence) +        { +            return fseek($this->fp, $offset, $whence); +        } +         +        function stream_flush() +        { +            return fflush($this->fp); +        } +         +        function stream_stat() +        { +            return fstat($this->fp); +        } +         +        function unlink($path) +        { +            return FALSE; +        } +         +        function rename($path_from, $path_to) +        { +            return FALSE; +        } +         +        function mkdir($path, $mode, $options) +        { +            return FALSE; +        } +         +        function rmdir($path, $options) +        { +            return FALSE; +        }        +    }; -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/util/FileUtils.php b/buildscripts/phing/classes/phing/util/FileUtils.php index 0f5ff19a..c98bbdd3 100644..100755 --- a/buildscripts/phing/classes/phing/util/FileUtils.php +++ b/buildscripts/phing/classes/phing/util/FileUtils.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: FileUtils.php,v 1.10 2005/05/26 13:10:53 mrook Exp $ + *  $Id: fe077b4174763861e773f5e5e55bbfc5030cac4d $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -33,7 +33,7 @@ include_once 'phing/system/io/PhingFile.php';   * - filter stuff   *   * @package  phing.util - * @version  $Revision: 1.10 $ + * @version  $Id$   */  class FileUtils { @@ -46,7 +46,7 @@ class FileUtils {       * @param Project $project       * @return Reader Assembled Reader (w/ filter chains).       */ -    function getChainedReader(Reader $in, &$filterChains, Project $project) { +    public static function getChainedReader(Reader $in, &$filterChains, Project $project) {          if (!empty($filterChains)) {              $crh = new ChainReaderHelper();              $crh->setBufferSize(65536); // 64k buffer, but isn't being used (yet?) @@ -69,9 +69,10 @@ class FileUtils {       * @param boolean $preserveLastModified       * @param array $filterChains        * @param Project $project +     * @param integer $mode       * @return void       */ -    function copyFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite = false, $preserveLastModified = true, &$filterChains = null, Project $project) { +    function copyFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite = false, $preserveLastModified = true, &$filterChains = null, Project $project, $mode = 0755) {          if ($overwrite || !$destFile->exists() || $destFile->lastModified() < $sourceFile->lastModified()) {              if ($destFile->exists() && $destFile->isFile()) { @@ -81,7 +82,7 @@ class FileUtils {              // ensure that parent dir of dest file exists!              $parent = $destFile->getParentFile();              if ($parent !== null && !$parent->exists()) { -                $parent->mkdirs(); +                $parent->mkdirs($mode);              }              if ((is_array($filterChains)) && (!empty($filterChains))) { @@ -98,6 +99,9 @@ class FileUtils {                      $in->close();                  if ( $out !== null )                      $out->close(); + +                $destFile->setMode($sourceFile->getMode()); +              } else {                  // simple copy (no filtering)                  $sourceFile->copyTo($destFile); @@ -291,4 +295,4 @@ class FileUtils {      }  } -?> + diff --git a/buildscripts/phing/classes/phing/util/LogWriter.php b/buildscripts/phing/classes/phing/util/LogWriter.php index 9e704fc3..ae97705e 100644..100755 --- a/buildscripts/phing/classes/phing/util/LogWriter.php +++ b/buildscripts/phing/classes/phing/util/LogWriter.php @@ -1,96 +1,95 @@  <?php -	/** -	 * $Id: LogWriter.php,v 1.2 2004/11/09 13:16:11 hlellelid Exp $ -	 * -	 * 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/system/io/Writer.php'; -	require_once 'phing/Task.php'; +    /** +     * $Id: ccb6c8b930bb3f293074969323467edeaf40bd02 $ +     * +     * 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/system/io/Writer.php'; +    require_once 'phing/Task.php'; -	/** -	 * Extends the Writer class to output messages to Phing's log -	 * -	 * @author Michiel Rook <michiel@trendserver.nl> -	 * @version $Id: LogWriter.php,v 1.2 2004/11/09 13:16:11 hlellelid Exp $ -	 * @package phing.util -	 */ -	class LogWriter extends Writer -	{ -		private $task = NULL; -		 -		private $level = NULL; -		 -		/** -		 * Constructs a new LogWriter object -		 */ -		function __construct(Task $task, $level = PROJECT_MSG_INFO) -		{ -			$this->task = $task; -			$this->level = $level; -		} -		 -		/** -		 * @see Writer::write() -		 */ -		function write($buf, $off = null, $len = null) -		{ -			$lines = explode("\n", $buf); -			 -			foreach ($lines as $line) -			{ -				if ($line == "") -				{ -					continue; -				} -				 -				$this->task->log($line, $this->level); -			} -		} -		 -		/** -		 * @see Writer::reset() -		 */ -		function reset() -		{ -		} +    /** +     * Extends the Writer class to output messages to Phing's log +     * +     * @author Michiel Rook <mrook@php.net> +     * @version $Id: ccb6c8b930bb3f293074969323467edeaf40bd02 $ +     * @package phing.util +     */ +    class LogWriter extends Writer +    { +        private $task = NULL; +         +        private $level = NULL; +         +        /** +         * Constructs a new LogWriter object +         */ +        function __construct(Task $task, $level = Project::MSG_INFO) +        { +            $this->task = $task; +            $this->level = $level; +        } +         +        /** +         * @see Writer::write() +         */ +        function write($buf, $off = null, $len = null) +        { +            $lines = explode("\n", $buf); +             +            foreach ($lines as $line) +            { +                if ($line == "") +                { +                    continue; +                } +                 +                $this->task->log($line, $this->level); +            } +        } +         +        /** +         * @see Writer::reset() +         */ +        function reset() +        { +        } -		/** -		 * @see Writer::close() -		 */ -		function close() -		{ -		} -		 -		/** -		 * @see Writer::open() -		 */ -		function open() -		{ -		} -		 -		/** -		 * @see Writer::getResource() -		 */ -		function getResource() -		{ -			return $this->task; -		} -	} +        /** +         * @see Writer::close() +         */ +        function close() +        { +        } +         +        /** +         * @see Writer::open() +         */ +        function open() +        { +        } +         +        /** +         * @see Writer::getResource() +         */ +        function getResource() +        { +            return $this->task; +        } +    } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/util/PathTokenizer.php b/buildscripts/phing/classes/phing/util/PathTokenizer.php index 29c0f059..0a469acf 100644 --- a/buildscripts/phing/classes/phing/util/PathTokenizer.php +++ b/buildscripts/phing/classes/phing/util/PathTokenizer.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: PathTokenizer.php,v 1.3 2003/12/24 12:38:42 hlellelid Exp $ + *  $Id: 0ca7f2a419b5cc4285a8f84695c4b680b0aa190b $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -45,7 +45,7 @@ include_once 'phing/util/StringHelper.php';   * @author Jeff Tulley <jtulley@novell.com>  (Ant) - * @pacakge phing.util + * @package phing.util   */  diff --git a/buildscripts/phing/classes/phing/util/PearPackageScanner.php b/buildscripts/phing/classes/phing/util/PearPackageScanner.php new file mode 100644 index 00000000..9071ed37 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/PearPackageScanner.php @@ -0,0 +1,170 @@ +<?php +/** + * Part of phing, the PHP build tool + * + * PHP version 5 + * + * @category Util + * @package  phing.util + * @author   Christian Weiske <cweiske@cweiske.de> + * @license  LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @version  SVN: $Id: e549026313edf53c67f495489f671cf0b71df80d $ + * @link     http://www.phing.info/ + */ +require_once 'phing/util/DirectoryScanner.php'; +require_once 'PEAR/Config.php'; + +/** + * Scans for files in a PEAR package. + * + * @category Util + * @package  phing.util + * @author   Christian Weiske <cweiske@cweiske.de> + * @license  LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link     http://www.phing.info/ + */ +class PearPackageScanner extends DirectoryScanner +{ +    protected $packageInfo; +    protected $role = 'php'; +    protected $config; +    protected $package; +    protected $channel = 'pear.php.net'; + +    /** +     * Sets the name of the PEAR package to get the files from +     * +     * @param string $package Package name without channel +     * +     * @return void +     */ +    public function setPackage($package) +    { +        $this->package = $package; +    } + +    /** +     * Sets the name of the package channel name +     * +     * @param string $channel package channel name or alias +     * +     * @return void +     */ +    public function setChannel($channel) +    { +        $this->channel = $channel; +    } + +    /** +     * Sets the full path to the PEAR configuration file +     * +     * @param string $config Configuration file +     * +     * @return void +     */ +    public function setConfig($config) +    { +        if ($config != '' && !file_exists($config)) { +            throw new BuildException( +                'PEAR configuration file "' . $config . '" does not exist' +            ); +        } + +        $this->config = $config; +    } + +    /** +     * Sets the role of files that should be included. +     * Examples are php,doc,script +     * +     * @param string $role PEAR file role +     * +     * @return void +     * +     * @internal +     * We do not verify the role against a hardcoded list since that +     * would break packages with additional roles. +     */ +    public function setRole($role) +    { +        if ($role == '') { +            throw new BuildException('A non-empty role is required'); +        } + +        $this->role = $role; +    } + +    /** +     * Loads the package information. +     * +     * @return void +     * +     * @uses $packageInfo +     */ +    protected function init() +    { +        if (!$this->packageInfo) { +            $this->packageInfo = $this->loadPackageInfo(); +        } +    } + +    /** +     * Loads and returns the PEAR package information. +     * +     * @return PEAR_PackageFile_v2 Package information object +     * +     * @throws BuildException When the package does not exist +     */ +    protected function loadPackageInfo() +    { +        $cfg = PEAR_Config::singleton($this->config); +        $reg = $cfg->getRegistry(); +        if (!$reg->packageExists($this->package, $this->channel)) { +            throw new BuildException( +                sprintf( +                    'PEAR package %s/%s does not exist', +                    $this->channel, $this->package +                ) +            ); +        } + +        $packageInfo = $reg->getPackage($this->package, $this->channel); +        return $packageInfo; +    } + +    /** +     * Generates the list of included files and directories +     * +     * @return boolean True if all went well, false if something was wrong +     * +     * @uses $filesIncluded +     * @uses $filesDeselected +     * @uses $filesNotIncluded +     * @uses $filesExcluded +     * @uses $everythingIncluded +     * @uses $dirsIncluded +     * @uses $dirsDeselected +     * @uses $dirsNotIncluded +     * @uses $dirsExcluded +     */ +    public function scan() +    { +        $this->init(); +        $list = $this->packageInfo->getFilelist(); +        $found = null; +        foreach ($list as $file => $att) { +            if ($att['role'] != $this->role) { +                continue; +            } +            $this->filesIncluded[] = $file; +            $found = array($file, $att); +        } +        if ($found !== null) { +            list($file, $att) = $found; +            $this->setBaseDir(substr($att['installed_as'], 0, -strlen($file))); +        } + +        return true; +    } + +} diff --git a/buildscripts/phing/classes/phing/util/SourceFileScanner.php b/buildscripts/phing/classes/phing/util/SourceFileScanner.php index b157dcb9..d958a15f 100644 --- a/buildscripts/phing/classes/phing/util/SourceFileScanner.php +++ b/buildscripts/phing/classes/phing/util/SourceFileScanner.php @@ -1,6 +1,6 @@  <?php  /* - *  $Id: SourceFileScanner.php,v 1.11 2005/05/26 13:10:53 mrook Exp $ + *  $Id: 0555ae8b4e7418c211bd69a066877ab8cf95fbb8 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -80,7 +80,7 @@ class SourceFileScanner {              $targets = $mapper->main($files[$i]);              if (empty($targets)) { -                $this->task->log($files[$i]." skipped - don't know how to handle it", PROJECT_MSG_VERBOSE); +                $this->task->log($files[$i]." skipped - don't know how to handle it", Project::MSG_VERBOSE);                  continue;              } @@ -93,7 +93,7 @@ class SourceFileScanner {                  }                  if ($src->lastModified() > $now) { -                    $this->task->log("Warning: ".$files[$i]." modified in the future (".$src->lastModified()." > ".$now.")", PROJECT_MSG_WARN); +                    $this->task->log("Warning: ".$files[$i]." modified in the future (".$src->lastModified()." > ".$now.")", Project::MSG_WARN);                  }              } catch (IOException $ioe) {                  $this->task->log("Unable to read file ".$files[$i]." (skipping): " . $ioe->getMessage()); @@ -113,15 +113,15 @@ class SourceFileScanner {                  }                  if (!$dest->exists()) { -                    $this->task->log($files[$i]." added as " . $dest->__toString() . " doesn't exist.", PROJECT_MSG_VERBOSE); +                    $this->task->log($files[$i]." added as " . $dest->__toString() . " doesn't exist.", Project::MSG_VERBOSE);                      $v[] =$files[$i];                      $added = true;                  } elseif ($src->lastModified() > $dest->lastModified()) { -                    $this->task->log($files[$i]." added as " . $dest->__toString() . " is outdated.", PROJECT_MSG_VERBOSE ); +                    $this->task->log($files[$i]." added as " . $dest->__toString() . " is outdated.", Project::MSG_VERBOSE );                      $v[]=$files[$i];                      $added = true;                  } elseif ($force === true) { -                    $this->task->log($files[$i]." added as " . $dest->__toString() . " is forced to be overwritten.", PROJECT_MSG_VERBOSE ); +                    $this->task->log($files[$i]." added as " . $dest->__toString() . " is forced to be overwritten.", Project::MSG_VERBOSE );                      $v[]=$files[$i];                      $added = true;                  } else { @@ -133,7 +133,7 @@ class SourceFileScanner {              }              if (!$added) { -                $this->task->log($files[$i]." omitted as ".$targetList." ".(count($targets) === 1 ? " is " : " are ")."up to date.",  PROJECT_MSG_VERBOSE); +                $this->task->log($files[$i]." omitted as ".$targetList." ".(count($targets) === 1 ? " is " : " are ")."up to date.",  Project::MSG_VERBOSE);              }          } @@ -156,4 +156,4 @@ class SourceFileScanner {          return $result;      }  } -?> + diff --git a/buildscripts/phing/classes/phing/util/StringHelper.php b/buildscripts/phing/classes/phing/util/StringHelper.php index 5d4bfd7a..31d0b0e9 100644 --- a/buildscripts/phing/classes/phing/util/StringHelper.php +++ b/buildscripts/phing/classes/phing/util/StringHelper.php @@ -18,9 +18,9 @@ class StringHelper {      /**       * Replaces identifier tokens with corresponding text values in passed string.       * -     * @params array $strings Array of strings to multiply. (If string is passed, will convert to array) -     * @params array $tokens The tokens to search for. -     * @params array $replacements The values with which to replace found tokens. +     * @param array $strings Array of strings to multiply. (If string is passed, will convert to array) +     * @param array $tokens The tokens to search for. +     * @param array $replacements The values with which to replace found tokens.       * @return string       */      public static function multiply($strings, $tokens, $replacements) { @@ -206,4 +206,3 @@ class StringHelper {  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/util/regexp/PregEngine.php b/buildscripts/phing/classes/phing/util/regexp/PregEngine.php index 758b40f3..76cf56b3 100644 --- a/buildscripts/phing/classes/phing/util/regexp/PregEngine.php +++ b/buildscripts/phing/classes/phing/util/regexp/PregEngine.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: PregEngine.php,v 1.6 2003/12/24 12:38:42 hlellelid Exp $ + *  $Id: 94607411e16d4c9091369ff4a65ea8f44bde8781 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,14 +26,60 @@ require_once 'phing/util/regexp/RegexpEngine.php';   * Implements a regexp engine using PHP's preg_match(), preg_match_all(), and preg_replace() functions.   *    * @author hans lellelid, hans@velum.net - * @package phing.util.regex + * @package phing.util.regexp   */  class PregEngine implements RegexpEngine {      /** +     * Set to null by default to distinguish between false and not set       * @var boolean       */ -    private $ignoreCase = false; +    private $ignoreCase = null; + +    /** +     * Set to null by default to distinguish between false and not set +     * @var boolean +     */ +    private $multiline = null; + +    /** +     * Pattern modifiers  +     * @link http://php.net/manual/en/reference.pcre.pattern.modifiers.php +     * @var string +     */ +    private $modifiers = null; + +    /** +     * Sets pattern modifiers for regex engine +     * +     * @param string $mods Modifiers to be applied to a given regex +     * @return void +     */ +    public function setModifiers($mods) { +        $this->modifiers =  (string)$mods; +    } + +    /** +     * Gets pattern modifiers. +     * @return string +     */ +    public function getModifiers() { +        $mods = $this->modifiers; +        if($this->getIgnoreCase()) { +            $mods .= 'i'; +        } elseif($this->getIgnoreCase() === false) { +            $mods = str_replace('i', '', $mods); +        } +        if($this->getMultiline()) { +            $mods .= 's'; +        } elseif($this->getMultiline() === false) { +            $mods = str_replace('s', '', $mods); +        } +        // filter out duplicates +        $mods = preg_split('//', $mods, -1, PREG_SPLIT_NO_EMPTY); +        $mods = implode('', array_unique($mods)); +        return $mods; +    }      /**       * Sets whether or not regex operation is case sensitive. @@ -51,6 +97,22 @@ class PregEngine implements RegexpEngine {      function getIgnoreCase() {          return $this->ignoreCase;      } + +    /** +     * Sets whether regexp should be applied in multiline mode. +     * @param boolean $bit +     */ +    function setMultiline($bit) { +        $this->multiline = $bit; +    } + +    /** +     * Gets whether regexp is to be applied in multiline mode. +     * @return boolean +     */ +    function getMultiline() { +        return $this->multiline; +    }      /**       * The pattern needs to be converted into PREG style -- which includes adding expression delims & any flags, etc. @@ -59,7 +121,8 @@ class PregEngine implements RegexpEngine {       */      private function preparePattern($pattern)      { -        return '/'.$pattern.'/'.($this->ignoreCase ? 'i' : ''); +        // Use backquotes since hardly ever found in a regexp pattern, avoids using preg_quote +        return '`'.$pattern.'`' . $this->getModifiers();      }      /** @@ -96,10 +159,9 @@ class PregEngine implements RegexpEngine {      function replace($pattern, $replace, $source) {          // convert \1 -> $1, because we want to use the more generic \1 in the XML          // but PREG prefers $1 syntax. -        $replace = preg_replace('/[^\\\]\\\(\d+)/', '$1', $replace); +        $replace = preg_replace('/\\\(\d+)/', '\$$1', $replace);          return preg_replace($this->preparePattern($pattern), $replace, $source);      }  } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/util/regexp/Regexp.php b/buildscripts/phing/classes/phing/util/regexp/Regexp.php index 68c06668..7188997e 100644..100755 --- a/buildscripts/phing/classes/phing/util/regexp/Regexp.php +++ b/buildscripts/phing/classes/phing/util/regexp/Regexp.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: Regexp.php,v 1.5 2003/12/24 18:40:33 hlellelid Exp $ + *  $Id: b669eb9f2dd8533cba67b2058b7cbc2f558bdeae $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,7 +23,7 @@   * A factory class for regex functions.   * @author Hans Lellelid <hans@xmpl.org>   * @package  phing.util.regexp - * @version $Revision: 1.5 $ + * @version $Id$   */  class Regexp { @@ -97,12 +97,11 @@ class Regexp {      /**       * Gets replacement string.       * @return string The pattern to replace matches with. -     * @return void       */      public function getReplace() {          return $this->replace;      } -     +      /**       * Performs match of specified pattern against $subject.       * @param string $subject The subject, on which to perform matches. @@ -146,6 +145,27 @@ class Regexp {          }          return $this->groups[$idx];      } + +    /** +     * Sets pattern modifiers for regex engine +     * +     * @param string $mods Modifiers to be applied to a given regex +     * @return void +     */ +    public function setModifiers($mods) { +        $this->engine->setModifiers($mods); +    } + +    /** +     * Gets pattern modifiers. +     * Subsequent call to engines getModifiers() filters out duplicates +     * i.e. if i is provided in $mods, and setIgnoreCase(true), "i"  +     * modifier would be included only once +     * @return string +     */ +    public function getModifiers() { +        return $this->engine->getModifiers(); +    }      /**       * Sets whether the regexp matching is case insensitive. @@ -163,6 +183,21 @@ class Regexp {      function getIgnoreCase() {          return $this->engine->getIgnoreCase();      } + +    /** +     * Sets whether regexp should be applied in multiline mode. +     * @param boolean $bit +     */ +    function setMultiline($bit) { +        $this->engine->setMultiline($bit); +    } + +    /** +     * Gets whether regexp is to be applied in multiline mode. +     * @return boolean +     */ +    function getMultiline() { +        return $this->engine->getMultiline(); +    }  }  -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php b/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php index 7d323466..3eb8c408 100644..100755 --- a/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php +++ b/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php @@ -1,6 +1,6 @@  <?php  /*  - *  $Id: RegexpEngine.php,v 1.4 2003/12/24 12:38:42 hlellelid Exp $ + *  $Id: 5e2886f3fae60fff1fd142e79717a3a7a4555772 $   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,8 +24,8 @@   * engine-specific implementations that sub-classes must override.   *    * @author Hans Lellelid <hans@velum.net> - * @package phing.util.regex - * @version $Revision: 1.4 $ + * @package phing.util.regexp + * @version $Id$   */  interface RegexpEngine { @@ -71,4 +71,3 @@ interface RegexpEngine {  } -?>
\ No newline at end of file  | 
