initial commit

This commit is contained in:
Chris Sewell
2012-11-28 03:55:08 -05:00
parent 7adb399b2e
commit cf140a2e97
3247 changed files with 492437 additions and 0 deletions

View File

@ -0,0 +1,478 @@
<?php
/*
* $Id: CapsuleTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
include_once 'phing/BuildException.php';
include_once 'phing/lib/Capsule.php';
include_once 'phing/util/StringHelper.php';
/**
* A phing task for generating output by using Capsule.
*
* This is based on the interface to TexenTask from Apache's Velocity engine.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1.17 $
* @package phing.tasks.ext
*/
class CapsuleTask extends Task {
/**
* Capsule "template" engine.
* @var Capsule
*/
protected $context;
/**
* Any vars assigned via the build file.
* @var array AssignedVar[]
*/
protected $assignedVars = array();
/**
* This is the control template that governs the output.
* It may or may not invoke the services of worker
* templates.
* @var string
*/
protected $controlTemplate;
/**
* This is where Velocity will look for templates
* using the file template loader.
* @var string
*/
protected $templatePath;
/**
* This is where texen will place all the output
* that is a product of the generation process.
* @var string
*/
protected $outputDirectory;
/**
* This is the file where the generated text
* will be placed.
* @var string
*/
protected $outputFile;
/**
* <p>
* These are properties that are fed into the
* initial context from a properties file. This
* is simply a convenient way to set some values
* that you wish to make available in the context.
* </p>
* <p>
* These values are not critical, like the template path
* or output path, but allow a convenient way to
* set a value that may be specific to a particular
* generation task.
* </p>
* <p>
* For example, if you are generating scripts to allow
* user to automatically create a database, then
* you might want the <code>$databaseName</code>
* to be placed
* in the initial context so that it is available
* in a script that might look something like the
* following:
* <code><pre>
* #!bin/sh
*
* echo y | mysqladmin create $databaseName
* </pre></code>
* The value of <code>$databaseName</code> isn't critical to
* output, and you obviously don't want to change
* the ant task to simply take a database name.
* So initial context values can be set with
* properties file.
*
* @var array
*/
protected $contextProperties;
// -----------------------------------------------------------------------
// The following getters & setters are used by phing to set properties
// specified in the XML for the capsule task.
// -----------------------------------------------------------------------
/**
* [REQUIRED] Set the control template for the
* generating process.
* @param string $controlTemplate
* @return void
*/
public function setControlTemplate ($controlTemplate) {
$this->controlTemplate = $controlTemplate;
}
/**
* Get the control template for the
* generating process.
* @return string
*/
public function getControlTemplate() {
return $this->controlTemplate;
}
/**
* [REQUIRED] Set the path where Velocity will look
* for templates using the file template
* loader.
* @return void
* @throws Exception
*/
public function setTemplatePath($templatePath) {
$resolvedPath = "";
$tok = strtok($templatePath, ",");
while ( $tok ) {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($tok);
$cpath = $fullPath->getCanonicalPath();
if ($cpath === false) {
$this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
} else {
$resolvedPath .= $cpath;
}
$tok = strtok(",");
if ( $tok ) {
$resolvedPath .= ",";
}
}
$this->templatePath = $resolvedPath;
}
/**
* Get the path where Velocity will look
* for templates using the file template
* loader.
* @return string
*/
public function getTemplatePath() {
return $this->templatePath;
}
/**
* [REQUIRED] Set the output directory. It will be
* created if it doesn't exist.
* @param PhingFile $outputDirectory
* @return void
* @throws Exception
*/
public function setOutputDirectory(PhingFile $outputDirectory) {
try {
if (!$outputDirectory->exists()) {
$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());
}
}
$this->outputDirectory = $outputDirectory->getCanonicalPath();
} catch (IOException $ioe) {
throw new BuildException($ioe);
}
}
/**
* Get the output directory.
* @return string
*/
public function getOutputDirectory() {
return $this->outputDirectory;
}
/**
* [REQUIRED] Set the output file for the
* generation process.
* @param string $outputFile (TODO: change this to File)
* @return void
*/
public function setOutputFile($outputFile) {
$this->outputFile = $outputFile;
}
/**
* Get the output file for the
* generation process.
* @return string
*/
public function getOutputFile() {
return $this->outputFile;
}
/**
* Set the context properties that will be
* fed into the initial context be the
* generating process starts.
* @param string $file
* @return void
*/
public function setContextProperties($file) {
$sources = explode(",", $file);
$this->contextProperties = new Properties();
// Always try to get the context properties resource
// from a file first. Templates may be taken from a JAR
// file but the context properties resource may be a
// resource in the filesystem. If this fails than attempt
// to get the context properties resource from the
// classpath.
for ($i=0, $sourcesLength=count($sources); $i < $sourcesLength; $i++) {
$source = new Properties();
try {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($sources[$i]);
$this->log("Using contextProperties file: " . $fullPath->toString());
$source->load($fullPath);
} catch (Exception $e) {
throw new BuildException("Context properties file " . $sources[$i] .
" could not be found in the file system!");
}
$keys = $source->keys();
foreach ($keys as $key) {
$name = $key;
$value = $this->project->replaceProperties($source->getProperty($name));
$this->contextProperties->setProperty($name, $value);
}
}
}
/**
* Get the context properties that will be
* fed into the initial context be the
* generating process starts.
* @return Properties
*/
public function getContextProperties() {
return $this->contextProperties;
}
/**
* Creates an "AssignedVar" class.
*/
public function createAssign() {
$a = new AssignedVar();
$this->assignedVars[] = $a;
return $a;
}
// ---------------------------------------------------------------
// End of XML setters & getters
// ---------------------------------------------------------------
/**
* Creates a Smarty object.
*
* @return Smarty initialized (cleared) Smarty context.
* @throws Exception the execute method will catch
* and rethrow as a <code>BuildException</code>
*/
public function initControlContext() {
$this->context->clear();
foreach($this->assignedVars as $var) {
$this->context->put($var->getName(), $var->getValue());
}
return $this->context;
}
/**
* Execute the input script with Velocity
*
* @throws BuildException
* BuildExceptions are thrown when required attributes are missing.
* Exceptions thrown by Velocity are rethrown as BuildExceptions.
*/
public function main() {
// Make sure the template path is set.
if (empty($this->templatePath)) {
throw new BuildException("The template path needs to be defined!");
}
// Make sure the control template is set.
if ($this->controlTemplate === null) {
throw new BuildException("The control template needs to be defined!");
}
// Make sure the output directory is set.
if ($this->outputDirectory === null) {
throw new BuildException("The output directory needs to be defined!");
}
// Make sure there is an output file.
if ($this->outputFile === null) {
throw new BuildException("The output file needs to be defined!");
}
// Setup Smarty runtime.
// Smarty uses one object to store properties and to store
// the context for the template (unlike Velocity). We setup this object, calling it
// $this->context, and then initControlContext simply zeros out
// any assigned variables.
$this->context = new Capsule();
if ($this->templatePath !== null) {
$this->log("Using templatePath: " . $this->templatePath);
$this->context->setTemplatePath($this->templatePath);
}
// Make sure the output directory exists, if it doesn't
// then create it.
$outputDir = new PhingFile($this->outputDirectory);
if (!$outputDir->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath());
$outputDir->mkdirs();
}
$this->context->setOutputDirectory($outputDir->getAbsolutePath());
$path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
$this->log("Generating to file " . $path);
//$writer = new FileWriter($path);
// The generator and the output path should
// be placed in the init context here and
// not in the generator class itself.
$c = $this->initControlContext();
// Set any variables that need to always
// be loaded
$this->populateInitialContext($c);
// Feed all the options into the initial
// control context so they are available
// in the control/worker templates.
if ($this->contextProperties !== null) {
foreach($this->contextProperties->keys() as $property) {
$value = $this->contextProperties->getProperty($property);
// Special exception (from Texen)
// for properties ending in file.contents:
// in that case we dump the contents of the file
// as the "value" for the Property.
if (preg_match('/file\.contents$/', $property)) {
// pull in contents of file specified
$property = substr($property, 0, strpos($property, "file.contents") - 1);
// reset value, and then
// read in teh contents of the file into that var
$value = "";
$f = new PhingFile($project->resolveFile($value)->getCanonicalPath());
if ($f->exists()) {
$fr = new FileReader($f);
$fr->readInto($value);
}
} // if ends with file.contents
if (StringHelper::isBoolean($value)) {
$value = StringHelper::booleanValue($value);
}
$c->put($property, $value);
} // foreach property
} // if contextProperties !== null
try {
$this->log("Parsing control template: " . $this->controlTemplate);
$c->parse($this->controlTemplate, $path);
} catch (Exception $ioe) {
throw new BuildException("Cannot write parsed template: ". $ioe->getMessage());
}
$this->cleanup();
}
/**
* Place useful objects into the initial context.
*
*
* @param Capsule $context The context to populate, as retrieved from
* {@link #initControlContext()}.
* @return void
* @throws Exception Error while populating context. The {@link
* #main()} method will catch and rethrow as a
* <code>BuildException</code>.
*/
protected function populateInitialContext(Capsule $context) {
$this->context->put("now", strftime("%c", time()));
$this->context->put("task", $this);
}
/**
* A hook method called at the end of {@link #execute()} which can
* be overridden to perform any necessary cleanup activities (such
* as the release of database connections, etc.). By default,
* does nothing.
* @return void
* @throws Exception Problem cleaning up.
*/
protected function cleanup() {
}
}
/**
* An "inner" class for holding assigned var values.
* May be need to expand beyond name/value in the future.
*/
class AssignedVar {
private $name;
private $value;
function setName($v) {
$this->name = $v;
}
function setValue($v) {
$this->value = $v;
}
function getName() {
return $this->name;
}
function getValue() {
return $this->value;
}
}

