libretime/airtime_mvc/library/phing/Project.php

1000 lines
34 KiB
PHP

<?php
/*
* $Id: Project.php 905 2010-10-05 16:28:03Z 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>.
*/
include_once 'phing/system/io/PhingFile.php';
include_once 'phing/util/FileUtils.php';
include_once 'phing/TaskAdapter.php';
include_once 'phing/util/StringHelper.php';
include_once 'phing/BuildEvent.php';
include_once 'phing/input/DefaultInputHandler.php';
/**
* The Phing project class. Represents a completely configured Phing project.
* The class defines the project and all tasks/targets. It also contains
* methods to start a build as well as some properties and FileSystem
* abstraction.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @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) */
private $globalFilterSet = array();
/** all globals filters (future use) */
private $globalFilters = array();
/** Project properties map (usually String to String). */
private $properties = array();
/**
* Map of "user" properties (as created in the Ant task, for example).
* Note that these key/value pairs are also always put into the
* project properties, so only the project properties need to be queried.
* Mapping is String to String.
*/
private $userProperties = array();
/**
* Map of inherited "user" properties - that are those "user"
* properties that have been created by tasks and not been set
* from the command line or a GUI tool.
* Mapping is String to String.
*/
private $inheritedProperties = array();
/** task definitions for this project*/
private $taskdefs = array();
/** type definitions for this project */
private $typedefs = array();
/** holds ref names and a reference to the referred object*/
private $references = array();
/** The InputHandler being used by this project. */
private $inputHandler;
/* -- properties that come in via xml attributes -- */
/** basedir (PhingFile object) */
private $basedir;
/** the default target name */
private $defaultTarget = 'all';
/** project name (required) */
private $name;
/** project description */
private $description;
/** require phing version */
private $phingVersion;
/** a FileUtils object */
private $fileUtils;
/** Build listeneers */
private $listeners = array();
/**
* Constructor, sets any default vars.
*/
function __construct() {
$this->fileUtils = new FileUtils();
$this->inputHandler = new DefaultInputHandler();
}
/**
* Sets the input handler
*/
public function setInputHandler(InputHandler $handler) {
$this->inputHandler = $handler;
}
/**
* Retrieves the current input handler.
*/
public function getInputHandler() {
return $this->inputHandler;
}
/** inits the project, called from main app */
function init() {
// set builtin properties
$this->setSystemProperties();
// load default tasks
$taskdefs = Phing::getResourcePath("phing/tasks/defaults.properties");
try { // try to load taskdefs
$props = new Properties();
$in = new PhingFile((string)$taskdefs);
if ($in === null) {
throw new BuildException("Can't load default task list");
}
$props->load($in);
$enum = $props->propertyNames();
foreach($enum as $key) {
$value = $props->getProperty($key);
$this->addTaskDefinition($key, $value);
}
} catch (IOException $ioe) {
throw new BuildException("Can't load default task list");
}
// load default tasks
$typedefs = Phing::getResourcePath("phing/types/defaults.properties");
try { // try to load typedefs
$props = new Properties();
$in = new PhingFile((string)$typedefs);
if ($in === null) {
throw new BuildException("Can't load default datatype list");
}
$props->load($in);
$enum = $props->propertyNames();
foreach($enum as $key) {
$value = $props->getProperty($key);
$this->addDataTypeDefinition($key, $value);
}
} catch(IOException $ioe) {
throw new BuildException("Can't load default datatype list");
}
}
/** returns the global filterset (future use) */
function getGlobalFilterSet() {
return $this->globalFilterSet;
}
// ---------------------------------------------------------
// Property methods
// ---------------------------------------------------------
/**
* Sets a property. Any existing property of the same name
* is overwritten, unless it is a user property.
* @param string $name The name of property to set.
* Must not be <code>null</code>.
* @param string $value The new value of the property.
* Must not be <code>null</code>.
* @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);
return;
}
if (isset($this->properties[$name])) {
$this->log("Overriding previous definition of property " . $name, Project::MSG_VERBOSE);
}
$this->log("Setting project property: " . $name . " -> " . $value, Project::MSG_DEBUG);
$this->properties[$name] = $value;
}
/**
* Sets a property if no value currently exists. If the property
* exists already, a message is logged and the method returns with
* no other effect.
*
* @param string $name The name of property to set.
* Must not be <code>null</code>.
* @param string $value The new value of the property.
* Must not be <code>null</code>.
* @since 2.0
*/
public function setNewProperty($name, $value) {
if (isset($this->properties[$name])) {
$this->log("Override ignored for property " . $name, Project::MSG_DEBUG);
return;
}
$this->log("Setting project property: " . $name . " -> " . $value, Project::MSG_DEBUG);
$this->properties[$name] = $value;
}
/**
* Sets a user property, which cannot be overwritten by
* set/unset property calls. Any previous value is overwritten.
* @param string $name The name of property to set.
* Must not be <code>null</code>.
* @param string $value The new value of the property.
* Must not be <code>null</code>.
* @see #setProperty()
*/
public function setUserProperty($name, $value) {
$this->log("Setting ro project property: " . $name . " -> " . $value, Project::MSG_DEBUG);
$this->userProperties[$name] = $value;
$this->properties[$name] = $value;
}
/**
* Sets a user property, which cannot be overwritten by set/unset
* property calls. Any previous value is overwritten. Also marks
* these properties as properties that have not come from the
* command line.
*
* @param string $name The name of property to set.
* Must not be <code>null</code>.
* @param string $value The new value of the property.
* Must not be <code>null</code>.
* @see #setProperty()
*/
public function setInheritedProperty($name, $value) {
$this->inheritedProperties[$name] = $value;
$this->setUserProperty($name, $value);
}
/**
* Sets a property unless it is already defined as a user property
* (in which case the method returns silently).
*
* @param name The name of the property.
* Must not be <code>null</code>.
* @param value The property value. Must not be <code>null</code>.
*/
private function setPropertyInternal($name, $value) {
if (isset($this->userProperties[$name])) {
$this->log("Override ignored for user property " . $name, Project::MSG_VERBOSE);
return;
}
$this->properties[$name] = $value;
}
/**
* Returns the value of a property, if it is set.
*
* @param string $name The name of the property.
* May be <code>null</code>, in which case
* the return value is also <code>null</code>.
* @return string The property value, or <code>null</code> for no match
* or if a <code>null</code> name is provided.
*/
public function getProperty($name) {
if (!isset($this->properties[$name])) {
return null;
}
$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;
}
/**
* Replaces ${} style constructions in the given value with the
* string value of the corresponding data types.
*
* @param value The string to be scanned for property references.
* May be <code>null</code>.
*
* @return the given string with embedded property names replaced
* by values, or <code>null</code> if the given string is
* <code>null</code>.
*
* @exception BuildException if the given value has an unclosed
* property name, e.g. <code>${xxx</code>
*/
public function replaceProperties($value) {
return ProjectConfigurator::replaceProperties($this, $value, $this->properties);
}
/**
* Returns the value of a user property, if it is set.
*
* @param string $name The name of the property.
* May be <code>null</code>, in which case
* the return value is also <code>null</code>.
* @return string The property value, or <code>null</code> for no match
* or if a <code>null</code> name is provided.
*/
public function getUserProperty($name) {
if (!isset($this->userProperties[$name])) {
return null;
}
return $this->userProperties[$name];
}
/**
* Returns a copy of the properties table.
* @return array A hashtable containing all properties
* (including user properties).
*/
public function getProperties() {
return $this->properties;
}
/**
* Returns a copy of the user property hashtable
* @return a hashtable containing just the user properties
*/
public function getUserProperties() {
return $this->userProperties;
}
/**
* Copies all user properties that have been set on the command
* line or a GUI tool from this instance to the Project instance
* given as the argument.
*
* <p>To copy all "user" properties, you will also have to call
* {@link #copyInheritedProperties copyInheritedProperties}.</p>
*
* @param Project $other the project to copy the properties to. Must not be null.
* @return void
* @since phing 2.0
*/
public function copyUserProperties(Project $other) {
foreach($this->userProperties as $arg => $value) {
if (isset($this->inheritedProperties[$arg])) {
continue;
}
$other->setUserProperty($arg, $value);
}
}
/**
* Copies all user properties that have not been set on the
* command line or a GUI tool from this instance to the Project
* instance given as the argument.
*
* <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.
*
* @since phing 2.0
*/
public function copyInheritedProperties(Project $other) {
foreach($this->userProperties as $arg => $value) {
if ($other->getUserProperty($arg) !== null) {
continue;
}
$other->setInheritedProperty($arg, $value);
}
}
// ---------------------------------------------------------
// END Properties methods
// ---------------------------------------------------------
function setDefaultTarget($targetName) {
$this->defaultTarget = (string) trim($targetName);
}
function getDefaultTarget() {
return (string) $this->defaultTarget;
}
/**
* Sets the name of the current project
*
* @param string name of project
* @return void
* @access public
* @author Andreas Aderhold, andi@binarycloud.com
*/
function setName($name) {
$this->name = (string) trim($name);
$this->setProperty("phing.project.name", $this->name);
}
/**
* Returns the name of this project
*
* @returns string projectname
* @access public
* @author Andreas Aderhold, andi@binarycloud.com
*/
function getName() {
return (string) $this->name;
}
/** Set the projects description */
function setDescription($description) {
$this->description = (string) trim($description);
}
/** return the description, null otherwise */
function getDescription() {
return $this->description;
}
/** Set the minimum required phing version **/
function setPhingVersion($version) {
$version = str_replace('phing', '', strtolower($version));
$this->phingVersion = (string)trim($version);
}
/** Get the minimum required phing version **/
function getPhingVersion() {
if($this->phingVersion === null) {
$this->setPhingVersion(Phing::getPhingVersion());
}
return $this->phingVersion;
}
/** Set basedir object from xml*/
function setBasedir($dir) {
if ($dir instanceof PhingFile) {
$dir = $dir->getAbsolutePath();
}
$dir = $this->fileUtils->normalize($dir);
$dir = new PhingFile((string) $dir);
if (!$dir->exists()) {
throw new BuildException("Basedir ".$dir->getAbsolutePath()." does not exist");
}
if (!$dir->isDirectory()) {
throw new BuildException("Basedir ".$dir->getAbsolutePath()." is not a directory");
}
$this->basedir = $dir;
$this->setPropertyInternal("project.basedir", $this->basedir->getAbsolutePath());
$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());
}
/**
* Returns the basedir of this project
*
* @returns PhingFile Basedir PhingFile object
* @access public
* @throws BuildException
* @author Andreas Aderhold, andi@binarycloud.com
*/
function getBasedir() {
if ($this->basedir === null) {
try { // try to set it
$this->setBasedir(".");
} catch (BuildException $exc) {
throw new BuildException("Can not set default basedir. ".$exc->getMessage());
}
}
return $this->basedir;
}
/**
* Sets system properties and the environment variables for this project.
*
* @return void
*/
function setSystemProperties() {
// first get system properties
$systemP = array_merge( self::getProperties(), Phing::getProperties() );
foreach($systemP as $name => $value) {
$this->setPropertyInternal($name, $value);
}
// and now the env vars
foreach($_SERVER as $name => $value) {
// skip arrays
if (is_array($value)) {
continue;
}
$this->setPropertyInternal('env.' . $name, $value);
}
return true;
}
/**
* Adds a task definition.
* @param string $name Name of tag.
* @param string $class The class path to use.
* @param string $classpath The classpat to use.
*/
function addTaskDefinition($name, $class, $classpath = null) {
$name = $name;
$class = $class;
if ($class === "") {
$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);
} else {
$this->log("Task $name ($class) already registerd, skipping", Project::MSG_VERBOSE);
}
}
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.
*/
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);
} else {
$this->log("Type $typeName ($typeClass) already registerd, skipping", Project::MSG_VERBOSE);
}
}
function getDataTypeDefinitions() {
return $this->typedefs;
}
/** add a new target to the project */
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);
$target->setProject($this);
$this->targets[$targetName] = $target;
$ctx = $this->getReference("phing.parsing.context");
$current = $ctx->getConfigurator()->getCurrentTargets();
$current[$targetName] = $target;
}
function getTargets() {
return $this->targets;
}
/**
* Create a new task instance and return reference to it. This method is
* sorta factory like. A _local_ instance is created and a reference returned to
* that instance. Usually PHP destroys local variables when the function call
* ends. But not if you return a reference to that variable.
* This is kinda error prone, because if no reference exists to the variable
* it is destroyed just like leaving the local scope with primitive vars. There's no
* central place where the instance is stored as in other OOP like languages.
*
* [HL] Well, ZE2 is here now, and this is still working. We'll leave this alone
* unless there's any good reason not to.
*
* @param string $taskType Task name
* @returns Task A task object
* @throws BuildException
* Exception
*/
function createTask($taskType) {
try {
$classname = "";
$tasklwr = strtolower($taskType);
foreach ($this->taskdefs as $name => $class) {
if (strtolower($name) === $tasklwr) {
$classname = $class;
break;
}
}
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();
if ($o instanceof Task) {
$task = $o;
} else {
$this->log (" (Using TaskAdapter for: $taskType)", Project::MSG_DEBUG);
// not a real task, try adapter
$taskA = new TaskAdapter();
$taskA->setProxy($o);
$task = $taskA;
}
$task->setProject($this);
$task->setTaskType($taskType);
// set default value, can be changed by the user
$task->setTaskName($taskType);
$this->log (" +Task: " . $taskType, Project::MSG_DEBUG);
} catch (Exception $t) {
throw new BuildException("Could not create task of type: " . $taskType, $t);
}
// everything fine return reference
return $task;
}
/**
* 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
*/
function createDataType($typeName) {
try {
$cls = "";
$typelwr = strtolower($typeName);
foreach ($this->typedefs as $name => $class) {
if (strtolower($name) === $typelwr) {
$cls = StringHelper::unqualify($class);
break;
}
}
if ($cls === "") {
return null;
}
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.)");
}
$type = new $cls();
$this->log(" +Type: $typeName", Project::MSG_DEBUG);
if (!($type instanceof DataType)) {
throw new Exception("$class is not an instance of phing.types.DataType");
}
if ($type instanceof ProjectComponent) {
$type->setProject($this);
}
} catch (Exception $t) {
throw new BuildException("Could not create type: $typeName", $t);
}
// everything fine return reference
return $type;
}
/**
* Executes a list of targets
*
* @param array List of target names to execute
* @returns void
* @throws BuildException
*/
function executeTargets($targetNames) {
foreach($targetNames as $tname) {
$this->executeTarget($tname);
}
}
/**
* Executes a target
*
* @param string Name of Target to execute
* @returns void
* @throws BuildException
*/
function executeTarget($targetName) {
// complain about executing void
if ($targetName === null) {
throw new BuildException("No target specified");
}
// invoke topological sort of the target tree and run all targets
// until targetName occurs.
$sortedTargets = $this->_topoSort($targetName, $this->targets);
$curIndex = (int) 0;
$curTarget = null;
do {
try {
$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);
throw $exc;
}
} while ($curTarget->getName() !== $targetName);
}
function resolveFile($fileName, $rootDir = null) {
if ($rootDir === null) {
return $this->fileUtils->resolveFile($this->basedir, $fileName);
} else {
return $this->fileUtils->resolveFile($rootDir, $fileName);
}
}
/**
* Topologically sort a set of Targets.
* @param $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
* @return An array of Strings with the names of the targets in
* sorted order.
*/
function _topoSort($root, &$targets) {
$root = (string) $root;
$ret = array();
$state = array();
$visiting = array();
// We first run a DFS based sort using the root as the starting node.
// This creates the minimum sequence of Targets to the root node.
// We then do a sort on any remaining unVISITED targets.
// This is unnecessary for doing our build, but it catches
// circular dependencies or missing Targets on the entire
// dependency tree, not just on the Targets that depend on the
// build Target.
$this->_tsort($root, $targets, $state, $visiting, $ret);
$retHuman = "";
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);
$keys = array_keys($targets);
while($keys) {
$curTargetName = (string) array_shift($keys);
if (!isset($state[$curTargetName])) {
$st = null;
} else {
$st = (string) $state[$curTargetName];
}
if ($st === null) {
$this->_tsort($curTargetName, $targets, $state, $visiting, $ret);
} elseif ($st === "VISITING") {
throw new Exception("Unexpected node in visiting state: $curTargetName");
}
}
$retHuman = "";
for ($i=0,$_i=count($ret); $i < $_i; $i++) {
$retHuman .= $ret[$i]->toString()." ";
}
$this->log("Complete build sequence is: $retHuman", Project::MSG_VERBOSE);
return $ret;
}
// one step in a recursive DFS traversal of the target dependency tree.
// - The array "state" contains the state (VISITED or VISITING or null)
// of all the target names.
// - The stack "visiting" contains a stack of target names that are
// currently on the DFS stack. (NB: the target names in "visiting" are
// exactly the target names in "state" that are in the VISITING state.)
// 1. Set the current target to the VISITING state, and push it onto
// the "visiting" stack.
// 2. Throw a BuildException if any child of the current node is
// in the VISITING state (implies there is a cycle.) It uses the
// "visiting" Stack to construct the cycle.
// 3. If any children have not been VISITED, tsort() the child.
// 4. Add the current target to the Vector "ret" after the children
// have been visited. Move the current target to the VISITED state.
// "ret" now contains the sorted sequence of Targets upto the current
// Target.
function _tsort($root, &$targets, &$state, &$visiting, &$ret) {
$state[$root] = "VISITING";
$visiting[] = $root;
if (!isset($targets[$root]) || !($targets[$root] instanceof Target)) {
$target = null;
} else {
$target = $targets[$root];
}
// make sure we exist
if ($target === null) {
$sb = "Target '$root' does not exist in this project.";
array_pop($visiting);
if (!empty($visiting)) {
$parent = (string) $visiting[count($visiting)-1];
$sb .= "It is used from target '$parent'.";
}
throw new BuildException($sb);
}
$deps = $target->getDependencies();
while($deps) {
$cur = (string) array_shift($deps);
if (!isset($state[$cur])) {
$m = null;
} else {
$m = (string) $state[$cur];
}
if ($m === null) {
// not been visited
$this->_tsort($cur, $targets, $state, $visiting, $ret);
} elseif ($m == "VISITING") {
// currently visiting this node, so have a cycle
throw $this->_makeCircularException($cur, $visiting);
}
}
$p = (string) array_pop($visiting);
if ($root !== $p) {
throw new Exception("Unexpected internal error: expected to pop $root but got $p");
}
$state[$root] = "VISITED";
$ret[] = $target;
}
function _makeCircularException($end, $stk) {
$sb = "Circular dependency: $end";
do {
$c = (string) array_pop($stk);
$sb .= " <- ".$c;
} while($c != $end);
return new BuildException($sb);
}
/**
* 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
*/
function addReference($name, $object) {
if (isset($this->references[$name])) {
$this->log("Overriding previous definition of reference to $name", Project::MSG_WARN);
}
$this->log("Adding reference: $name -> ".get_class($object), Project::MSG_DEBUG);
$this->references[$name] = $object;
}
/**
* Returns the references array.
* @return array
*/
function getReferences() {
return $this->references;
}
/**
* Returns a specific reference.
* @param string $key The reference id/key.
* @return Reference or null if not defined
*/
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
*/
function log($msg, $level = Project::MSG_INFO) {
$this->logObject($this, $msg, $level);
}
function logObject($obj, $msg, $level) {
$this->fireMessageLogged($obj, $msg, $level);
}
function addBuildListener(BuildListener $listener) {
$this->listeners[] = $listener;
}
function removeBuildListener(BuildListener $listener) {
$newarray = array();
for ($i=0, $size=count($this->listeners); $i < $size; $i++) {
if ($this->listeners[$i] !== $listener) {
$newarray[] = $this->listeners[$i];
}
}
$this->listeners = $newarray;
}
function getBuildListeners() {
return $this->listeners;
}
function fireBuildStarted() {
$event = new BuildEvent($this);
foreach($this->listeners as $listener) {
$listener->buildStarted($event);
}
}
function fireBuildFinished($exception) {
$event = new BuildEvent($this);
$event->setException($exception);
foreach($this->listeners as $listener) {
$listener->buildFinished($event);
}
}
function fireTargetStarted($target) {
$event = new BuildEvent($target);
foreach($this->listeners as $listener) {
$listener->targetStarted($event);
}
}
function fireTargetFinished($target, $exception) {
$event = new BuildEvent($target);
$event->setException($exception);
foreach($this->listeners as $listener) {
$listener->targetFinished($event);
}
}
function fireTaskStarted($task) {
$event = new BuildEvent($task);
foreach($this->listeners as $listener) {
$listener->taskStarted($event);
}
}
function fireTaskFinished($task, $exception) {
$event = new BuildEvent($task);
$event->setException($exception);
foreach($this->listeners as $listener) {
$listener->taskFinished($event);
}
}
function fireMessageLoggedEvent($event, $message, $priority) {
$event->setMessage($message, $priority);
foreach($this->listeners as $listener) {
$listener->messageLogged($event);
}
}
function fireMessageLogged($object, $message, $priority) {
$this->fireMessageLoggedEvent(new BuildEvent($object), $message, $priority);
}
}