View File

@ -0,0 +1,556 @@
<?php
/*
* $Id: CreoleSQLExecTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/CreoleTask.php';
include_once 'phing/system/io/StringReader.php';
/**
* Executes a series of SQL statements on a database using Creole.
*
* <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
* @version $Revision: 1.21 $
*/
class CreoleSQLExecTask extends CreoleTask {
private $goodSql = 0;
private $totalSql = 0;
const DELIM_ROW = "row";
const DELIM_NORMAL = "normal";
/**
* Database connection
*/
private $conn = null;
/**
* files to load
*/
private $filesets = array();
/**
* SQL statement
*/
private $statement = null;
/**
* SQL input file
*/
private $srcFile = null;
/**
* SQL input command
*/
private $sqlCommand = "";
/**
* SQL transactions to perform
*/
private $transactions = array();
/**
* SQL Statement delimiter
*/
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
/**
* Print SQL results.
*/
private $print = false;
/**
* Print header columns.
*/
private $showheaders = true;
/**
* Results Output file.
*/
private $output = null;
/**
* Action to perform if an error is found
**/
private $onError = "abort";
/**
* Encoding to use when reading SQL statements from a file
*/
private $encoding = null;
/**
* Append to an existing file or overwrite it?
*/
private $append = false;
/**
* 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;
}
/**
* Add a SQL transaction to execute
*/
public function createTransaction() {
$t = new SQLExecTransaction($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;
}
/**
* 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;
}
/**
* Set the print flag.
*
* @param boolean $print
*/
public function setPrint($print)
{
$this->print = (boolean) $print;
}
/**
* Print headers for result sets from the
* statements; optional, default true.
* @param boolean $showheaders
*/
public function setShowheaders($showheaders) {
$this->showheaders = (boolean) $showheaders;
}
/**
* Set the output file;
* optional, defaults to the console.
* @param PhingFile $output
*/
public function setOutput(PhingFile $output) {
$this->output = $output;
}
/**
* whether output should be appended to or overwrite
* an existing file. Defaults to false.
* @param $append
*/
public function setAppend($append) {
$this->append = (boolean) $append;
}
/**
* Action to perform when statement fails: continue, stop, or abort
* optional; default &quot;abort&quot;
*/
public function setOnerror($action) {
$this->onError = $action;
}
/**
* Load the sql file and then execute it
* @throws BuildException
*/
public function main() {
$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)) {
if (count($this->transactions) === 0) {
throw new BuildException("Source file or fileset, "
. "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
for ($i = 0,$size=count($this->filesets); $i < $size; $i++) {
$fs = $this->filesets[$i];
$ds = $fs->getDirectoryScanner($this->project);
$srcDir = $fs->getDir($this->project);
$srcFiles = $ds->getIncludedFiles();
// Make a transaction for each file
for ($j=0, $size=count($srcFiles); $j < $size; $j++) {
$t = $this->createTransaction();
$t->setSrc(new PhingFile($srcDir, $srcFiles[$j]));
}
}
// 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 = $this->conn->createStatement();
$out = null;
try {
if ($this->output !== null) {
$this->log("Opening output file " . $this->output, PROJECT_MSG_VERBOSE);
$out = new BufferedWriter(new FileWriter($this->output->getAbsolutePath(), $this->append));
}
// Process all transactions
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->conn->commit();
}
}
if ($out) $out->close();
} catch (Exception $e) {
if ($out) $out->close();
throw $e;
}
} catch (IOException $e) {
if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (SQLException $ex) {}
}
throw new BuildException($e->getMessage(), $this->location);
} catch (SQLException $e){
if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (SQLException $ex) {}
}
throw new BuildException($e->getMessage(), $this->location);
}
$this->log($this->goodSql . " of " . $this->totalSql .
" SQL statements executed successfully");
} catch (Exception $e) {
$this->transactions = $savedTransaction;
$this->sqlCommand = $savedSqlCommand;
throw $e;
}
// finally {
$this->transactions = $savedTransaction;
$this->sqlCommand = $savedSqlCommand;
}
/**
* read in lines and execute them
* @throws SQLException, IOException
*/
public function runStatements(Reader $reader, $out = null) {
$sql = "";
$line = "";
$in = new BufferedReader($reader);
try {
while (($line = $in->readLine()) !== null) {
$line = trim($line);
$line = ProjectConfigurator::replaceProperties($this->project, $line,
$this->project->getProperties());
if (StringHelper::startsWith("//", $line) ||
StringHelper::startsWith("--", $line) ||
StringHelper::startsWith("#", $line)) {
continue;
}
if (strlen($line) > 4
&& strtoupper(substr($line,0, 4)) == "REM ") {
continue;
}
$sql .= " " . $line;
$sql = trim($sql);
// 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";
}
if ($this->delimiterType == self::DELIM_NORMAL
&& 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);
$sql = "";
}
}
// Catch any statements not followed by ;
if ($sql !== "") {
$this->execSQL($sql, $out);
}
} catch (SQLException $e) {
throw new BuildException("Error running statements", $e);
}
}
/**
* Exec the sql statement.
* @throws SQLException
*/
protected function execSQL($sql, $out = null) {
// Check and ignore empty statements
if (trim($sql) == "") {
return;
}
try {
$this->totalSql++;
if (!$this->statement->execute($sql)) {
$this->log($this->statement->getUpdateCount() . " rows affected", PROJECT_MSG_VERBOSE);
} else {
if ($this->print) {
$this->printResults($out);
}
}
$this->goodSql++;
} catch (SQLException $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);
}
}
/**
* print any results in the statement.
* @throw 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);
$line = "";
$colsprinted = false;
while ($rs->next()) {
$fields = $rs->getRow();
if (!$colsprinted && $this->showheaders) {
$first = true;
foreach($fields as $fieldName => $ignore) {
if ($first) $first = false; else $line .= ",";
$line .= $fieldName;
}
if ($out !== null) {
$out->write($line);
$out->newLine();
} else {
print($line.$lSep);
}
$line = "";
$colsprinted = true;
} // if show headers
$first = true;
foreach($fields as $columnValue) {
if ($columnValue != null) {
$columnValue = trim($columnValue);
}
if ($first) {
$first = false;
} else {
$line .= ",";
}
$line .= $columnValue;
}
if ($out !== null) {
$out->write($line);
$out->newLine();
} else {
print($line . $lSep);
}
$line = "";
} // while rs->next()
}
} while ($this->statement->getMoreResults());
print($lSep);
if ($out !== null) $out->newLine();
}
}
/**
* "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.
*/
class SQLExecTransaction {
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, SQLException
*/
public function runTransaction($out = null)
{
if (!empty($this->tSqlCommand)) {
$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);
$reader = new FileReader($this->tSrcFile);
$this->parent->runStatements($reader, $out);
$reader->close();
}
}
}

View File

@ -0,0 +1,242 @@
<?php
/*
* $Id: CreoleTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 Creole 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 $Revision: 1.13 $
* @package phing.tasks.system
*/
abstract class CreoleTask extends Task {
/**
* Used for caching loaders / driver. This is to avoid
* getting an OutOfMemoryError when calling this task
* multiple times in a row.
*
* NOT IMPLEMENTED YET
*/
private static $loaderMap = array();
private $caching = true;
/**
* Autocommit flag. Default value is false
*/
private $autocommit = false;
/**
* [optional] Classpath to Creole driver to use.
* @param string
*/
private $driver;
/**
* 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() {
include_once 'creole/Creole.php';
if (!class_exists('Creole')) {
throw new Exception("Creole task depends on Creole classes being on include_path. (i.e. include of 'creole/Creole.php' failed.)");
}
}
/**
* 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;
}
/**
* Set the Creole driver to be used.
*
* @param string $driver driver class name
*/
public function setDriver($driver)
{
$this->driver = $driver;
}
/**
* 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);
$info = new Properties();
$dsn = Creole::parseDSN($this->url);
if (!isset($dsn["username"]) && $this->userId === null) {
throw new BuildException("Username must be in URL or userid attribute must be set.", $this->location);
}
if ($this->userId) {
$dsn["username"] = $this->getUserId();
}
if ($this->password) {
$dsn["password"] = $this->getPassword();
}
if ($this->driver) {
Creole::registerDriver($dsn['phptype'], $this->driver);
}
$conn = Creole::getConnection($dsn);
$conn->setAutoCommit($this->autocommit);
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;
}
}

View File

@ -0,0 +1,183 @@
<?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 $Revision: 1.0 $
* @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
/**
* 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;
}
/**
* 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->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.");
}
}
}

View File

@ -0,0 +1,77 @@
<?php
/*
* $Id: MailTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Send a message by mail()
*
* <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 $Revision: 1.1 $
* @package phing.tasks.ext
*/
class MailTask extends Task {
protected $recipient;
protected $subject;
protected $msg;
function main() {
$this->log('Sending mail to ' . $this->recipient );
mail($this->recipient, $this->subject, $this->msg);
}
/** setter for message */
function setMsg($msg) {
$this->setMessage($msg);
}
/** alias setter */
function setMessage($msg) {
$this->msg = (string) $msg;
}
/** setter for subject **/
function setSubject($subject) {
$this->subject = (string) $subject;
}
/** setter for recipient **/
function setRecipient($recipient) {
$this->recipient = (string) $recipient;
}
/** alias for recipient **/
function setTo($recipient) {
$this->recipient = (string) $recipient;
}
/** Supporting the <mail>Message</mail> syntax. */
function addText($msg)
{
$this->msg = (string) $msg;
}
}

View File

@ -0,0 +1,65 @@
<?php
/*
* $Id: PackageAsPathTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Convert dot-notation packages to relative paths.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1.5 $
* @package phing.tasks.ext
*/
class PackageAsPathTask extends Task {
/** The package to convert. */
protected $pckg;
/** The value to store the conversion in. */
protected $name;
/**
* Executes the package to patch converstion and stores it
* in the user property <code>value</code>.
*/
public function main()
{
$this->project->setUserProperty($this->name, strtr($this->pckg, '.', '/'));
}
/**
* @param string $pckg the package to convert
*/
public function setPackage($pckg)
{
$this->pckg = $pckg;
}
/**
* @param string $name the Ant variable to store the path in
*/
public function setName($name)
{
$this->name = $name;
}
}

View File

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

View File

@ -0,0 +1,82 @@
<?php
require_once 'phing/Task.php';
/**
* A PHP lint task. Checking syntax of one or more PHP source file.
*
* @author Knut Urdalen <knut.urdalen@telio.no>
* @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
/**
* 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];
}
/**
* 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);
}
}
}
}
/**
* 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);
}
}
}
?>

View File

@ -0,0 +1,610 @@
<?php
/*
* $Id: SmartyTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/BuildException.php';
include_once 'phing/util/StringHelper.php';
/**
* A phing task for generating output by using Smarty.
*
* This is based on the TexenTask from Apache's Velocity engine. This class
* was originally proted in order to provide a template compiling system for
* Torque.
*
* TODO:
* - Add Path / useClasspath support?
*
* @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 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext
*/
class SmartyTask extends Task {
/**
* Smarty template engine.
* @var Smarty
*/
protected $context;
/**
* Variables that are assigned to the context on parse/compile.
* @var array
*/
protected $properties = array();
/**
* This is the control template that governs the output.
* It may or may not invoke the services of worker
* templates.
* @var string
*/
protected $controlTemplate;
/**
* This is where Velocity will look for templates
* using the file template loader.
* @var string
*/
protected $templatePath;
/**
* This is where texen will place all the output
* that is a product of the generation process.
* @var string
*/
protected $outputDirectory;
/**
* This is the file where the generated text
* will be placed.
* @var string
*/
protected $outputFile;
/**
* <p>
* These are properties that are fed into the
* initial context from a properties file. This
* is simply a convenient way to set some values
* that you wish to make available in the context.
* </p>
* <p>
* These values are not critical, like the template path
* or output path, but allow a convenient way to
* set a value that may be specific to a particular
* generation task.
* </p>
* <p>
* For example, if you are generating scripts to allow
* user to automatically create a database, then
* you might want the <code>$databaseName</code>
* to be placed
* in the initial context so that it is available
* in a script that might look something like the
* following:
* <code><pre>
* #!bin/sh
*
* echo y | mysqladmin create $databaseName
* </pre></code>
* The value of <code>$databaseName</code> isn't critical to
* output, and you obviously don't want to change
* the ant task to simply take a database name.
* So initial context values can be set with
* properties file.
*
* @var array
*/
protected $contextProperties;
/**
* Smarty compiles templates before parsing / replacing tokens in them.
* By default it will try ./templates_c, but you may wish to override this.
* @var string
*/
protected $compilePath;
/**
* Whether to force Smarty to recompile templates.
* Smarty does check file modification time, but you can set this
* to be *sure* that the template will be compiled (of course it will
* be slower if you do).
* @var boolean
*/
protected $forceCompile = false;
/**
* Smarty can use config files.
* This tells Smarty where to look for the config files.
* @var string
*/
protected $configPath;
/**
* Customize the left delimiter for Smarty tags.
* @var string
*/
protected $leftDelimiter;
/**
* Customize the right delimiter for Smarty tags.
* @var string
*/
protected $rightDelimiter;
// -----------------------------------------------------------------------
// The following getters & setters are used by phing to set properties
// specified in the XML for the smarty task.
// -----------------------------------------------------------------------
public function init() {
include_once 'Smarty.class.php';
if (!class_exists('Smarty')) {
throw new BuildException("To use SmartyTask, you must have the path to Smarty.class.php on your include_path or your \$PHP_CLASSPATH environment variable.");
}
}
/**
* [REQUIRED] Set the control template for the
* generating process.
* @param string $controlTemplate
* @return void
*/
public function setControlTemplate ($controlTemplate) {
$this->controlTemplate = $controlTemplate;
}
/**
* Get the control template for the
* generating process.
* @return string
*/
public function getControlTemplate() {
return $this->controlTemplate;
}
/**
* [REQUIRED] Set the path where Velocity will look
* for templates using the file template
* loader.
* @return void
* @throws Exception
*/
public function setTemplatePath($templatePath) {
$resolvedPath = "";
$tok = strtok($templatePath, ",");
while ( $tok ) {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($tok);
$cpath = $fullPath->getCanonicalPath();
if ($cpath === false) {
$this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
} else {
$resolvedPath .= $cpath;
}
$tok = strtok(",");
if ( $tok ) {
$resolvedPath .= ",";
}
}
$this->templatePath = $resolvedPath;
}
/**
* Get the path where Velocity will look
* for templates using the file template
* loader.
* @return string
*/
public function getTemplatePath() {
return $this->templatePath;
}
/**
* [REQUIRED] Set the output directory. It will be
* created if it doesn't exist.
* @param PhingFile $outputDirectory
* @return void
* @throws Exception
*/
public function setOutputDirectory(PhingFile $outputDirectory) {
try {
if (!$outputDirectory->exists()) {
$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());
}
}
$this->outputDirectory = $outputDirectory->getCanonicalPath();
} catch (IOException $ioe) {
throw new BuildException($ioe->getMessage());
}
}
/**
* Get the output directory.
* @return string
*/
public function getOutputDirectory() {
return $this->outputDirectory;
}
/**
* [REQUIRED] Set the output file for the
* generation process.
* @return void
*/
public function setOutputFile($outputFile) {
$this->outputFile = $outputFile;
}
/**
* Get the output file for the
* generation process.
* @return string
*/
public function getOutputFile() {
return $this->outputFile;
}
/**
* Set the path Smarty uses as a "cache" for compiled templates.
* @param string $compilePath
*/
public function setCompilePath($compilePath) {
$this->compilePath = $compilePath;
}
/**
* Get the path Smarty uses for compiling templates.
* @return string
*/
public function getCompilePath() {
return $this->compilePath;
}
/**
* Set whether Smarty should always recompile tempaltes.
* @param boolean $force
* @return void
*/
public function setForceCompile($force) {
$this->forceCompile = (boolean) $force;
}
/**
* Get whether Smarty should always recompile template.
* @return boolean
*/
public function getForceCompile() {
return $this->forceCompile;
}
/**
* Set where Smarty looks for config files.
* @param string $configPath
* @return void
*/
public function setConfigPath($configPath) {
$this->configPath = $configPath;
}
/**
* Get the path that Smarty uses for looking for config files.
* @return string
*/
public function getConfigPath() {
return $this->configPath;
}
/**
* Set Smarty template left delimiter.
* @param string $delim
* @return void
*/
public function setLeftDelimiter($delim) {
$this->leftDelimiter = $delim;
}
/**
* Get Smarty template right delimiter
* @return string
*/
public function getLeftDelimiter() {
return $this->leftDelimiter;
}
/**
* Set Smarty template right delimiter.
* @param string $delim
* @return void
*/
public function setRightDelimiter($delim) {
$this->rightDelimiter = $delim;
}
/**
* Get Smarty template right delimiter
* @return string
*/
public function getRightDelimiter() {
return $this->rightDelimiter;
}
/**
* Set the context properties that will be
* fed into the initial context be the
* generating process starts.
* @param string $file
* @return void
*/
public function setContextProperties($file) {
$sources = explode(",", $file);
$this->contextProperties = new Properties();
// Always try to get the context properties resource
// from a file first. Templates may be taken from a JAR
// file but the context properties resource may be a
// resource in the filesystem. If this fails than attempt
// to get the context properties resource from the
// classpath.
for ($i=0, $sourcesLength=count($sources); $i < $sourcesLength; $i++) {
$source = new Properties();
try {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($sources[$i]);
$this->log("Using contextProperties file: " . $fullPath->__toString());
$source->load($fullPath);
} catch (Exception $e) {
throw new BuildException("Context properties file " . $sources[$i] .
" could not be found in the file system!");
}
$keys = $source->keys();
foreach ($keys as $key) {
$name = $key;
$value = $this->project->replaceProperties($source->getProperty($name));
$this->contextProperties->setProperty($name, $value);
}
}
}
/**
* Get the context properties that will be
* fed into the initial context be the
* generating process starts.
* @return Properties
*/
public function getContextProperties() {
return $this->contextProperties;
}
// ---------------------------------------------------------------
// End of XML setters & getters
// ---------------------------------------------------------------
/**
* Creates a Smarty object.
*
* @return Smarty initialized (cleared) Smarty context.
* @throws Exception the execute method will catch
* and rethrow as a <code>BuildException</code>
*/
public function initControlContext() {
$this->context->clear_all_assign();
return $this->context;
}
/**
* Execute the input script with Velocity
*
* @throws BuildException
* BuildExceptions are thrown when required attributes are missing.
* Exceptions thrown by Velocity are rethrown as BuildExceptions.
*/
public function main() {
// Make sure the template path is set.
if (empty($this->templatePath)) {
throw new BuildException("The template path needs to be defined!");
}
// Make sure the control template is set.
if ($this->controlTemplate === null) {
throw new BuildException("The control template needs to be defined!");
}
// Make sure the output directory is set.
if ($this->outputDirectory === null) {
throw new BuildException("The output directory needs to be defined!");
}
// Make sure there is an output file.
if ($this->outputFile === null) {
throw new BuildException("The output file needs to be defined!");
}
// Setup Smarty runtime.
// Smarty uses one object to store properties and to store
// the context for the template (unlike Velocity). We setup this object, calling it
// $this->context, and then initControlContext simply zeros out
// any assigned variables.
$this->context = new Smarty();
if ($this->compilePath !== null) {
$this->log("Using compilePath: " . $this->compilePath);
$this->context->compile_dir = $this->compilePath;
}
if ($this->configPath !== null) {
$this->log("Using configPath: " . $this->configPath);
$this->context->config_dir = $this->configPath;
}
if ($this->forceCompile !== null) {
$this->context->force_compile = $this->forceCompile;
}
if ($this->leftDelimiter !== null) {
$this->context->left_delimiter = $this->leftDelimiter;
}
if ($this->rightDelimiter !== null) {
$this->context->right_delimiter = $this->rightDelimiter;
}
if ($this->templatePath !== null) {
$this->log("Using templatePath: " . $this->templatePath);
$this->context->template_dir = $this->templatePath;
}
$smartyCompilePath = new PhingFile($this->context->compile_dir);
if (!$smartyCompilePath->exists()) {
$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);
}
}
// Make sure the output directory exists, if it doesn't
// then create it.
$file = new PhingFile($this->outputDirectory);
if (!$file->exists()) {
$this->log("Output directory does not exist, creating: " . $file->getAbsolutePath());
$file->mkdirs();
}
$path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
$this->log("Generating to file " . $path);
$writer = new FileWriter($path);
// The generator and the output path should
// be placed in the init context here and
// not in the generator class itself.
$c = $this->initControlContext();
// Set any variables that need to always
// be loaded
$this->populateInitialContext($c);
// Feed all the options into the initial
// control context so they are available
// in the control/worker templates.
if ($this->contextProperties !== null) {
foreach($this->contextProperties->keys() as $property) {
$value = $this->contextProperties->getProperty($property);
// Special exception (from Texen)
// for properties ending in file.contents:
// in that case we dump the contents of the file
// as the "value" for the Property.
if (StringHelper::endsWith("file.contents", $property)) {
// pull in contents of file specified
$property = substr($property, 0, strpos($property, "file.contents") - 1);
// reset value, and then
// read in teh contents of the file into that var
$value = "";
$f = new PhingFile($project->resolveFile($value)->getCanonicalPath());
if ($f->exists()) {
try {
$fr = new FileReader($f);
$fr->readInto($value);
} catch (Exception $e) {
throw $e;
}
}
} // if ends with file.contents
if (StringHelper::isBoolean($value)) {
$value = StringHelper::booleanValue($value);
}
$c->assign($property, $value);
} // foreach property
} // if contextProperties !== null
try {
//$c->display($this->controlTemplate);
$writer->write($c->fetch($this->controlTemplate));
$writer->close();
} catch (IOException $ioe) {
$writer->close();
throw new BuildException("Cannot write parsed template.");
}
$this->cleanup();
}
/**
* <p>Place useful objects into the initial context.</p>
*
* <p>TexenTask places <code>Date().toString()</code> into the
* context as <code>$now</code>. Subclasses who want to vary the
* objects in the context should override this method.</p>
*
* <p><code>$generator</code> is not put into the context in this
* method.</p>
*
* @param context The context to populate, as retrieved from
* {@link #initControlContext()}.
* @return void
* @throws Exception Error while populating context. The {@link
* #execute()} method will catch and rethrow as a
* <code>BuildException</code>.
*/
protected function populateInitialContext(Smarty $context) {
}
/**
* A hook method called at the end of {@link #execute()} which can
* be overridden to perform any necessary cleanup activities (such
* as the release of database connections, etc.). By default,
* does nothing.
* @return void
* @throws Exception Problem cleaning up.
*/
protected function cleanup() {
}
}

425
lib/symfony/vendor/phing/tasks/ext/TarTask.php vendored Executable file
View File

@ -0,0 +1,425 @@
<?php
/*
* $Id: TarTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Creates a tar archive using PEAR Archive_Tar.
*
* @author Hans Lellelid <hans@xmpl.org> (Phing)
* @author Stefano Mazzocchi <stefano@apache.org> (Ant)
* @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
* @author Magesh Umasankar
* @version $Revision: 1.10 $
* @package phing.tasks.ext
*/
class TarTask extends MatchingTask {
const TAR_NAMELEN = 100;
const WARN = "warn";
const FAIL = "fail";
const OMIT = "omit";
private $tarFile;
private $baseDir;
private $includeEmpty = true; // Whether to include empty dirs in the TAR
private $longFileMode = "warn";
private $filesets = array();
private $fileSetFiles = array();
/**
* Indicates whether the user has been warned about long files already.
*/
private $longWarningGiven = false;
/**
* Compression mode. Available options "gzip", "bzip2", "none" (null).
*/
private $compression = null;
/**
* 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 TarTask.");
}
}
/**
* Add a new fileset
* @return FileSet
*/
public function createTarFileSet() {
$this->fileset = new TarFileSet();
$this->filesets[] = $this->fileset;
return $this->fileset;
}
/**
* Add a new fileset. Alias to createTarFileSet() for backwards compatibility.
* @return FileSet
* @see createTarFileSet()
*/
public function createFileSet() {
$this->fileset = new TarFileSet();
$this->filesets[] = $this->fileset;
return $this->fileset;
}
/**
* Set is the name/location of where to create the tar file.
* @param PhingFile $destFile The output of the tar
*/
public function setDestFile(PhingFile $destFile) {
$this->tarFile = $destFile;
}
/**
* This is the base directory to look in for things to tar.
* @param PhingFile $baseDir
*/
public function setBasedir(PhingFile $baseDir) {
$this->baseDir = $baseDir;
}
/**
* Set the include empty dirs flag.
* @param boolean Flag if empty dirs should be tarred too
* @return void
* @access public
*/
function setIncludeEmptyDirs($bool) {
$this->includeEmpty = (boolean) $bool;
}
/**
* Set how to handle long files, those with a path&gt;100 chars.
* Optional, default=warn.
* <p>
* Allowable values are
* <ul>
* <li> truncate - paths are truncated to the maximum length
* <li> fail - paths greater than the maximim cause a build exception
* <li> warn - paths greater than the maximum cause a warning and GNU is used
* <li> gnu - GNU extensions are used for any paths greater than the maximum.
* <li> omit - paths greater than the maximum are omitted from the archive
* </ul>
*/
public function setLongfile($mode) {
$this->longFileMode = $mode;
}
/**
* Set compression method.
* Allowable values are
* <ul>
* <li> none - no compression
* <li> gzip - Gzip compression
* <li> bzip2 - Bzip2 compression
* </ul>
*/
public function setCompression($mode) {
switch($mode) {
case "gzip":
$this->compression = "gz";
break;
case "bzip2":
$this->compression = "bz2";
break;
case "none":
$this->compression = null;
break;
default:
$this->log("Ignoring unknown compression mode: ".$mode, PROJECT_MSG_WARN);
$this->compression = null;
}
}
/**
* do the work
* @throws BuildException
*/
public function main() {
if ($this->tarFile === null) {
throw new BuildException("tarfile attribute must be set!", $this->getLocation());
}
if ($this->tarFile->exists() && $this->tarFile->isDirectory()) {
throw new BuildException("tarfile is a directory!", $this->getLocation());
}
if ($this->tarFile->exists() && !$this->tarFile->canWrite()) {
throw new BuildException("Can not write to the specified tarfile!", $this->getLocation());
}
// shouldn't need to clone, since the entries in filesets
// themselves won't be modified -- only elements will be added
$savedFileSets = $this->filesets;
try {
if ($this->baseDir !== null) {
if (!$this->baseDir->exists()) {
throw new BuildException("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;
}
}
if (empty($this->filesets)) {
throw new BuildException("You must supply either a basedir "
. "attribute or some nested filesets.",
$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;
}
}
$this->log("Building tar: " . $this->tarFile->__toString(), PROJECT_MSG_INFO);
$tar = new Archive_Tar($this->tarFile->getAbsolutePath(), $this->compression);
// print errors
$tar->setErrorHandling(PEAR_ERROR_PRINT);
foreach($this->filesets as $fs) {
$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.");
}
$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();
}
$tar->addModify($filesToTar, '', $fsBasedir->getAbsolutePath());
}
} catch (IOException $ioe) {
$msg = "Problem creating TAR: " . $ioe->getMessage();
$this->filesets = $savedFileSets;
throw new BuildException($msg, $ioe, $this->getLocation());
}
$this->filesets = $savedFileSets;
}
/**
* @param array $files array of filenames
* @param PhingFile $dir
* @return boolean
*/
protected function archiveIsUpToDate($files, $dir) {
$sfs = new SourceFileScanner($this);
$mm = new MergeMapper();
$mm->setTo($this->tarFile->getAbsolutePath());
return count($sfs->restrict($files, $dir, null, $mm)) == 0;
}
}
/**
* This is a FileSet with the option to specify permissions.
*
* Permissions are currently not implemented by PEAR Archive_Tar,
* but hopefully they will be in the future.
*
*/
class TarFileSet extends FileSet {
private $files = null;
private $mode = 0100644;
private $userName = "";
private $groupName = "";
private $prefix = "";
private $fullpath = "";
private $preserveLeadingSlashes = false;
/**
* 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 ($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;
}
/**
* A 3 digit octal string, specify the user, group and
* other modes in the standard Unix fashion;
* optional, default=0644
* @param string $octalString
*/
public function setMode($octalString) {
$octal = (int) $octalString;
$this->mode = 0100000 | $octal;
}
public function getMode() {
return $this->mode;
}
/**
* The username for the tar entry
* This is not the same as the UID, which is
* not currently set by the task.
*/
public function setUserName($userName) {
$this->userName = $userName;
}
public function getUserName() {
return $this->userName;
}
/**
* The groupname for the tar entry; optional, default=""
* This is not the same as the GID, which is
* not currently set by the task.
*/
public function setGroup($groupName) {
$this->groupName = $groupName;
}
public function getGroup() {
return $this->groupName;
}
/**
* If the prefix attribute is set, all files in the fileset
* are prefixed with that path in the archive.
* optional.
*/
public function setPrefix($prefix) {
$this->prefix = $prefix;
}
public function getPrefix() {
return $this->prefix;
}
/**
* If the fullpath attribute is set, the file in the fileset
* is written with that path in the archive. The prefix attribute,
* if specified, is ignored. It is an error to have more than one file specified in
* such a fileset.
*/
public function setFullpath($fullpath) {
$this->fullpath = $fullpath;
}
public function getFullpath() {
return $this->fullpath;
}
/**
* Flag to indicates whether leading `/'s should
* be preserved in the file names.
* Optional, default is <code>false</code>.
* @return void
*/
public function setPreserveLeadingSlashes($b) {
$this->preserveLeadingSlashes = (boolean) $b;
}
public function getPreserveLeadingSlashes() {
return $this->preserveLeadingSlashes;
}
}

View File

@ -0,0 +1,90 @@
<?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 $Revision: 1.0 $
* @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 = substr($tarfileName, strrpos($tarfileName, '.'));
switch($mode) {
case '.gz':
$compression = 'gz';
break;
case '.bz2':
$compression = 'bz2';
break;
case '.tar':
break;
default:
$this->log('Ignoring unknown compression mode: ' . $mode, PROJECT_MSG_WARN);
}
return new Archive_Tar($tarfile->getAbsolutePath(), $compression);
}
}

View File

@ -0,0 +1,68 @@
<?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';
require_once 'phing/lib/Zip.php';
/**
* Extracts one or several zip archive using PEAR Archive_Zip (which is presently unreleased
* and included with Phing).
*
* @author Joakim Bodin <joakim.bodin+phing@gmail.com>
* @version $Revision: 1.0 $
* @package phing.tasks.ext
* @since 2.2.0
*/
class UnzipTask extends ExtractBaseTask {
protected function extractArchive(PhingFile $zipfile)
{
$extractParams = array('add_path' => $this->todir->getAbsolutePath());
if(!empty($this->removepath))
{
$extractParams['remove_path'] = $this->removepath;
}
$this->log("Extracting zip: " . $zipfile->__toString() . ' to ' . $this->todir->__toString(), PROJECT_MSG_INFO);
try {
$zip = new Archive_Zip($zipfile->getAbsolutePath());
$extractResponse = $zip->extract($extractParams);
if(is_array($extractResponse)) {
foreach ($extractResponse as $extractedPath) {
$this->log('Extracted' . $extractedPath['stored_filename'] . ' to ' . $this->todir->__toString(), PROJECT_MSG_VERBOSE);
}
} else if ($extractResponse === 0) {
throw new BuildException('Failed to extract zipfile: ' . $zip->errorInfo(true));
}
} catch (IOException $ioe) {
$msg = "Could not extract ZIP: " . $ioe->getMessage();
throw new BuildException($msg, $ioe, $this->getLocation());
}
}
protected function listArchiveContent(PhingFile $zipfile)
{
$zip = new Archive_Zip($zipfile->getAbsolutePath());
return $zip->listContent();
}
}

View File

@ -0,0 +1,116 @@
<?php
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>
* @package phing.tasks.ext
*/
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
/**
* File to be performed syntax check on
*
* @param PhingFile $file
*/
public function setFile(PhingFile $file) {
$this->file = $file;
}
/**
* XML Schema Description file to validate against
*
* @param PhingFile $schema
*/
public function setSchema(PhingFile $schema) {
$this->schema = $schema;
}
/**
* 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];
}
/**
* 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->file) and count($this->filesets) == 0) {
throw new BuildException("Missing either a nested fileset or attribute 'file' set");
}
set_error_handler(array($this, 'errorHandler'));
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);
}
}
}
restore_error_handler();
}
/**
* Performs validation
*
* @param string $file
* @return void
*/
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);
}
} else {
throw new BuildException('Permission denied: '.$file);
}
} else {
throw new BuildException('File not found: '.$file);
}
}
/**
* Local error handler to catch validation errors and log them through Phing
*
* @param int $level
* @param string $message
* @param string $file
* @param int $line
*/
public function errorHandler($level, $message, $file, $line, $context) {
$matches = array();
preg_match('/^.*\(\): (.*)$/', $message, $matches);
$this->log($matches[1], PROJECT_MSG_ERR);
}
}
?>

View File

@ -0,0 +1,163 @@
<?php
require_once 'phing/Task.php';
/**
* ZendCodeAnalyzerTask analyze PHP source code using the ZendCodeAnalyzer included in Zend Studio 5.1
*
* Available warnings:
* <b>zend-error</b> - %s(line %d): %s
* <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.
* <b>bool-object</b> - Object used when boolean expression is expected.
* <b>call-time-ref</b> - Call-time reference is deprecated. Define function as accepting parameter by reference instead.
* <b>if-if-else</b> - In if-if-else construction else relates to the closest if. Use braces to make the code clearer.
* <b>define-params</b> - define() requires two or three parameters.
* <b>define-const</b> - First parameter for define() should be string. Maybe you forgot quotes?
* <b>break-var</b> - Break/continue with variable is dangerous - break level can be out of scope.
* <b>break-depth</b> - Break/continue with depth more than current nesting level.
* <b>var-once</b> - Variable '%s' encountered only once. May be a typo?
* <b>var-arg-unused</b> - Function argument '%s' is never used.
* <b>var-global-unused</b> - Global variable '%s' is defined but never used.
* <b>var-use-before-def</b> - Variable '%s' is used before it was assigned.
* <b>var-use-before-def-global</b> - Global variable '%s' is used without being assigned. You are probably relying on register_globals feature of PHP. Note that this feature is off by default.
* <b>var-no-global</b> - PHP global variable '%s' is used as local. Maybe you wanted to define '%s' as global?
* <b>var-value-unused</b> - Value assigned to variable '%s' is never used
* <b>var-ref-notmodified</b> - Function parameter '%s' is passed by reference but never modified. Consider passing by value.
* <b>return-empty-val</b> - Function '%s' has both empty return and return with value.
* <b>return-empty-used</b> - Function '%s' has empty return but return value is used.
* <b>return-noref</b> - Function '%s' returns reference but the value is not assigned by reference. Maybe you meant '=&' instead of '='?
* <b>return-end-used</b> - Control reaches the end of function '%s'(file %s, line %d) but return value is used.
* <b>sprintf-miss-args</b> - Missing arguments for sprintf: format reqires %d arguments but %d are supplied.
* <b>sprintf-extra-args</b> - Extra arguments for sprintf: format reqires %d arguments but %d are supplied.
* <b>unreach-code</b> - Unreachable code in function '%s'.
* <b>include-var</b> - include/require with user-accessible variable can be dangerous. Consider using constant instead.
* <b>non-object</b> - Variable '%s' used as object, but has different type.
* <b>bad-escape</b> - Bad escape sequence: \%c, did you mean \\%c?
* <b>empty-cond</b> - Condition without a body
* <b>expr-unused</b> - Expression result is never used
*
* @author Knut Urdalen <knut.urdalen@telio.no>
* @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];
}
/**
* 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);
}
/**
* 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);
}
}
}
?>

176
lib/symfony/vendor/phing/tasks/ext/ZipTask.php vendored Executable file
View File

@ -0,0 +1,176 @@
<?php
/*
* $Id: ZipTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
include_once 'phing/lib/Zip.php';
/**
* Creates a zip archive using PEAR Archive_Zip (which is presently unreleased
* and included with Phing).
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Revision: 1.2 $
* @package phing.tasks.ext
* @since 2.1.0
*/
class ZipTask extends MatchingTask {
private $zipFile;
private $baseDir;
private $filesets = array();
private $fileSetFiles = array();
/**
* Add a new fileset.
* @return FileSet
*/
public function createFileSet() {
$this->fileset = new FileSet();
$this->filesets[] = $this->fileset;
return $this->fileset;
}
/**
* Set is the name/location of where to create the zip file.
* @param PhingFile $destFile The output of the zip
*/
public function setDestFile(PhingFile $destFile) {
$this->zipFile = $destFile;
}
/**
* This is the base directory to look in for things to zip.
* @param PhingFile $baseDir
*/
public function setBasedir(PhingFile $baseDir) {
$this->baseDir = $baseDir;
}
/**
* do the work
* @throws BuildException
*/
public function main() {
if ($this->zipFile === null) {
throw new BuildException("zipfile attribute must be set!", $this->getLocation());
}
if ($this->zipFile->exists() && $this->zipFile->isDirectory()) {
throw new BuildException("zipfile is a directory!", $this->getLocation());
}
if ($this->zipFile->exists() && !$this->zipFile->canWrite()) {
throw new BuildException("Can not write to the specified zipfile!", $this->getLocation());
}
// shouldn't need to clone, since the entries in filesets
// themselves won't be modified -- only elements will be added
$savedFileSets = $this->filesets;
try {
if ($this->baseDir !== null) {
if (!$this->baseDir->exists()) {
throw new BuildException("basedir does not exist!", $this->getLocation());
}
// 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)) {
throw new BuildException("You must supply either a basedir "
. "attribute or some nested filesets.",
$this->getLocation());
}
// check if zip is out of date with respect to each
// fileset
$upToDate = true;
foreach($this->filesets as $fs) {
$ds = $fs->getDirectoryScanner($this->project);
$files = $ds->getIncludedFiles();
if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) {
$upToDate = false;
}
for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
if ($this->zipFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) {
throw new BuildException("A zip file cannot include itself", $this->getLocation());
}
}
}
if ($upToDate) {
$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);
$zip = new Archive_Zip($this->zipFile->getAbsolutePath());
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);
$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->getCanonicalPath()));
}
} catch (IOException $ioe) {
$msg = "Problem creating ZIP: " . $ioe->getMessage();
$this->filesets = $savedFileSets;
throw new BuildException($msg, $ioe, $this->getLocation());
}
$this->filesets = $savedFileSets;
}
/**
* @param array $files array of filenames
* @param PhingFile $dir
* @return boolean
*/
protected function archiveIsUpToDate($files, $dir) {
$sfs = new SourceFileScanner($this);
$mm = new MergeMapper();
$mm->setTo($this->zipFile->getAbsolutePath());
return count($sfs->restrict($files, $dir, null, $mm)) == 0;
}
}

View File

@ -0,0 +1,127 @@
<?php
/**
* $Id: CoverageMerger.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/util/Properties.php';
/**
* Saves coverage output of the test to a specified database
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: CoverageMerger.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.coverage
* @since 2.1.0
*/
class CoverageMerger
{
private static function mergeCodeCoverage($left, $right)
{
$coverageMerged = array();
reset($left);
reset($right);
while (current($left) && current($right))
{
$linenr_left = key($left);
$linenr_right = key($right);
if ($linenr_left < $linenr_right)
{
$coverageMerged[$linenr_left] = current($left);
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))
{
$coverageMerged[key($left)] = current($left);
next($left);
}
while (current($right))
{
$coverageMerged[key($right)] = current($right);
next($right);
}
return $coverageMerged;
}
static function merge($project, $codeCoverageInformation)
{
$database = new PhingFile($project->getProperty('coverage.database'));
$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));
}
}
}
$props->store($database);
}
}
?>

View File

@ -0,0 +1,92 @@
<?php
/**
* $Id: CoverageMergerTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/system/util/Properties.php';
require_once 'phing/tasks/ext/coverage/CoverageMerger.php';
/**
* Merges code coverage snippets into a code coverage database
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: CoverageMergerTask.php 3076 2006-12-18 08:52:12Z fabien $
* @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();
/**
* 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();
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();
}
}
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));
}
}
}
?>

View File

@ -0,0 +1,407 @@
<?php
/**
* $Id: CoverageReportTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/system/util/Properties.php';
require_once 'phing/tasks/ext/phpunit2/PHPUnit2Util.php';
require_once 'phing/tasks/ext/coverage/CoverageReportTransformer.php';
/**
* Transforms information in a code coverage database to XML
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: CoverageReportTask.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.coverage
* @since 2.1.0
*/
class CoverageReportTask extends Task
{
private $outfile = "coverage.xml";
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);
}
}
function createClasspath()
{
$this->classpath = new Path();
return $this->classpath;
}
function setGeshiPath($path)
{
$this->geshipath = $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 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;
}
protected function getPackageElement($packageName)
{
$packages = $this->doc->documentElement->getElementsByTagName('package');
foreach ($packages as $package)
{
if ($package->getAttribute('name') == $packageName)
{
return $package;
}
}
return NULL;
}
protected function addClassToPackage($classname, $element)
{
$packageName = PHPUnit2Util::getPackageName($classname);
$package = $this->getPackageElement($packageName);
if ($package === NULL)
{
$package = $this->doc->createElement('package');
$package->setAttribute('name', $packageName);
$this->doc->documentElement->appendChild($package);
}
$package->appendChild($element);
}
protected function stripDiv($source)
{
$openpos = strpos($source, "<div");
$closepos = strpos($source, ">", $openpos);
$line = substr($source, $closepos + 1);
$tagclosepos = strpos($line, "</div>");
$line = substr($line, 0, $tagclosepos);
return $line;
}
protected function highlightSourceFile($filename)
{
if ($this->geshipath)
{
require_once $this->geshipath . '/geshi.php';
$source = file_get_contents($filename);
$geshi = new GeSHi($source, 'php', $this->geshilanguagespath);
$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
$geshi->enable_strict_mode(true);
$geshi->enable_classes(true);
$geshi->set_url_for_keyword_group(3, '');
$html = $geshi->parse_code();
$lines = split("<li>|</li>", $html);
// skip first and last line
array_pop($lines);
array_shift($lines);
$lines = array_filter($lines);
$lines = array_map(array($this, 'stripDiv'), $lines);
return $lines;
}
else
{
$lines = file($filename);
for ($i = 0; $i < count($lines); $i++)
{
$line = $lines[$i];
$line = rtrim($line);
$lines[$i] = utf8_encode($line);
}
return $lines;
}
}
protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1)
{
$sourceElement = $this->doc->createElement('sourcefile');
$sourceElement->setAttribute('name', basename($filename));
$filelines = $this->highlightSourceFile($filename);
$linenr = 1;
foreach ($filelines as $line)
{
$lineElement = $this->doc->createElement('sourceline');
$lineElement->setAttribute('coveredcount', (isset($coverageInformation[$linenr]) ? $coverageInformation[$linenr] : '0'));
if ($linenr == $classStartLine)
{
$lineElement->setAttribute('startclass', 1);
}
$textnode = $this->doc->createTextNode($line);
$lineElement->appendChild($textnode);
$sourceElement->appendChild($lineElement);
$linenr++;
}
return $sourceElement;
}
protected function filterCovered($var)
{
return ($var >= 0);
}
protected function transformCoverageInformation($filename, $coverageInformation)
{
// Strip last line of coverage information
end($coverageInformation);
unset($coverageInformation[key($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);
$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]);
}
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;
}
// small fix for XDEBUG_CC_UNUSED
if (isset($coverageInformation[$method->getStartLine()]))
{
unset($coverageInformation[$method->getStartLine()]);
}
if (isset($coverageInformation[$method->getEndLine()]))
{
unset($coverageInformation[$method->getEndLine()]);
}
if ($method->isAbstract())
{
continue;
}
$linenr = key($coverageInformation);
while ($linenr !== null && $linenr < $method->getStartLine())
{
next($coverageInformation);
$linenr = key($coverageInformation);
}
if (current($coverageInformation) > 0 && $method->getStartLine() <= $linenr && $linenr <= $method->getEndLine())
{
$methodscovered++;
}
$methodcount++;
}
$statementcount = count($coverageInformation);
$statementscovered = count(array_filter($coverageInformation, array($this, 'filterCovered')));
$classElement->appendChild($this->transformSourceFile($filename, $coverageInformation, $classStartLine));
$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);
}
}
}
protected function calculateStatistics()
{
$packages = $this->doc->documentElement->getElementsByTagName('package');
$totalmethodcount = 0;
$totalmethodscovered = 0;
$totalstatementcount = 0;
$totalstatementscovered = 0;
foreach ($packages as $package)
{
$methodcount = 0;
$methodscovered = 0;
$statementcount = 0;
$statementscovered = 0;
$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()
{
$this->log("Transforming coverage report");
$database = new PhingFile($this->project->getProperty('coverage.database'));
$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();
}
}
}
?>

View File

@ -0,0 +1,121 @@
<?php
/**
* $Id: CoverageReportTransformer.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 Phing/Xdebug code coverage xml report.
* The default transformation generates an html report in framed style.
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: CoverageReportTransformer.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.coverage
* @since 2.1.0
*/
class CoverageReportTransformer
{
private $task = NULL;
private $styleDir = "";
private $toDir = "";
private $document = NULL;
function __construct(Task $task)
{
$this->task = $task;
}
function setStyleDir($styleDir)
{
$this->styleDir = $styleDir;
}
function setToDir($toDir)
{
$this->toDir = $toDir;
}
function setXmlDocument($document)
{
$this->document = $document;
}
function transform()
{
$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);
ExtendedFileStream::registerStream();
// no output for the framed report
// it's all done by extension...
$proc->setParameter('', 'output.dir', $dir->getAbsolutePath());
$proc->transformToXML($this->document);
}
private function getStyleSheet()
{
$xslname = "coverage-frames.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;
}
}
?>

View File

@ -0,0 +1,163 @@
<?php
/**
* $Id: CoverageSetupTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/system/util/Properties.php';
require_once 'phing/tasks/ext/coverage/CoverageMerger.php';
/**
* Initializes a code coverage database
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: CoverageSetupTask.php 3076 2006-12-18 08:52:12Z fabien $
* @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 filename of the coverage database */
private $database = "coverage.db";
/** the classpath to use (optional) */
private $classpath = NULL;
/**
* 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;
}
/**
* Sets the filename of the coverage database to use
*
* @param string the filename of the database
*/
function setDatabase($database)
{
$this->database = $database;
}
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;
}
/**
* 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();
foreach ($this->filesets as $fileset)
{
$ds = $fileset->getDirectoryScanner($this->project);
$ds->scan();
$includedFiles = $ds->getIncludedFiles();
foreach ($includedFiles as $file)
{
if (strstr($file, ".php"))
{
$fs = new PhingFile(realpath($ds->getBaseDir()), $file);
$files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath());
}
}
}
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();
$this->log("Setting up coverage database for " . count($files) . " files");
$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());
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));
}
}
}
?>

View File

@ -0,0 +1,44 @@
<?php
/**
* $Id: IoncubeComment.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 for comments for ionCube tasks
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: IoncubeComment.php 3076 2006-12-18 08:52:12Z fabien $
* @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);
}
}
?>

View File

@ -0,0 +1,336 @@
<?php
/**
* $Id: IoncubeEncoderTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/ioncube/IoncubeComment.php';
/**
* Invokes the ionCube Encoder (PHP4 or PHP5)
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: IoncubeEncoderTask.php 3076 2006-12-18 08:52:12Z fabien $
* @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();
/**
* 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;
}
/**
* Sets the version of PHP to use (defaults to 5)
*/
function setPhpVersion($phpVersion)
{
$this->phpVersion = $phpVersion;
}
/**
* 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;
}
/**
* Returns the source directory
*/
function getFromDir($fromDir)
{
return $this->fromDir;
}
/**
* Sets the target directory
*/
function setToDir($toDir)
{
$this->toDir = $toDir;
}
/**
* Returns the target directory
*/
function getToDir($toDir)
{
return $this->toDir;
}
/**
* 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;
}
/**
* Sets the optimize option
*/
function setOptimize($optimize)
{
$this->optimize = $optimize;
}
/**
* Returns the optimize option
*/
function getOptimize()
{
return $this->optimize;
}
/**
* 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 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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);
if ($return != 0)
{
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 . "' ";
}
if (!empty($this->passPhrase))
{
$arguments.= "--passphrase '" . $this->passPhrase . "' ";
}
foreach ($this->comments as $comment)
{
$arguments.= "--add-comment '" . $comment->getValue() . "' ";
}
if ($this->fromDir != "")
{
$arguments .= $this->fromDir . " ";
}
if ($this->toDir != "")
{
$arguments .= "-o " . $this->toDir . " ";
}
return $arguments;
}
}
?>

View File

@ -0,0 +1,144 @@
<?php
/**
* $Id: IoncubeLicenseTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/ioncube/IoncubeComment.php';
/**
* Invokes the ionCube "make_license" program
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: IoncubeLicenseTask.php 3076 2006-12-18 08:52:12Z fabien $
* @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();
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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);
if ($return != 0)
{
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 . "' ";
}
return $arguments;
}
}
?>

View File

@ -0,0 +1,231 @@
<?php
/*
* $Id: Fileset.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Builds list of files for PEAR_PackageFileManager using a Phing FileSet.
*
* Some code here is taken from PEAR_PackageFileManager_File -- getting results from flat
* array into the assoc array expected from getFileList().
*
* @author Greg Beaver
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.tasks.ext.pearpackage
* @version $Revision: 1.7 $
*/
class PEAR_PackageFileManager_Fileset {
/**
* @access private
* @var PEAR_PackageFileManager
*/
private $parent;
/**
* Curent Phing Project.
* @var Project
*/
private $project;
/**
* FileSets to use.
* @var array FileSet[]
*/
private $filesets = array();
/**
* Set up the FileSet filelist generator
*
* 'project' and 'filesets' are the only options that this class uses.
*
* @param PEAR_PackageFileManager
* @param array
*/
function __construct($parent, $options)
{
$this->parent = $parent;
$this->project = $options['phing_project'];
$this->filesets = $options['phing_filesets'];
}
/**
* Generate the <filelist></filelist> section
* of the package file.
*
* This function performs the backend generation of the array
* containing all files in this package
* @return array structure of all files to include
*/
function getFileList() {
$allfiles = array();
foreach($this->filesets as $fs) {
$ds = $fs->getDirectoryScanner($this->project);
$files = $ds->getIncludedFiles();
// We need to store these files keyed by the basedir from DirectoryScanner
// so that we can resolve the fullpath of the file later.
if (isset($allfiles[$ds->getBasedir()]))
{
$allfiles[$ds->getBasedir()] = array_merge($allfiles[$ds->getBasedir()], $files);
}
else
{
$allfiles[$ds->getBasedir()] = $files;
}
}
$struc = array();
foreach($allfiles as $basedir => $files) {
foreach($files as $file) {
// paths are relative to $basedir above
$path = strtr(dirname($file), DIRECTORY_SEPARATOR, '/');
if (!$path || $path == '.') {
$path = '/'; // for array index
}
$parts = explode('.', basename($file));
$ext = array_pop($parts);
if (strlen($ext) == strlen($file)) {
$ext = '';
}
$f = new PhingFile($basedir, $file);
$struc[$path][] = array('file' => basename($file),
'ext' => $ext,
'path' => (($path == '/') ? basename($file) : $path . '/' . basename($file)),
'fullpath' => $f->getAbsolutePath());
}
}
uksort($struc,'strnatcasecmp');
foreach($struc as $key => $ind) {
usort($ind, array($this, 'sortfiles'));
$struc[$key] = $ind;
}
$tempstruc = $struc;
$struc = array('/' => $tempstruc['/']);
$bv = 0;
foreach($tempstruc as $key => $ind) {
$save = $key;
if ($key != '/') {
$struc['/'] = $this->setupDirs($struc['/'], explode('/', $key), $tempstruc[$key]);
}
}
uksort($struc['/'], array($this, 'mystrucsort'));
return $struc;
}
/**
* Recursively move contents of $struc into associative array
*
* The contents of $struc have many indexes like 'dir/subdir/subdir2'.
* This function converts them to
* array('dir' => array('subdir' => array('subdir2')))
* @param array struc is array('dir' => array of files in dir,
* 'dir/subdir' => array of files in dir/subdir,...)
* @param array array form of 'dir/subdir/subdir2' array('dir','subdir','subdir2')
* @return array same as struc but with array('dir' =>
* array(file1,file2,'subdir' => array(file1,...)))
*/
private function setupDirs($struc, $dir, $contents) {
if (!count($dir)) {
foreach($contents as $dir => $files) {
if (is_string($dir)) {
if (strpos($dir, '/')) {
$test = true;
$a = $contents[$dir];
unset($contents[$dir]);
$b = explode('/', $dir);
$c = array_shift($b);
if (isset($contents[$c])) {
$contents[$c] = $this->setDir($contents[$c], $this->setupDirs(array(), $b, $a));
} else {
$contents[$c] = $this->setupDirs(array(), $b, $a);
}
}
}
}
return $contents;
}
$me = array_shift($dir);
if (!isset($struc[$me])) {
$struc[$me] = array();
}
$struc[$me] = $this->setupDirs($struc[$me], $dir, $contents);
return $struc;
}
/**
* Recursively add all the subdirectories of $contents to $dir without erasing anything in
* $dir
* @param array
* @param array
* @return array processed $dir
*/
function setDir($dir, $contents)
{
while(list($one,$two) = each($contents)) {
if (isset($dir[$one])) {
$dir[$one] = $this->setDir($dir[$one], $contents[$one]);
} else {
$dir[$one] = $two;
}
}
return $dir;
}
/**
* Sorting functions for the file list
* @param string
* @param string
* @access private
*/
function sortfiles($a, $b)
{
return strnatcasecmp($a['file'],$b['file']);
}
function mystrucsort($a, $b)
{
if (is_numeric($a) && is_string($b)) return 1;
if (is_numeric($b) && is_string($a)) return -1;
if (is_numeric($a) && is_numeric($b))
{
if ($a > $b) return 1;
if ($a < $b) return -1;
if ($a == $b) return 0;
}
return strnatcasecmp($a,$b);
}
}
?>

View File

@ -0,0 +1,191 @@
<?php
/**
* $Id: PHPDocumentorTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PHPDocumentorTask.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.phpdoc
*/
class PHPDocumentorTask extends Task
{
/**
* The path to the executable for phpDocumentor
*/
private $programPath = 'phpdoc';
private $title = "Default Title";
private $destdir = ".";
private $sourcepath = NULL;
private $output = "";
private $linksource = false;
private $parseprivate = false;
/**
* Sets the path to the phpDocumentor executable
*/
function setProgramPath($programPath)
{
$this->programPath = $programPath;
}
/**
* Returns the path to the phpDocumentor executable
*/
function getProgramPath()
{
return $this->programPath;
}
/**
* 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();
$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
*/
private function constructArguments()
{
$arguments = "-q on ";
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 on ";
}
if ($this->parseprivate)
{
$arguments.= "-pp on ";
}
return $arguments;
}
};
?>

View File

@ -0,0 +1,171 @@
<?php
/**
* $Id: BatchTest.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: BatchTest.php 3076 2006-12-18 08:52:12Z fabien $
* @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, $this->classpath);
$declaredClasses = array_merge($declaredClasses, $definedClasses);
}
$elements = array_filter($declaredClasses, array($this, "filterTests"));
return $elements;
}
}
?>

View File

@ -0,0 +1,120 @@
<?php
/**
* $Id: FormatterElement.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: FormatterElement.php 3076 2006-12-18 08:52:12Z fabien $
* @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;
}
}
?>

View File

@ -0,0 +1,187 @@
<?php
/**
* $Id: PHPUnit2ReportTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PHPUnit2ReportTask.php 3076 2006-12-18 08:52:12Z fabien $
* @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;
}
/**
* Returns the path to the XSL stylesheet
*/
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;
}
/**
* Transforms the DOM document
*/
private function transform(DOMDocument $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);
}
}
/**
* Fixes 'testsuite' elements with no package attribute, adds
* package="default" to those elements.
*/
private function fixPackages(DOMDocument $document)
{
$testsuites = $document->getElementsByTagName('testsuite');
foreach ($testsuites as $testsuite)
{
if (!$testsuite->hasAttribute('package'))
{
$testsuite->setAttribute('package', 'default');
}
}
}
/**
* The main entry point
*
* @throws BuildException
*/
public function main()
{
$testSuitesDoc = new DOMDocument();
$testSuitesDoc->load($this->inFile);
$this->fixPackages($testSuitesDoc);
$this->transform($testSuitesDoc);
}
}
?>

View File

@ -0,0 +1,158 @@
<?php
/**
* $Id: PHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @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 addSkippedTest(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;
}
}
}
?>

View File

@ -0,0 +1,239 @@
<?php
/**
* $Id: PHPUnit2Task.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PHPUnit2Task.php 3076 2006-12-18 08:52:12Z fabien $
* @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;
}
}
?>

View File

@ -0,0 +1,107 @@
<?php
/**
* $Id: PHPUnit2TestRunner.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PHPUnit2TestRunner.php 3076 2006-12-18 08:52:12Z fabien $
* @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;
}
}
?>

View File

@ -0,0 +1,121 @@
<?php
/**
* $Id: PHPUnit2Util.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PHPUnit2Util.php 3076 2006-12-18 08:52:12Z fabien $
* @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()]);
}
}
if (isset(self::$definedClasses[$filename]))
{
return self::$definedClasses[$filename];
}
else
{
return array();
}
}
}
?>

View File

@ -0,0 +1,117 @@
<?php
/**
* $Id: PlainPHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: PlainPHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @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();
}
}
}
?>

View File

@ -0,0 +1,58 @@
<?php
/**
* $Id: SummaryPHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php';
/**
* Prints short summary output of the test to Phing's logging system.
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SummaryPHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.phpunit2
* @since 2.1.0
*/
class SummaryPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter
{
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;
}
}
?>

View File

@ -0,0 +1,117 @@
<?php
/**
* $Id: XMLPHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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.rook@gmail.com>
* @version $Id: XMLPHPUnit2ResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @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();
}
}
}
?>

View File

@ -0,0 +1,52 @@
<?php
/**
* $Id: SimpleTestCountResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Dummy result formatter used to count SimpleTest results
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SimpleTestCountResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @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;
}
}
?>

View File

@ -0,0 +1,62 @@
<?php
/**
* $Id: SimpleTestFormatterElement.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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/SimpleTestPlainResultFormatter.php';
require_once 'phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php';
require_once 'phing/tasks/ext/phpunit2/FormatterElement.php';
/**
* Child class of "FormatterElement", overrides setType to provide other
* formatter classes for SimpleTest
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SimpleTestFormatterElement.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.simpletest
* @since 2.2.0
*/
class SimpleTestFormatterElement extends FormatterElement
{
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");
}
}
}
?>

View File

@ -0,0 +1,95 @@
<?php
/**
* $Id: SimpleTestPlainResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 <michiel.rook@gmail.com>
* @version $Id: SimpleTestPlainResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.simpletest
* @since 2.2.0
*/
class SimpleTestPlainResultFormatter extends SimpleTestResultFormatter
{
private $inner = "";
function getExtension()
{
return ".txt";
}
function getPreferredOutfile()
{
return "testresults";
}
function paintCaseStart($test_name)
{
parent::paintCaseStart($test_name);
$this->inner = "";
}
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";
}
}
?>

View File

@ -0,0 +1,162 @@
<?php
/**
* $Id: SimpleTestResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 '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.rook@gmail.com>
* @version $Id: SimpleTestResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.phpunit2
* @since 2.2.0
*/
abstract class SimpleTestResultFormatter extends SimpleReporter
{
protected $out = NULL;
protected $project = NULL;
private $timer = NULL;
private $runCount = 0;
private $failureCount = 0;
private $errorCount = 0;
private $currentTest = "";
/**
* 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;
}
}
}
?>

View File

@ -0,0 +1,54 @@
<?php
/**
* $Id: SimpleTestSummaryResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 short summary output of the test to Phing's logging system.
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SimpleTestSummaryResultFormatter.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.simpletest
* @since 2.2.0
*/
class SimpleTestSummaryResultFormatter extends SimpleTestResultFormatter
{
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";
if ($this->out != NULL)
{
$this->out->write($sb);
}
}
}
}
?>

View File

@ -0,0 +1,238 @@
<?php
/**
* $Id: SimpleTestTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 SimpleTest tests.
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SimpleTestTask.php 3076 2006-12-18 08:52:12Z fabien $
* @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;
/**
* 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/SimpleTestFormatterElement.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;
}
/**
* Add a new formatter to all tests of this task.
*
* @param SimpleTestFormatterElement formatter element
*/
function addFormatter(SimpleTestFormatterElement $fe)
{
$this->formatters[] = $fe;
}
/**
* 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;
}
/**
* 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);
}
}
?>

View File

@ -0,0 +1,180 @@
<?php
/*
* $Id: SvnBaseTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Send a message by mail()
*
* <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 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext
*/
abstract class SvnBaseTask extends Task
{
private $workingCopy = "";
private $repositoryUrl = "";
private $svnPath = "/usr/bin/svn";
private $svn = NULL;
private $mode = "";
private $svnArgs = 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.");
}
}
/**
* Sets the path to the workingcopy
*/
function setWorkingCopy($workingCopy)
{
$this->workingCopy = $workingCopy;
}
/**
* Returns the path to the workingcopy
*/
function getWorkingCopy()
{
return $this->workingCopy;
}
/**
* Sets the path/URI to the repository
*/
function setRepositoryUrl($repositoryUrl)
{
$this->repositoryUrl = $repositoryUrl;
}
/**
* Returns the path/URI to the repository
*/
function getRepositoryUrl()
{
return $this->repositoryUrl;
}
/**
* 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;
}
/**
* 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);
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");
}
}
}
/**
* 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);
throw new BuildException("Failed to run the 'svn " . $this->mode . "' command: " . $err['message']);
}
}
}
}
?>

View File

@ -0,0 +1,68 @@
<?php
/**
* $Id: SvnExportTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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';
/**
* Exports/checks out a repository to a local directory
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SvnExportTask.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.svn
* @see VersionControl_SVN
* @since 2.1.0
*/
class SvnExportTask extends SvnBaseTask
{
private $toDir = "";
/**
* 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;
}
/**
* The main entry point
*
* @throws BuildException
*/
function main()
{
$this->setup('export');
$this->log("Exporting SVN repository to '" . $this->toDir . "'");
$this->run(array($this->toDir));
}
}
?>

View File

@ -0,0 +1,75 @@
<?php
/**
* $Id: SvnLastRevisionTask.php 3076 2006-12-18 08:52:12Z fabien $
*
* 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 number of the last revision of a workingcopy in a property
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: SvnLastRevisionTask.php 3076 2006-12-18 08:52:12Z fabien $
* @package phing.tasks.ext.svn
* @see VersionControl_SVN
* @since 2.1.0
*/
class SvnLastRevisionTask extends SvnBaseTask
{
private $propertyName = "svn.lastrevision";
/**
* 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;
}
/**
* 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'.");
}
}
}
?>