diff options
author | ctrlaltca <> | 2013-01-02 14:42:24 +0000 |
---|---|---|
committer | ctrlaltca <> | 2013-01-02 14:42:24 +0000 |
commit | edf2251aca60a970e822079d23933e5b70b26571 (patch) | |
tree | 366b6688efbb03f20f47268bea57859cea673c70 /buildscripts/phing/classes/phing/tasks | |
parent | 8e5f2510bd577e15095e46afc7d0ba6808549bf8 (diff) |
backported all related changes up to 3229 to branch/3.2
Diffstat (limited to 'buildscripts/phing/classes/phing/tasks')
208 files changed, 28763 insertions, 4702 deletions
diff --git a/buildscripts/phing/classes/phing/tasks/defaults.properties b/buildscripts/phing/classes/phing/tasks/defaults.properties index d0e62eff..32a03295 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/defaults.properties +++ b/buildscripts/phing/classes/phing/tasks/defaults.properties @@ -3,13 +3,15 @@ ; ------------------------------------- ; Internal system tasks -; +; adhoc=phing.tasks.system.AdhocTask adhoc-task=phing.tasks.system.AdhocTaskdefTask adhoc-type=phing.tasks.system.AdhocTypedefTask append=phing.tasks.system.AppendTask available=phing.tasks.system.AvailableTask chmod=phing.tasks.system.ChmodTask +chown=phing.tasks.system.ChownTask +concat=phing.tasks.system.AppendTask condition=phing.tasks.system.ConditionTask copy=phing.tasks.system.CopyTask cvs=phing.tasks.system.CvsTask @@ -17,7 +19,7 @@ cvspass=phing.tasks.system.CvsPassTask delete=phing.tasks.system.DeleteTask echo=phing.tasks.system.EchoTask exec=phing.tasks.system.ExecTask -fail=phing.tasks.system.ExitTask +fail=phing.tasks.system.FailTask foreach=phing.tasks.system.ForeachTask includepath=phing.tasks.system.IncludePathTask input=phing.tasks.system.InputTask @@ -38,32 +40,106 @@ uptodate=phing.tasks.system.UpToDateTask xslt=phing.tasks.system.XsltTask if=phing.tasks.system.IfTask warn=phing.tasks.system.WarnTask +import=phing.tasks.system.ImportTask +loadfile=phing.tasks.system.LoadFileTask ; "Core" contributed tasks ; -- i.e. no taskdef needed. -sql=phing.tasks.ext.CreoleSQLExecTask +creole=phing.tasks.ext.creole.CreoleSQLExecTask +pdo=phing.tasks.ext.pdo.PDOSQLExecTask +pdosqlexec=phing.tasks.ext.pdo.PDOSQLExecTask package-as-path=phing.tasks.ext.PackageAsPathTask smarty=phing.tasks.ext.SmartyTask capsule=phing.tasks.ext.CapsuleTask tar=phing.tasks.ext.TarTask +untar=phing.tasks.ext.UntarTask pearpkg=phing.tasks.ext.PearPackageTask +pearpkg2=phing.tasks.ext.PearPackage2Task mail=phing.tasks.ext.MailTask zip=phing.tasks.ext.ZipTask -phplint=phing.tasks.ext.PhpLintTask +unzip=phing.tasks.ext.UnzipTask +waitfor=phing.tasks.system.WaitForTask +trycatch=phing.tasks.system.TryCatchTask ; "ext" tasks -phpdoc=phing.tasks.ext.phpdoc.PHPDocumentorTask +phpdoc=phing.tasks.ext.phpdoc.PhpDocumentorTask +phpdocext=phing.tasks.ext.phpdoc.PhpDocumentorExternalTask svnlastrevision=phing.tasks.ext.svn.SvnLastRevisionTask +svncheckout=phing.tasks.ext.svn.SvnCheckoutTask svnexport=phing.tasks.ext.svn.SvnExportTask -phpunit2=phing.tasks.ext.phpunit2.PHPUnit2Task -phpunit2report=phing.tasks.ext.phpunit2.PHPUnit2ReportTask +svnupdate=phing.tasks.ext.svn.SvnUpdateTask +svnswitch=phing.tasks.ext.svn.SvnSwitchTask +svncopy=phing.tasks.ext.svn.SvnCopyTask +svncommit=phing.tasks.ext.svn.SvnCommitTask +svnlist=phing.tasks.ext.svn.SvnListTask +svnlog=phing.tasks.ext.svn.SvnLogTask +svninfo=phing.tasks.ext.svn.SvnInfoTask +gitinit=phing.tasks.ext.git.GitInitTask +gitclone=phing.tasks.ext.git.GitCloneTask +gitgc=phing.tasks.ext.git.GitGcTask +gitbranch=phing.tasks.ext.git.GitBranchTask +gitfetch=phing.tasks.ext.git.GitFetchTask +gitmerge=phing.tasks.ext.git.GitMergeTask +gitcheckout=phing.tasks.ext.git.GitCheckoutTask +gitpull=phing.tasks.ext.git.GitPullTask +gitpush=phing.tasks.ext.git.GitPushTask +gitlog=phing.tasks.ext.git.GitLogTask +gittag=phing.tasks.ext.git.GitTagTask +phpunit3=phing.tasks.ext.phpunit.PHPUnitTask +phpunit3report=phing.tasks.ext.phpunit.PHPUnitReportTask +phpunit=phing.tasks.ext.phpunit.PHPUnitTask +phpunitreport=phing.tasks.ext.phpunit.PHPUnitReportTask coverage-setup=phing.tasks.ext.coverage.CoverageSetupTask coverage-merger=phing.tasks.ext.coverage.CoverageMergerTask coverage-report=phing.tasks.ext.coverage.CoverageReportTask +coverage-threshold=phing.tasks.ext.coverage.CoverageThresholdTask ioncubeencoder=phing.tasks.ext.ioncube.IoncubeEncoderTask ioncubelicense=phing.tasks.ext.ioncube.IoncubeLicenseTask simpletest=phing.tasks.ext.simpletest.SimpleTestTask phplint=phing.tasks.ext.PhpLintTask xmllint=phing.tasks.ext.XmlLintTask -analyze=phing.tasks.ext.ZendCodeAnalyzerTask
\ No newline at end of file +analyze=phing.tasks.ext.ZendCodeAnalyzerTask +zendcodeanalyzer=phing.tasks.ext.ZendCodeAnalyzerTask +jsllint=phing.tasks.ext.JslLintTask +manifest=phing.tasks.ext.ManifestTask +phpcodesniffer=phing.tasks.ext.PhpCodeSnifferTask +phpcpd=phing.tasks.ext.phpcpd.PHPCPDTask +phpmd=phing.tasks.ext.phpmd.PHPMDTask +phpdepend=phing.tasks.ext.pdepend.PhpDependTask +ftpdeploy=phing.tasks.ext.FtpDeployTask +phkpackage=phing.tasks.ext.phk.PhkPackageTask +pharpackage=phing.tasks.ext.phar.PharPackageTask +scp=phing.tasks.ext.ScpTask +; deprecate ScpSendTask +scpsend=phing.tasks.ext.ScpTask +ssh=phing.tasks.ext.SshTask +replaceregexp=phing.tasks.ext.ReplaceRegexpTask +jsmin=phing.tasks.ext.jsmin.JsMinTask +version=phing.tasks.ext.VersionTask +filehash=phing.tasks.ext.FileHashTask +filesize=phing.tasks.ext.FileSizeTask +xmlproperty=phing.tasks.ext.XmlPropertyTask +exportproperties=phing.tasks.ext.ExportPropertiesTask +http-request=phing.tasks.ext.HttpRequestTask +httpget=phing.tasks.ext.HttpGetTask +patch=phing.tasks.ext.PatchTask +dbdeploy=phing.tasks.ext.dbdeploy.DbDeployTask +symlink=phing.tasks.ext.SymlinkTask +s3get=phing.tasks.ext.Service.Amazon.S3.S3GetTask +s3put=phing.tasks.ext.Service.Amazon.S3.S3PutTask +zendguardencode=phing.tasks.ext.zendguard.ZendGuardEncodeTask +zendguardlicense=phing.tasks.ext.zendguard.ZendGuardLicenseTask +docblox=phing.tasks.ext.docblox.DocBloxTask +phpdoc2=phing.tasks.ext.phpdoc.PhpDocumentor2Task +rST=phing.tasks.ext.rSTTask +apigen=phing.tasks.ext.apigen.ApiGenTask +parallel=phing.tasks.ext.ParallelTask +symfonyconsole=phing.tasks.ext.SymfonyConsole.SymfonyConsoleTask +; liquibase +liquibase-changelog=phing.tasks.ext.liquibase.LiquibaseChangeLogTask +liquibase-dbdoc=phing.tasks.ext.liquibase.LiquibaseDbDocTask +liquibase-diff=phing.tasks.ext.liquibase.LiquibaseDiffTask +liquibase-rollback=phing.tasks.ext.liquibase.LiquibaseRollbackTask +liquibase-tag=phing.tasks.ext.liquibase.LiquibaseTagTask +liquibase-update=phing.tasks.ext.liquibase.LiquibaseUpdateTask diff --git a/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php b/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php index aa43a0e4..13ccd73d 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: CapsuleTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 205bc55fd1f7f36783d105ff2d0e27357282bbed $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/util/StringHelper.php'; * This is based on the interface to TexenTask from Apache's Velocity engine. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.17 $ + * @version $Id: 205bc55fd1f7f36783d105ff2d0e27357282bbed $ * @package phing.tasks.ext */ class CapsuleTask extends Task { @@ -185,7 +185,7 @@ class CapsuleTask extends Task { public function setOutputDirectory(PhingFile $outputDirectory) { try { if (!$outputDirectory->exists()) { - $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE); + $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),Project::MSG_VERBOSE); if (!$outputDirectory->mkdirs()) { throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath()); } @@ -393,7 +393,7 @@ class CapsuleTask extends Task { // reset value, and then // read in teh contents of the file into that var $value = ""; - $f = new PhingFile($project->resolveFile($value)->getCanonicalPath()); + $f = new PhingFile($this->project->resolveFile($value)->getCanonicalPath()); if ($f->exists()) { $fr = new FileReader($f); $fr->readInto($value); @@ -453,25 +453,27 @@ class CapsuleTask extends Task { /** * An "inner" class for holding assigned var values. * May be need to expand beyond name/value in the future. + * + * @package phing.tasks.ext */ class AssignedVar { private $name; private $value; - function setName($v) { + public function setName($v) { $this->name = $v; } - function setValue($v) { + public function setValue($v) { $this->value = $v; } - function getName() { + public function getName() { return $this->name; } - function getValue() { + public function getValue() { return $this->value; } diff --git a/buildscripts/phing/classes/phing/tasks/ext/ExportPropertiesTask.php b/buildscripts/phing/classes/phing/tasks/ext/ExportPropertiesTask.php new file mode 100644 index 00000000..8bc64bbb --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ExportPropertiesTask.php @@ -0,0 +1,141 @@ +<?php + +/* + * $Id: 7d96a453b74edc40fdea85ba8befe6459334016d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once "phing/Task.php"; + +/** + * Saves currently defined properties into a specified file + * + * @author Andrei Serdeliuc + * @extends Task + * @version $Id: 7d96a453b74edc40fdea85ba8befe6459334016d $ + * @package phing.tasks.ext + */ +class ExportPropertiesTask extends Task +{ + /** + * Array of project properties + * + * (default value: null) + * + * @var array + * @access private + */ + private $_properties = null; + + /** + * Target file for saved properties + * + * (default value: null) + * + * @var string + * @access private + */ + private $_targetFile = null; + + /** + * Exclude properties starting with these prefixes + * + * @var array + * @access private + */ + private $_disallowedPropertyPrefixes = array( + 'host.', + 'phing.', + 'os.', + 'php.', + 'line.', + 'env.', + 'user.' + ); + + /** + * setter for _targetFile + * + * @access public + * @param string $file + * @return bool + */ + public function setTargetFile($file) + { + if(!is_dir(dirname($file))) { + throw new BuildException("Parent directory of target file doesn't exist"); + } + + if(!is_writable(dirname($file)) && (file_exists($file) && !is_writable($file))) { + throw new BuildException("Target file isn't writable"); + } + + $this->_targetFile = $file; + return true; + } + + /** + * setter for _disallowedPropertyPrefixes + * + * @access public + * @param string $file + * @return bool + */ + public function setDisallowedPropertyPrefixes($prefixes) + { + $this->_disallowedPropertyPrefixes = explode(",", $prefixes); + return true; + } + + public function main() + { + // Sets the currently declared properties + $this->_properties = $this->getProject()->getProperties(); + + if(is_array($this->_properties) && !empty($this->_properties) && null !== $this->_targetFile) { + $propertiesString = ''; + foreach($this->_properties as $propertyName => $propertyValue) { + if(!$this->isDisallowedPropery($propertyName)) { + $propertiesString .= $propertyName . "=" . $propertyValue . PHP_EOL; + } + } + + if(!file_put_contents($this->_targetFile, $propertiesString)) { + throw new BuildException('Failed writing to ' . $this->_targetFile); + } + } + } + + /** + * Checks if a property name is disallowed + * + * @access protected + * @param string $propertyName + * @return bool + */ + protected function isDisallowedPropery($propertyName) + { + foreach($this->_disallowedPropertyPrefixes as $property) { + if(substr($propertyName, 0, strlen($property)) == $property) { + return true; + } + } + + return false; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/ExtractBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/ExtractBaseTask.php new file mode 100644 index 00000000..e47acc24 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ExtractBaseTask.php @@ -0,0 +1,199 @@ +<?php +/* + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/system/MatchingTask.php'; + +/** + * Base class for extracting tasks such as Unzip and Untar. + * + * @author Joakim Bodin <joakim.bodin+phing@gmail.com> + * @version $Id: 8aa7996b72792da30f1ec94174f09b9c612bcc1a $ + * @package phing.tasks.ext + * @since 2.2.0 + */ +abstract class ExtractBaseTask extends MatchingTask { + /** + * @var PhingFile $file + */ + protected $file; + /** + * @var PhingFile $todir + */ + protected $todir; + protected $removepath; + protected $filesets = array(); // all fileset objects assigned to this task + + /** + * Set to true to always extract (and possibly overwrite) + * all files from the archive + * @var boolean + */ + protected $forceExtract = false; + + /** + * Add a new fileset. + * @return FileSet + */ + public function createFileSet() { + $this->fileset = new FileSet(); + $this->filesets[] = $this->fileset; + return $this->fileset; + } + + /** + * Set the name of the zip file to extract. + * @param PhingFile $file zip file to extract + */ + public function setFile(PhingFile $file) { + $this->file = $file; + } + + /** + * This is the base directory to look in for things to zip. + * @param PhingFile $baseDir + */ + public function setToDir(PhingFile $todir) { + $this->todir = $todir; + } + + public function setRemovePath($removepath) + { + $this->removepath = $removepath; + } + + /** + * Sets the forceExtract attribute + * @param boolean $forceExtract + */ + public function setForceExtract($forceExtract) + { + $this->forceExtract = (bool) $forceExtract; + } + + /** + * do the work + * @throws BuildException + */ + public function main() { + + $this->validateAttributes(); + + $filesToExtract = array(); + if ($this->file !== null) { + if(!$this->isDestinationUpToDate($this->file)) { + $filesToExtract[] = $this->file; + } else { + $this->log('Nothing to do: ' . $this->todir->getAbsolutePath() . ' is up to date for ' . $this->file->getCanonicalPath(), Project::MSG_INFO); + } + } + + foreach($this->filesets as $compressedArchiveFileset) { + $compressedArchiveDirScanner = $compressedArchiveFileset->getDirectoryScanner($this->project); + $compressedArchiveFiles = $compressedArchiveDirScanner->getIncludedFiles(); + $compressedArchiveDir = $compressedArchiveFileset->getDir($this->project); + + foreach ($compressedArchiveFiles as $compressedArchiveFilePath) { + $compressedArchiveFile = new PhingFile($compressedArchiveDir, $compressedArchiveFilePath); + if($compressedArchiveFile->isDirectory()) + { + throw new BuildException($compressedArchiveFile->getAbsolutePath() . ' compressed archive cannot be a directory.'); + } + + if ($this->forceExtract || !$this->isDestinationUpToDate($compressedArchiveFile)) { + $filesToExtract[] = $compressedArchiveFile; + } else { + $this->log('Nothing to do: ' . $this->todir->getAbsolutePath() . ' is up to date for ' . $compressedArchiveFile->getCanonicalPath(), Project::MSG_INFO); + } + } + } + + foreach ($filesToExtract as $compressedArchiveFile) { + $this->extractArchive($compressedArchiveFile); + } + } + + abstract protected function extractArchive(PhingFile $compressedArchiveFile); + + /** + * @param array $files array of filenames + * @param PhingFile $dir + * @return boolean + */ + protected function isDestinationUpToDate(PhingFile $compressedArchiveFile) { + if (!$compressedArchiveFile->exists()) { + throw new BuildException("Could not find file " . $compressedArchiveFile->__toString() . " to extract."); + } + + $compressedArchiveContent = $this->listArchiveContent($compressedArchiveFile); + if(is_array($compressedArchiveContent)) { + + $fileSystem = FileSystem::getFileSystem(); + foreach ($compressedArchiveContent as $compressArchivePathInfo) { + $compressArchiveFilename = $compressArchivePathInfo['filename']; + if(!empty($this->removepath) && strlen($compressArchiveFilename) >= strlen($this->removepath)) + { + $compressArchiveFilename = preg_replace('/^' . $this->removepath . '/','', $compressArchiveFilename); + } + $compressArchivePath = new PhingFile($this->todir, $compressArchiveFilename); + + if(!$compressArchivePath->exists() || + $fileSystem->compareMTimes($compressedArchiveFile->getCanonicalPath(), $compressArchivePath->getCanonicalPath()) == 1) { + return false; + } + } + + } + + return true; + } + + abstract protected function listArchiveContent(PhingFile $compressedArchiveFile); + + /** + * Validates attributes coming in from XML + * + * @access private + * @return void + * @throws BuildException + */ + protected function validateAttributes() { + + if ($this->file === null && count($this->filesets) === 0) { + throw new BuildException("Specify at least one source compressed archive - a file or a fileset."); + } + + if ($this->todir === null) { + throw new BuildException("todir must be set."); + } + + if ($this->todir !== null && $this->todir->exists() && !$this->todir->isDirectory()) { + throw new BuildException("todir must be a directory."); + } + + if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) { + throw new BuildException("Compressed archive file cannot be a directory."); + } + + if ($this->file !== null && !$this->file->exists()) { + throw new BuildException("Could not find compressed archive file " . $this->file->__toString() . " to extract."); + } + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/FileHashTask.php b/buildscripts/phing/classes/phing/tasks/ext/FileHashTask.php new file mode 100644 index 00000000..5660e793 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/FileHashTask.php @@ -0,0 +1,147 @@ +<?php +/* + * $Id: c59aff266a03f0e2cf22dc33143f2decf2d5e05c $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ +require_once 'phing/Task.php'; + +/** + * fileHash + * + * Calculate either MD5 or SHA hash value of a specified file and retun the + * value in a property + * + * @author Johan Persson <johan162@gmail.com> + * @version $Id: c59aff266a03f0e2cf22dc33143f2decf2d5e05c $ + * @package phing.tasks.ext + */ +class FileHashTask extends Task +{ + /** + * Property for File + * @var PhingFile file + */ + private $file; + + /** + * Property to be set + * @var string $property + */ + private $propertyName = "filehashvalue"; + + /** + * Specify which hash algorithm to use. + * 0 = MD5 + * 1 = SHA1 + * + * @var integer $hashtype + */ + private $hashtype=0; + + + /** + * Specify if MD5 or SHA1 hash should be used + * @param integer $type 0=MD5, 1=SHA1 + */ + public function setHashtype($type) + { + $this->hashtype = $type; + } + + /** + * Which file to calculate the hash value of + * @param PhingFile $file + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Set the name of the property to store the hash value in + * @param $property + * @return void + */ + public function setPropertyName($property) + { + $this->propertyName = $property; + } + + /** + * Main-Method for the Task + * + * @return void + * @throws BuildException + */ + public function main() + { + $this->checkFile(); + $this->checkPropertyName(); + + // read file + if( (int)$this->hashtype === 0 ) { + $this->log("Calculating MD5 hash from: ".$this->file); + $hashValue = md5_file($this->file,false); + } + elseif( (int)$this->hashtype === 1 ) { + $this->log("Calculating SHA1 hash from: ".$this->file); + $hashValue = sha1_file($this->file,false); + } + else { + throw new BuildException( + sprintf('[FileHash] Unknown hashtype specified %d. Must be either 0 (=MD5) or 1 (=SHA1).',$this->hashtype)); + + } + + // publish hash value + $this->project->setProperty($this->propertyName, $hashValue); + + } + + /** + * checks file attribute + * @return void + * @throws BuildException + */ + private function checkFile() + { + // check File + if ($this->file === null || + strlen($this->file) == 0) { + throw new BuildException('[FileHash] You must specify an input file.', $this->file); + } + + if( ! is_readable($this->file) ) { + throw new BuildException(sprintf('[FileHash] Input file does not exist or is not readable: %s',$this->file)); + } + + } + + /** + * checks property attribute + * @return void + * @throws BuildException + */ + private function checkPropertyName() + { + if (is_null($this->propertyName) || + strlen($this->propertyName) === 0) { + throw new BuildException('Property name for publishing hashvalue is not set'); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/FileSizeTask.php b/buildscripts/phing/classes/phing/tasks/ext/FileSizeTask.php new file mode 100644 index 00000000..120197dd --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/FileSizeTask.php @@ -0,0 +1,120 @@ +<?php +/* + * $Id: 2a59c1a9b46f3fd71df0fd3b50908eff268fd630 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ +require_once 'phing/Task.php'; + +/** + * fileHash + * + * Calculate either MD5 or SHA hash value of a specified file and retun the + * value in a property + * + * @author Johan Persson <johan162@gmail.com> + * @version $Id: 2a59c1a9b46f3fd71df0fd3b50908eff268fd630 $ + * @package phing.tasks.ext + */ +class FileSizeTask extends Task +{ + /** + * Property for File + * @var PhingFile file + */ + private $file; + + /** + * Property where the file size will be stored + * @var string $property + */ + private $propertyName = "filesize"; + + /** + * Which file to calculate the file size of + * @param PhingFile $file + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Set the name of the property to store the file size + * @param $property + * @return void + */ + public function setPropertyName($property) + { + $this->propertyName = $property; + } + + /** + * Main-Method for the Task + * + * @return void + * @throws BuildException + */ + public function main() + { + $this->checkFile(); + $this->checkPropertyName(); + + $size = filesize($this->file); + + if( $size === false ) { + throw new BuildException(sprintf('[FileSize] Cannot determine size of file: %s',$this->file)); + + } + + // publish hash value + $this->project->setProperty($this->propertyName, $size); + + } + + /** + * checks file attribute + * @return void + * @throws BuildException + */ + private function checkFile() + { + // check File + if ($this->file === null || + strlen($this->file) == 0) { + throw new BuildException('[FileSize] You must specify an input file.', $this->file); + } + + if( ! is_readable($this->file) ) { + throw new BuildException(sprintf('[FileSize] Input file does not exist or is not readable: %s',$this->file)); + } + + } + + /** + * checks property attribute + * @return void + * @throws BuildException + */ + private function checkPropertyName() + { + if (is_null($this->propertyName) || + strlen($this->propertyName) === 0) { + throw new BuildException('[FileSize] Property name for publishing file size is not set'); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/FtpDeployTask.php b/buildscripts/phing/classes/phing/tasks/ext/FtpDeployTask.php new file mode 100644 index 00000000..136c0ac7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/FtpDeployTask.php @@ -0,0 +1,233 @@ +<?php +/** + * $Id: 87063ecf88b18eae74c2bca3918a1b4ac9f52807 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * FtpDeployTask + * + * Deploys a set of files to a remote FTP server. + * + * + * Example usage: + * <ftpdeploy host="host" port="21" username="user" password="password" dir="public_html" mode="ascii" clearfirst="true"> + * <fileset dir="."> + * <include name="**"/> + * <exclude name="phing"/> + * <exclude name="build.xml"/> + * <exclude name="images/**.png"/> + * <exclude name="images/**.gif"/> + * <exclude name="images/**.jpg"/> + * </fileset> + * </ftpdeploy> + * + * @author Jorrit Schippers <jorrit at ncode dot nl> + * @version $Id: 87063ecf88b18eae74c2bca3918a1b4ac9f52807 $ + * @since 2.3.1 + * @package phing.tasks.ext + */ +class FtpDeployTask extends Task +{ + private $host = null; + private $port = 21; + private $username = null; + private $password = null; + private $dir = null; + private $filesets; + private $completeDirMap; + private $mode = FTP_BINARY; + private $clearFirst = false; + private $passive = false; + + protected $logLevel = Project::MSG_VERBOSE; + + public function __construct() { + $this->filesets = array(); + $this->completeDirMap = array(); + } + + public function setHost($host) { + $this->host = $host; + } + + public function setPort($port) { + $this->port = (int) $port; + } + + public function setUsername($username) { + $this->username = $username; + } + + public function setPassword($password) { + $this->password = $password; + } + + public function setDir($dir) { + $this->dir = $dir; + } + + public function setMode($mode) { + switch(strtolower($mode)) { + case 'ascii': + $this->mode = FTP_ASCII; + break; + case 'binary': + case 'bin': + $this->mode = FTP_BINARY; + break; + } + } + + public function setPassive($passive) + { + $this->passive = (bool) $passive; + } + + public function setClearFirst($clearFirst) { + $this->clearFirst = (bool) $clearFirst; + } + + public function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Set level of log messages generated (default = info) + * @param string $level + */ + public function setLevel($level) + { + switch ($level) + { + case "error": $this->logLevel = Project::MSG_ERR; break; + case "warning": $this->logLevel = Project::MSG_WARN; break; + case "info": $this->logLevel = Project::MSG_INFO; break; + case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; + case "debug": $this->logLevel = Project::MSG_DEBUG; break; + } + } + + /** + * The init method: check if Net_FTP is available + */ + public function init() { + require_once 'PEAR.php'; + + $paths = explode(PATH_SEPARATOR, get_include_path()); + foreach($paths as $path) { + if(file_exists($path.DIRECTORY_SEPARATOR.'Net'.DIRECTORY_SEPARATOR.'FTP.php')) { + return true; + } + } + throw new BuildException('The FTP Deploy task requires the Net_FTP PEAR package.'); + } + + /** + * The main entry point method. + */ + public function main() { + $project = $this->getProject(); + + require_once 'Net/FTP.php'; + $ftp = new Net_FTP($this->host, $this->port); + $ret = $ftp->connect(); + if(@PEAR::isError($ret)) { + throw new BuildException('Could not connect to FTP server '.$this->host.' on port '.$this->port.': '.$ret->getMessage()); + } else { + $this->log('Connected to FTP server ' . $this->host . ' on port ' . $this->port, $this->logLevel); + } + + $ret = $ftp->login($this->username, $this->password); + if(@PEAR::isError($ret)) { + throw new BuildException('Could not login to FTP server '.$this->host.' on port '.$this->port.' with username '.$this->username.': '.$ret->getMessage()); + } else { + $this->log('Logged in to FTP server with username ' . $this->username, $this->logLevel); + } + + if ($this->passive) { + $this->log('Setting passive mode', $this->logLevel); + $ret = $ftp->setPassive(); + if(@PEAR::isError($ret)) { + $ftp->disconnect(); + throw new BuildException('Could not set PASSIVE mode: '.$ret->getMessage()); + } + } + + // append '/' to the end if necessary + $dir = substr($this->dir, -1) == '/' ? $this->dir : $this->dir.'/'; + + if($this->clearFirst) { + // TODO change to a loop through all files and directories within current directory + $this->log('Clearing directory '.$dir, $this->logLevel); + $ftp->rm($dir, true); + } + + // Create directory just in case + $ret = $ftp->mkdir($dir, true); + if(@PEAR::isError($ret)) { + $ftp->disconnect(); + throw new BuildException('Could not create directory '.$dir.': '.$ret->getMessage()); + } + + $ret = $ftp->cd($dir); + if(@PEAR::isError($ret)) { + $ftp->disconnect(); + throw new BuildException('Could not change to directory '.$dir.': '.$ret->getMessage()); + } else { + $this->log('Changed directory ' . $dir, $this->logLevel); + } + + $fs = FileSystem::getFileSystem(); + $convert = $fs->getSeparator() == '\\'; + + foreach($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $fromDir = $fs->getDir($project); + $srcFiles = $ds->getIncludedFiles(); + $srcDirs = $ds->getIncludedDirectories(); + foreach($srcDirs as $dirname) { + if($convert) + $dirname = str_replace('\\', '/', $dirname); + $this->log('Will create directory '.$dirname, $this->logLevel); + $ret = $ftp->mkdir($dirname, true); + if(@PEAR::isError($ret)) { + $ftp->disconnect(); + throw new BuildException('Could not create directory '.$dirname.': '.$ret->getMessage()); + } + } + foreach($srcFiles as $filename) { + $file = new PhingFile($fromDir->getAbsolutePath(), $filename); + if($convert) + $filename = str_replace('\\', '/', $filename); + $this->log('Will copy '.$file->getCanonicalPath().' to '.$filename, $this->logLevel); + $ret = $ftp->put($file->getCanonicalPath(), $filename, true, $this->mode); + if(@PEAR::isError($ret)) { + $ftp->disconnect(); + throw new BuildException('Could not deploy file '.$filename.': '.$ret->getMessage()); + } + } + } + + $ftp->disconnect(); + $this->log('Disconnected from FTP server', $this->logLevel); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/HttpGetTask.php b/buildscripts/phing/classes/phing/tasks/ext/HttpGetTask.php new file mode 100755 index 00000000..114b80a1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/HttpGetTask.php @@ -0,0 +1,170 @@ +<?php +/* + * $Id: f3fa317b72e2f70f1e483fa49dbf089094e2a476 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * A HTTP request task. + * Making an HTTP request and try to match the response against an provided + * regular expression. + * + * @package phing.tasks.ext + * @author Ole Markus With <o.with@sportradar.com> + * @version $Id: f3fa317b72e2f70f1e483fa49dbf089094e2a476 $ + */ +class HttpGetTask extends Task +{ + /** + * Holds the request URL + * + * @var string + */ + protected $url = null; + + /** + * Holds the filename to store the output in + * + * @var string + */ + protected $filename = null; + + /** + * Holds the save location + * + * @var string + */ + protected $dir = null; + + /** + * Holds the proxy + * + * @var string + */ + protected $_proxy = null; + + /** + * Load the necessary environment for running this task. + * + * @throws BuildException + */ + public function init() + { + @include_once 'HTTP/Request2.php'; + + if (! class_exists('HTTP_Request2')) { + throw new BuildException( + 'HttpRequestTask depends on HTTP_Request2 being installed ' + . 'and on include_path.', + $this->getLocation() + ); + } + } + + + /** + * Make the GET request + * + * @throws BuildException + */ + public function main() + { + if (!isset($this->url)) { + throw new BuildException("Missing attribute 'url'"); + } + + if (!isset($this->dir)) { + throw new BuildException("Missing attribute 'dir'"); + } + + $config = array(); + if (isset($this->_proxy) && $url = parse_url($this->_proxy)) { + $config['proxy_user'] = $url['user']; + $config['proxy_password'] = $url['pass']; + $config['proxy_host'] = $url['host']; + $config['proxy_port'] = $url['port']; + } + + $this->log("Fetching " . $this->url); + + $request = new HTTP_Request2($this->url, '', $config); + $response = $request->send(); + if ($response->getStatus() != 200) { + throw new BuildException("Request unsuccessful. Response from server: " . $response->getStatus() . " " . $response->getReasonPhrase()); + } + + $content = $response->getBody(); + $disposition = $response->getHeader('content-disposition'); + + if ($this->filename) { + $filename = $this->filename; + } elseif ($disposition && 0 == strpos($disposition, 'attachment') + && preg_match('/filename="([^"]+)"/', $disposition, $m)) { + $filename = basename($m[1]); + } else { + $filename = basename(parse_url($this->url, PHP_URL_PATH)); + } + + if (!is_writable($this->dir)) { + throw new BuildException("Cannot write to directory: " . $this->dir); + } + + $filename = $this->dir . "/" . $filename; + file_put_contents($filename, $content); + + $this->log("Contents from " . $this->url . " saved to $filename"); + } + + /** + * Sets the request URL + * + * @param string $url + */ + public function setUrl($url) { + $this->url = $url; + } + + /** + * Sets the filename to store the output in + * + * @param string $filename + */ + public function setFilename($filename) { + $this->filename = $filename; + } + + /** + * Sets the save location + * + * @param string $dir + */ + public function setDir($dir) { + $this->dir = $dir; + } + + /** + * Sets the proxy + * + * @param string $proxy + */ + public function setProxy($proxy) { + $this->_proxy = $proxy; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/HttpRequestTask.php b/buildscripts/phing/classes/phing/tasks/ext/HttpRequestTask.php new file mode 100644 index 00000000..e6f15075 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/HttpRequestTask.php @@ -0,0 +1,286 @@ +<?php +/* + * $Id: 495c02bc3a90d24694d8a4bf2d43ac077e0f9ec6 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * A HTTP request task. + * Making an HTTP request and try to match the response against an provided + * regular expression. + * + * @package phing.tasks.ext + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 495c02bc3a90d24694d8a4bf2d43ac077e0f9ec6 $ + * @since 2.4.1 + */ +class HttpRequestTask extends Task +{ + /** + * Holds the request URL + * + * @var string + */ + protected $_url = null; + + /** + * Holds the regular expression that should match the response + * + * @var string + */ + protected $_responseRegex = ''; + + /** + * Whether to enable detailed logging + * + * @var boolean + */ + protected $_verbose = false; + + /** + * Holds additional header data + * + * @var array<Parameter> + */ + protected $_headers = array(); + + /** + * Holds additional config data for HTTP_Request2 + * + * @var array<Parameter> + */ + protected $_configData = array(); + + /** + * Holds the authentication user name + * + * @var string + */ + protected $_authUser = null; + + /** + * Holds the authentication password + * + * @var string + */ + protected $_authPassword = ''; + + /** + * Holds the authentication scheme + * + * @var string + */ + protected $_authScheme; + + /** + * Holds the events that will be logged + * + * @var array<string> + */ + protected $_observerEvents = array( + 'connect', + 'sentHeaders', + 'sentBodyPart', + 'receivedHeaders', + 'receivedBody', + 'disconnect', + ); + + /** + * Sets the request URL + * + * @param string $url + */ + public function setUrl($url) + { + $this->_url = $url; + } + + /** + * Sets the response regex + * + * @param string $regex + */ + public function setResponseRegex($regex) + { + $this->_responseRegex = $regex; + } + + /** + * Sets the authentication user name + * + * @param string $user + */ + public function setAuthUser($user) + { + $this->_authUser = $user; + } + + /** + * Sets the authentication password + * + * @param string $password + */ + public function setAuthPassword($password) + { + $this->_authPassword = $password; + } + + /** + * Sets the authentication scheme + * + * @param string $scheme + */ + public function setAuthScheme($scheme) + { + $this->_authScheme = $scheme; + } + + /** + * Sets whether to enable detailed logging + * + * @param boolean $verbose + */ + public function setVerbose($verbose) + { + $this->_verbose = StringHelper::booleanValue($verbose); + } + + /** + * Sets a list of observer events that will be logged + * if verbose output is enabled. + * + * @param string $observerEvents List of observer events + * + * @return void + */ + public function setObserverEvents($observerEvents) + { + $this->_observerEvents = array(); + + $token = ' ,;'; + $ext = strtok($observerEvents, $token); + + while ($ext !== false) { + $this->_observerEvents[] = $ext; + $ext = strtok($token); + } + } + + /** + * Creates an additional header for this task + * + * @return Parameter The created header + */ + public function createHeader() + { + $num = array_push($this->_headers, new Parameter()); + return $this->_headers[$num-1]; + } + + /** + * Creates a config parameter for this task + * + * @return Parameter The created parameter + */ + public function createConfig() + { + $num = array_push($this->_configData, new Parameter()); + return $this->_configData[$num-1]; + } + + /** + * Load the necessary environment for running this task. + * + * @throws BuildException + */ + public function init() + { + @include_once 'HTTP/Request2.php'; + + if (! class_exists('HTTP_Request2')) { + throw new BuildException( + 'HttpRequestTask depends on HTTP_Request2 being installed ' + . 'and on include_path.', + $this->getLocation() + ); + } + + $this->_authScheme = HTTP_Request2::AUTH_BASIC; + + // Other dependencies that should only be loaded + // when class is actually used + require_once 'HTTP/Request2/Observer/Log.php'; + } + + /** + * Make the http request + */ + public function main() + { + if (!isset($this->_url)) { + throw new BuildException("Missing attribute 'url' set"); + } + + $request = new HTTP_Request2($this->_url); + + // set the authentication data + if (!empty($this->_authUser)) { + $request->setAuth( + $this->_authUser, + $this->_authPassword, + $this->_authScheme + ); + } + + foreach ($this->_configData as $config) { + $request->setConfig($config->getName(), $config->getValue()); + } + + foreach ($this->_headers as $header) { + $request->setHeader($header->getName(), $header->getValue()); + } + + if ($this->_verbose) { + $observer = new HTTP_Request2_Observer_Log(); + + // set the events we want to log + $observer->events = $this->_observerEvents; + + $request->attach($observer); + } + + $response = $request->send(); + + if ($this->_responseRegex !== '') { + $matches = array(); + preg_match($this->_responseRegex, $response->getBody(), $matches); + + if (count($matches) === 0) { + throw new BuildException( + 'The received response body did not match the ' + . 'given regular expression' + ); + } else { + $this->log('The response body matched the provided regex.'); + } + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/JslLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/JslLintTask.php new file mode 100644 index 00000000..77a4aad5 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/JslLintTask.php @@ -0,0 +1,284 @@ +<?php +/* + * $Id: 551de2e94aa21f44e19dd0806051f1eabf8b20f9 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/util/DataStore.php'; + +/** + * A Javascript lint task. Checks syntax of Javascript files. + * Javascript lint (http://www.javascriptlint.com) must be in the system path. + * This class is based on Knut Urdalen's PhpLintTask. + * + * @author Stefan Priebsch <stefan.priebsch@e-novative.de> + * @version $Id: 551de2e94aa21f44e19dd0806051f1eabf8b20f9 $ + * @package phing.tasks.ext + */ +class JslLintTask extends Task +{ + protected $file; // the source file (from xml attribute) + protected $filesets = array(); // all fileset objects assigned to this task + + protected $showWarnings = true; + protected $haltOnFailure = false; + protected $hasErrors = false; + private $badFiles = array(); + + private $cache = null; + private $conf = null; + + private $executable = "jsl"; + + /** + * @var PhingFile + */ + protected $tofile = null; + + /** + * Sets the flag if warnings should be shown + * @param boolean $show + */ + public function setShowWarnings($show) { + $this->showWarnings = StringHelper::booleanValue($show); + } + + /** + * The haltonfailure property + * @param boolean $aValue + */ + public function setHaltOnFailure($aValue) { + $this->haltOnFailure = $aValue; + } + + /** + * File to be performed syntax check on + * @param PhingFile $file + */ + public function setFile(PhingFile $file) { + $this->file = $file; + } + + /** + * Whether to store last-modified times in cache + * + * @param PhingFile $file + */ + public function setCacheFile(PhingFile $file) + { + $this->cache = new DataStore($file); + } + + /** + * jsl config file + * + * @param PhingFile $file + */ + public function setConfFile(PhingFile $file) + { + $this->conf = $file; + } + + public function setExecutable($path){ + $this->executable = $path; + + if (!@file_exists($path)) { + throw new BuildException("JavaScript Lint executable '{$path}' not found"); + } + } + + public function getExecutable(){ + return $this->executable; + } + + /** + * Nested creator, creates a FileSet for this task + * + * @return FileSet The created fileset object + */ + public function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * File to save error messages to + * + * @param PhingFile $file + */ + public function setToFile(PhingFile $tofile) + { + $this->tofile = $tofile; + } + + /** + * Execute lint check against PhingFile or a FileSet + */ + public function main() { + if(!isset($this->file) and count($this->filesets) == 0) { + throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + } + + if (empty($this->executable)) { + throw new BuildException("Missing the 'executable' attribute"); + } + + if($this->file instanceof PhingFile) { + $this->lint($this->file->getPath()); + } else { // process filesets + $project = $this->getProject(); + foreach($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $files = $ds->getIncludedFiles(); + $dir = $fs->getDir($this->project)->getPath(); + foreach($files as $file) { + $this->lint($dir.DIRECTORY_SEPARATOR.$file); + } + } + } + + // write list of 'bad files' to file (if specified) + if ($this->tofile) { + $writer = new FileWriter($this->tofile); + + foreach ($this->badFiles as $file => $messages) { + foreach ($messages as $msg) { + $writer->write($file . "=" . $msg . PHP_EOL); + } + } + + $writer->close(); + } + + if ($this->haltOnFailure && $this->hasErrors) throw new BuildException('Syntax error(s) in JS files:' .implode(', ', array_keys($this->badFiles))); + } + + /** + * Performs the actual syntax check + * + * @param string $file + * @return void + */ + protected function lint($file) + { + $command = $this->executable . ' -output-format ' . escapeshellarg('file:__FILE__;line:__LINE__;message:__ERROR__') . ' '; + + if (isset($this->conf)) { + $command .= '-conf ' . escapeshellarg($this->conf->getPath()) . ' '; + } + + $command .= '-process '; + + if(file_exists($file)) + { + if(is_readable($file)) + { + if ($this->cache) + { + $lastmtime = $this->cache->get($file); + + if ($lastmtime >= filemtime($file)) + { + $this->log("Not linting '" . $file . "' due to cache", Project::MSG_DEBUG); + return false; + } + } + + $messages = array(); + exec($command.'"'.$file.'"', $messages, $return); + + if ($return > 100) { + throw new BuildException("Could not execute Javascript Lint executable '{$this->executable}'"); + } + + $summary = $messages[sizeof($messages) - 1]; + + preg_match('/(\d+)\serror/', $summary, $matches); + $errorCount = (count($matches) > 1 ? $matches[1] : 0); + + preg_match('/(\d+)\swarning/', $summary, $matches); + $warningCount = (count($matches) > 1 ? $matches[1] : 0); + + $errors = array(); + $warnings = array(); + if ($errorCount > 0 || $warningCount > 0) { + $last = false; + foreach ($messages as $message) { + $matches = array(); + if (preg_match('/^(\.*)\^$/', $message)) { + $column = strlen($message); + if ($last == 'error') { + $errors[count($errors) - 1]['column'] = $column; + } else if ($last == 'warning') { + $warnings[count($warnings) - 1]['column'] = $column; + } + $last = false; + } + if (!preg_match('/^file:(.+);line:(\d+);message:(.+)$/', $message, $matches)) continue; + $msg = $matches[3]; + $data = array('filename' => $matches[1], 'line' => $matches[2], 'message' => $msg); + if (preg_match('/^.*error:.+$/i', $msg)) { + $errors[] = $data; + $last = 'error'; + } else if (preg_match('/^.*warning:.+$/i', $msg)) { + $warnings[] = $data; + $last = 'warning'; + } + } + } + + if($this->showWarnings && $warningCount > 0) + { + $this->log($file . ': ' . $warningCount . ' warnings detected', Project::MSG_WARN); + foreach ($warnings as $warning) { + $this->log('- line ' . $warning['line'] . (isset($warning['column']) ? ' column ' . $warning['column'] : '') . ': ' . $warning['message'], Project::MSG_WARN); + } + } + + if($errorCount > 0) + { + $this->log($file . ': ' . $errorCount . ' errors detected', Project::MSG_ERR); + if (!isset($this->badFiles[$file])) { + $this->badFiles[$file] = array(); + } + + foreach ($errors as $error) { + $message = 'line ' . $error['line'] . (isset($error['column']) ? ' column ' . $error['column'] : '') . ': ' . $error['message']; + $this->log('- ' . $message, Project::MSG_ERR); + array_push($this->badFiles[$file], $message); + } + $this->hasErrors = true; + } else if (!$this->showWarnings || $warningCount == 0) { + $this->log($file . ': No syntax errors detected', Project::MSG_VERBOSE); + + if ($this->cache) + { + $this->cache->put($file, filemtime($file)); + } + } + } else { + throw new BuildException('Permission denied: '.$file); + } + } else { + throw new BuildException('File not found: '.$file); + } + } +} + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/MailTask.php b/buildscripts/phing/classes/phing/tasks/ext/MailTask.php index 16d29fb8..0fff88cc 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/MailTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/MailTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: MailTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 901fb0efa435ae78d249a50ed0e0f6e5d31e0d32 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,56 +22,138 @@ include_once 'phing/Task.php'; /** - * Send a message by mail() + * Send an e-mail message * - * <mail to="user@example.org" subject="build complete">The build process is a success...</mail> + * <mail tolist="user@example.org" subject="build complete">The build process is a success...</mail> * - * @author Francois Harvey at SecuriWeb (http://www.securiweb.net) - * @version $Revision: 1.1 $ - * @package phing.tasks.ext + * @author Michiel Rook <mrook@php.net> + * @author Francois Harvey at SecuriWeb (http://www.securiweb.net) + * @version $Id: 901fb0efa435ae78d249a50ed0e0f6e5d31e0d32 $ + * @package phing.tasks.ext */ -class MailTask extends Task { - - protected $recipient; - - protected $subject; +class MailTask extends Task +{ + protected $tolist = null; + protected $subject = null; + protected $msg = null; + protected $from = null; + + protected $filesets = array(); - protected $msg; + public function main() + { + if (empty($this->from)) { + throw new BuildException('Missing "from" attribute'); + } + + $this->log('Sending mail to ' . $this->tolist); + + if (!empty($this->filesets)) { + @require_once 'Mail.php'; + @require_once 'Mail/mime.php'; + + if (!class_exists('Mail_mime')) { + throw new BuildException('Need the PEAR Mail_mime package to send attachments'); + } + + $mime = new Mail_mime(); + $hdrs = array( + 'From' => $this->from, + 'Subject' => $this->subject + ); + $mime->setTXTBody($this->msg); + + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($this->project); + $fromDir = $fs->getDir($this->project); + $srcFiles = $ds->getIncludedFiles(); - function main() { - $this->log('Sending mail to ' . $this->recipient ); - mail($this->recipient, $this->subject, $this->msg); + foreach ($srcFiles as $file) { + $mime->addAttachment($fromDir . DIRECTORY_SEPARATOR . $file, 'application/octet-stream'); + } + } + + $body = $mime->get(); + $hdrs = $mime->headers($hdrs); + + $mail = Mail::factory('mail'); + $mail->send($this->tolist, $hdrs, $body); + } else { + mail($this->tolist, $this->subject, $this->msg, "From: {$this->from}\n"); + } } - /** setter for message */ - function setMsg($msg) { + /** + * Setter for message + */ + public function setMsg($msg) + { $this->setMessage($msg); } - /** alias setter */ - function setMessage($msg) { + /** + * Alias setter + */ + public function setMessage($msg) + { $this->msg = (string) $msg; } - /** setter for subject **/ - function setSubject($subject) { - $this->subject = (string) $subject; + /** + * Setter for subject + */ + public function setSubject($subject) + { + $this->subject = (string) $subject; } - /** setter for recipient **/ - function setRecipient($recipient) { - $this->recipient = (string) $recipient; + /** + * Setter for tolist + */ + public function setToList($tolist) + { + $this->tolist = $tolist; + } + + /** + * Alias for (deprecated) recipient + */ + public function setRecipient($recipient) + { + $this->tolist = (string) $recipient; } - /** alias for recipient **/ - function setTo($recipient) { - $this->recipient = (string) $recipient; + /** + * Alias for to + */ + public function setTo($to) + { + $this->tolist = (string) $to; } - /** Supporting the <mail>Message</mail> syntax. */ - function addText($msg) + /** + * Supports the <mail>Message</mail> syntax. + */ + public function addText($msg) { $this->msg = (string) $msg; } + + /** + * Sets email address of sender + */ + public function setFrom($from) + { + $this->from = $from; + } + + /** + * Adds a fileset + */ + public function createFileSet() + { + $fileset = new FileSet(); + $this->filesets[] = $fileset; + return $fileset; + } } - diff --git a/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php b/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php new file mode 100644 index 00000000..b9cfae64 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php @@ -0,0 +1,343 @@ +<?php +/** + * $Id: 7f8f119fe5dd44ca9f374e24d776a1a764260e33 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once "phing/Task.php"; +require_once 'phing/system/io/PhingFile.php'; + +/** + * ManifestTask + * + * Generates a simple Manifest file with optional checksums. + * + * + * Manifest schema: + * ... + * path/to/file CHECKSUM [CHECKSUM2] [CHECKSUM3] + * path/to/secondfile CHECKSUM [CHECKSUM2] [CHECKSUM3] + * ... + * + * Example usage: + * <manifest checksum="crc32" file="${dir_build}/Manifest"> + * <fileset refid="files_build" /> + * </manifest> + * + * <manifest checksum="md5,adler32,sha256" file="${dir_build}/Manifest"> + * <fileset refid="files_build" /> + * </manifest> + * + * + * + * @author David Persson <davidpersson at qeweurope dot org> + * @package phing.tasks.ext + * @version $Id: 7f8f119fe5dd44ca9f374e24d776a1a764260e33 $ + * @since 2.3.1 + */ +class ManifestTask extends Task +{ + var $taskname = 'manifest'; + + /** + * Action + * + * "w" for reading in files from fileSet + * and writing manifest + * + * or + * + * "r" for reading in files from fileSet + * and checking against manifest + * + * @var string "r" or "w" + */ + private $action = 'w'; + + /** + * The target file passed in the buildfile. + */ + private $destFile = null; + + /** + * Holds filesets + * + * @var array An Array of objects + */ + private $filesets = array(); + + /** + * Enable/Disable checksuming or/and select algorithm + * true defaults to md5 + * false disables checksuming + * string "md5,sha256,..." enables generation of multiple checksums + * string "sha256" generates sha256 checksum only + * + * @var mixed + */ + private $checksum = false; + + /** + * A string used in hashing method + * + * @var string + */ + private $salt = ''; + + /** + * Holds some data collected during runtime + * + * @var array + */ + private $meta = array('totalFileCount' => 0,'totalFileSize' => 0); + + + /** + * The setter for the attribute "file" + * This is where the manifest will be written to/read from + * + * @param string Path to readable file + * @return void + */ + public function setFile(PhingFile $file) + { + $this->file = $file; + } + + /** + * The setter for the attribute "checksum" + * + * @param mixed $mixed + * @return void + */ + public function setChecksum($mixed) + { + if(is_string($mixed)) { + $data = array(strtolower($mixed)); + + if(strpos($data[0],',')) { + $data = explode(',',$mixed); + } + + $this->checksum = $data; + + } elseif($mixed === true) { + $this->checksum = array('md5'); + + } + } + + /** + * The setter for the optional attribute "salt" + * + * @param string $string + * @return void + */ + public function setSalt($string) + { + $this->salt = $string; + } + + /** + * Nested creator, creates a FileSet for this task + * + * @access public + * @return object The created fileset object + */ + public function createFileSet() + { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * The init method: Do init steps. + */ + public function init() + { + // nothing to do here + } + + /** + * Delegate the work + */ + public function main() + { + $this->validateAttributes(); + + if($this->action == 'w') { + $this->write(); + + } elseif($this->action == 'r') { + $this->read(); + + } + } + + /** + * Creates Manifest file + * Writes to $this->file + * + * @throws BuildException + */ + private function write() + { + $project = $this->getProject(); + + if(!touch($this->file->getPath())) { + throw new BuildException("Unable to write to ".$this->file->getPath()."."); + } + + $this->log("Writing to " . $this->file->__toString(), Project::MSG_INFO); + + if(is_array($this->checksum)) { + $this->log("Using " . implode(', ',$this->checksum)." for checksuming.", Project::MSG_INFO); + } + + foreach($this->filesets as $fs) { + + $dir = $fs->getDir($this->project)->getPath(); + + $ds = $fs->getDirectoryScanner($project); + $fromDir = $fs->getDir($project); + $srcFiles = $ds->getIncludedFiles(); + $srcDirs = $ds->getIncludedDirectories(); + + foreach($ds->getIncludedFiles() as $file_path) { + $line = $file_path; + if($this->checksum) { + foreach($this->checksum as $algo) { + if(!$hash = $this->hashFile($dir.'/'.$file_path,$algo)) { + throw new BuildException("Hashing $dir/$file_path with $algo failed!"); + } + + $line .= "\t".$hash; + } + } + $line .= "\n"; + $manifest[] = $line; + $this->log("Adding file ".$file_path,Project::MSG_VERBOSE); + $this->meta['totalFileCount'] ++; + $this->meta['totalFileSize'] += filesize($dir.'/'.$file_path); + } + + } + + file_put_contents($this->file,$manifest); + + $this->log("Done. Total files: ".$this->meta['totalFileCount'].". Total file size: ".$this->meta['totalFileSize']." bytes.", Project::MSG_INFO); + } + + /** + * @todo implement + */ + private function read() + { + throw new BuildException("Checking against manifest not yet supported."); + } + + /** + * Wrapper method for hash generation + * Automatically selects extension + * Falls back to built-in functions + * + * @link http://www.php.net/mhash + * @link http://www.php.net/hash + * + * @param string $msg The string that should be hashed + * @param string $algo Algorithm + * @return mixed String on success, false if $algo is not available + */ + private function hash($msg,$algo) + { + if(extension_loaded('hash')) { + $algo = strtolower($algo); + + if(in_array($algo,hash_algos())) { + return hash($algo,$this->salt.$msg); + } + + } + + if(extension_loaded('mhash')) { + $algo = strtoupper($algo); + + if(defined('MHASH_'.$algo)) { + return mhash('MHASH_'.$algo,$this->salt.$msg); + + } + } + + switch(strtolower($algo)) { + case 'md5': + return md5($this->salt.$msg); + case 'crc32': + return abs(crc32($this->salt.$msg)); + } + + return false; + } + + /** + * Hash a files contents + * plus it's size an modification time + * + * @param string $file + * @param string $algo + * @return mixed String on success, false if $algo is not available + */ + private function hashFile($file,$algo) + { + if(!file_exists($file)) { + return false; + } + + $msg = file_get_contents($file).filesize($file).filemtime($file); + + return $this->hash($msg,$algo); + } + + /** + * Validates attributes coming in from XML + * + * @access private + * @return void + * @throws BuildException + */ + protected function validateAttributes() + { + if($this->action != 'r' && $this->action != 'w') { + throw new BuildException("'action' attribute has non valid value. Use 'r' or 'w'"); + } + + if(empty($this->salt)) { + $this->log("No salt provided. Specify one with the 'salt' attribute.", Project::MSG_WARN); + } + + if (is_null($this->file) && count($this->filesets) === 0) { + throw new BuildException("Specify at least sources and destination - a file or a fileset."); + } + + if (!is_null($this->file) && $this->file->exists() && $this->file->isDirectory()) { + throw new BuildException("Destination file cannot be a directory."); + } + + } +} + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php b/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php index b8664aac..2db5ad69 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: PackageAsPathTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 976dafaf4cafd9ff8f47907a09943ae3963aea79 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ require_once 'phing/Task.php'; * Convert dot-notation packages to relative paths. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.5 $ + * @version $Id: 976dafaf4cafd9ff8f47907a09943ae3963aea79 $ * @package phing.tasks.ext */ class PackageAsPathTask extends Task { diff --git a/buildscripts/phing/classes/phing/tasks/ext/ParallelTask.php b/buildscripts/phing/classes/phing/tasks/ext/ParallelTask.php new file mode 100755 index 00000000..b8da5cb4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ParallelTask.php @@ -0,0 +1,83 @@ +<?php + +/** + * $Id: 860b2b6cdbd797754660fe2c1554e22ab2db4967 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + * + * @package phing.tasks.ext + */ + +/** + * Uses the DocBlox_Parallel library to run nested Phing tasks concurrently. + * + * WARNING: this task is highly experimental! + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 860b2b6cdbd797754660fe2c1554e22ab2db4967 $ + * @package phing.tasks.ext + * @see https://github.com/phpdocumentor/Parallel + * @since 2.4.10 + */ +class ParallelTask extends SequentialTask +{ + /** + * Maximum number of threads / processes + * @var int + */ + private $threadCount = 2; + + /** + * Sets the maximum number of threads / processes to use + * @param int $threadCount + */ + public function setThreadCount($threadCount) + { + $this->threadCount = $threadCount; + } + + public function init() + { + } + + public function main() + { + @include_once 'phing/contrib/DocBlox/Parallel/Manager.php'; + @include_once 'phing/contrib/DocBlox/Parallel/Worker.php'; + @include_once 'phing/contrib/DocBlox/Parallel/WorkerPipe.php'; + if (!class_exists('DocBlox_Parallel_Worker')) { + throw new BuildException( + 'ParallelTask depends on DocBlox being installed and on include_path.', + $this->getLocation() + ); + } + + $mgr = new DocBlox_Parallel_Manager(); + $mgr->setProcessLimit($this->threadCount); + + foreach ($this->nestedTasks as $task) { + $worker = new DocBlox_Parallel_Worker( + array($task, 'perform'), + array($task) + ); + + $mgr->addWorker($worker); + } + + $mgr->execute(); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/PatchTask.php b/buildscripts/phing/classes/phing/tasks/ext/PatchTask.php new file mode 100755 index 00000000..162f5fe5 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/PatchTask.php @@ -0,0 +1,301 @@ +<?php +/** + * Patches a file by applying a 'diff' file to it + * + * Requires "patch" to be on the execution path. + * + * Based on Apache Ant PatchTask: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +require_once 'phing/Task.php'; + +/** + * Patches a file by applying a 'diff' file to it + * + * Requires "patch" to be on the execution path. + * + * @package phing.tasks.ext + */ +class PatchTask extends Task +{ + /** + * Base command to be executed (must end with a space character!) + * @var string + */ + const CMD = 'patch --batch --silent '; + + /** + * File to be patched + * @var string + */ + private $originalFile; + + /** + * Patch file + * + * @var string + */ + private $patchFile; + + /** + * Value for a "-p" option + * @var int + */ + private $strip; + + /** + * Command line arguments for patch binary + * @var array + */ + private $cmdArgs = array(); + + /** + * Halt on error return value from patch invocation. + * @var bool + */ + private $haltOnFailure = false; + + /** + * The file containing the diff output + * + * Required. + * + * @param string $file File containing the diff output + * @return void + * @throws BuildException if $file not exists + */ + public function setPatchFile($file) + { + if (!is_file($file)) + { + throw new BuildException(sprintf('Patchfile %s doesn\'t exist', $file)); + } + $this->patchFile = $file; + } + + /** + * The file to patch + * + * Optional if it can be inferred from the diff file. + * + * @param string $file File to patch + * @return void + */ + public function setOriginalFile($file) + { + $this->originalFile = $file; + } + + /** + * The name of a file to send the output to, instead of patching + * the file(s) in place + * + * Optional. + * + * @param string $file File to send the output to + * @return void + */ + public function setDestFile($file) + { + if ($file !== null) + { + $this->cmdArgs []= "--output=$file"; + } + } + + /** + * Flag to create backups + * + * Optional, default - false + * + * @param bool $backups If true create backups + * @return void + */ + public function setBackups($backups) + { + if ($backups) + { + $this->cmdArgs []= '--backup'; + } + } + + /** + * Flag to ignore whitespace differences; + * + * Default - false + * + * @param bool $ignore If true ignore whitespace differences + * @return void + */ + public function setIgnoreWhiteSpace($ignore) + { + if ($ignore) + { + $this->cmdArgs []= '--ignore-whitespace'; + } + } + + /** + * Strip the smallest prefix containing <i>num</i> leading slashes + * from filenames. + * + * patch's <i>--strip</i> option. + * + * @param int $num number of lines to strip + * @return void + * @throws BuildException if num is < 0, or other errors + */ + public function setStrip($num) + { + if ($num < 0) + { + throw new BuildException('strip has to be >= 0'); + } + + $this->strip = $num; + } + + /** + * Work silently unless an error occurs + * + * Optional, default - false + * @param bool $flag If true suppress set the -s option on the patch command + * @return void + */ + public function setQuiet($flag) + { + if ($flag) + { + $this->cmdArgs []= '--silent'; + } + } + + /** + * Assume patch was created with old and new files swapped + * + * Optional, default - false + * + * @param bool $flag If true set the -R option on the patch command + * @return void + */ + public function setReverse($flag) + { + if ($flag) + { + $this->cmdArgs []= '--reverse'; + } + } + + /** + * The directory to run the patch command in + * + * Defaults to the project's base directory. + * + * @param string $directory Directory to run the patch command in + * @return void + */ + public function setDir($directory) + { + $this->cmdArgs []= "--directory=$directory"; + } + + /** + * Ignore patches that seem to be reversed or already applied + * + * @param bool $flag If true set the -N (--forward) option + * @return void + */ + public function setForward($flag) + { + if ($flag) + { + $this->cmdArgs []= "--forward"; + } + } + + /** + * Set the maximum fuzz factor + * + * Defaults to 0 + * + * @param string $value Value of a fuzz factor + * @return void + */ + public function setFuzz($value) + { + $this->cmdArgs []= "--fuzz=$value"; + } + + /** + * If true, stop the build process if the patch command + * exits with an error status. + * + * The default is "false" + * + * @param bool $value "true" if it should halt, otherwise "false" + * @return void + */ + public function setHaltOnFailure($value) + { + $this->haltOnFailure = $value; + } + + /** + * Main task method + * + * @return void + * @throws BuildException when it all goes a bit pear shaped + */ + public function main() + { + if ($this->patchFile == null) + { + throw new BuildException('patchfile argument is required'); + } + + // Define patch file + $this->cmdArgs []= '-i ' . $this->patchFile; + // Define strip factor + if ($this->strip != null) + { + $this->cmdArgs []= '--strip=' . $this->strip; + } + // Define original file if specified + if ($this->originalFile != null) + { + $this->cmdArgs []= $this->originalFile; + } + + $cmd = self::CMD . implode(' ', $this->cmdArgs); + + $this->log('Applying patch: ' . $this->patchFile); + + exec($cmd, $output, $exitCode); + + foreach ($output as $line) + { + $this->log($line, Project::MSG_VERBOSE); + } + + if ($exitCode != 0 && $this->haltOnFailure) + { + throw new BuildException( "Task exited with code $exitCode" ); + } + + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/PearPackage2Task.php b/buildscripts/phing/classes/phing/tasks/ext/PearPackage2Task.php new file mode 100644 index 00000000..f42231f7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/PearPackage2Task.php @@ -0,0 +1,279 @@ +<?php +/* + * $Id: 1b20dbb6595bd4c41d1e5f1430900e3bf95de411 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/PearPackageTask.php'; + +/** + * A task to create a PEAR package.xml version 2.0 file. + * + * This class uses the PEAR_PackageFileManager2 class to perform the work. + * + * This class is designed to be very flexible -- i.e. account for changes to the package.xml w/o + * requiring changes to this class. We've accomplished this by having generic <option> and <mapping> + * nested elements. All options are set using PEAR_PackageFileManager2::setOptions(). + * + * The <option> tag is used to set a simple option value. + * <code> + * <option name="option_name" value="option_value"/> + * or <option name="option_name">option_value</option> + * </code> + * + * The <mapping> tag represents a complex data type. You can use nested <element> (and nested <element> with + * <element> tags) to represent the full complexity of the structure. Bear in mind that what you are creating + * will be mapped to an associative array that will be passed in via PEAR_PackageFileManager2::setOptions(). + * <code> + * <mapping name="option_name"> + * <element key="key_name" value="key_val"/> + * <element key="key_name" value="key_val"/> + * </mapping> + * </code> + * + * Here's an over-simple example of how this could be used: + * <code> + * <pearpkg2 name="phing" dir="${build.src.dir}"> + * <fileset dir="src"> + * <include name="**"/> + * </fileset> + * <option name="outputdirectory" value="./build"/> + * <option name="packagefile" value="package2.xml"/> + * <option name="packagedirectory" value="./${build.dist.dir}"/> + * <option name="baseinstalldir" value="${pkg.prefix}"/> + * <option name="channel" value="my.pear-channel.com"/> + * <option name="summary" value="${pkg.summary}"/> + * <option name="description" value="${pkg.description}"/> + * <option name="apiversion" value="${pkg.version}"/> + * <option name="apistability" value="beta"/> + * <option name="releaseversion" value="${pkg.version}"/> + * <option name="releasestability" value="beta"/> + * <option name="license" value="none"/> + * <option name="phpdep" value="5.0.0"/> + * <option name="pearinstallerdep" value="1.4.6"/> + * <option name="packagetype" value="php"/> + * <option name="notes" value="${pkg.relnotes}"/> + * <mapping name="maintainers"> + * <element> + * <element key="handle" value="hlellelid"/> + * <element key="name" value="Hans"/> + * <element key="email" value="hans@xmpl.org"/> + * <element key="role" value="lead"/> + * <element key="active" value="yes"/> + * </element> + * </mapping> + * </pearpkg2> + * </code> + * + * Look at the build.xml in the Phing base directory (assuming you have the full distro / CVS version of Phing) to + * see a more complete example of how to call this script. + * + * @author Stuart Binge <stuart.binge@complinet.com> + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext + * @version $Id: 1b20dbb6595bd4c41d1e5f1430900e3bf95de411 $ + */ +class PearPackage2Task extends PearPackageTask { + + public function init() { + include_once 'PEAR/PackageFileManager2.php'; + if (!class_exists('PEAR_PackageFileManager2')) { + throw new BuildException("You must have installed PEAR_PackageFileManager in order to create a PEAR package.xml version 2.0 file."); + } + } + + protected function setVersion2Options() + { + $this->pkg->setPackage($this->package); + $this->pkg->setDate(strftime('%Y-%m-%d')); + $this->pkg->setTime(strftime('%H:%M:%S')); + + $newopts = array(); + foreach ($this->options as $opt) { + switch ($opt->getName()) { + case 'summary': + $this->pkg->setSummary($opt->getValue()); + break; + + case 'description': + $this->pkg->setDescription($opt->getValue()); + break; + + case 'uri': + $this->pkg->setUri($opt->getValue()); + break; + + case 'license': + $this->pkg->setLicense($opt->getValue()); + break; + + case 'channel': + $this->pkg->setChannel($opt->getValue()); + break; + + case 'apiversion': + $this->pkg->setAPIVersion($opt->getValue()); + break; + + case 'releaseversion': + $this->pkg->setReleaseVersion($opt->getValue()); + break; + + case 'releasestability': + $this->pkg->setReleaseStability($opt->getValue()); + break; + + case 'apistability': + $this->pkg->setAPIStability($opt->getValue()); + break; + + case 'notes': + $this->pkg->setNotes($opt->getValue()); + break; + + case 'packagetype': + $this->pkg->setPackageType($opt->getValue()); + break; + + case 'phpdep': + $this->pkg->setPhpDep($opt->getValue()); + break; + + case 'pearinstallerdep': + $this->pkg->setPearinstallerDep($opt->getValue()); + break; + + default: + $newopts[] = $opt; + break; + } + } + $this->options = $newopts; + + $newmaps = array(); + foreach ($this->mappings as $map) { + switch ($map->getName()) { + case 'deps': + $deps = $map->getValue(); + foreach ($deps as $dep) { + $type = isset($dep['optional']) ? 'optional' : 'required'; + $min = isset($dep['min']) ? $dep['min'] : $dep['version']; + $max = isset($dep['max']) ? $dep['max'] : null; + $rec = isset($dep['recommended']) ? $dep['recommended'] : null; + $channel = isset($dep['channel']) ? $dep['channel'] : false; + $uri = isset($dep['uri']) ? $dep['uri'] : false; + + if (!empty($channel)) { + $this->pkg->addPackageDepWithChannel( + $type, $dep['name'], $channel, $min, $max, $rec + ); + } elseif (!empty($uri)) { + $this->pkg->addPackageDepWithUri( + $type, $dep['name'], $uri + ); + } + }; + break; + + case 'extdeps': + $deps = $map->getValue(); + foreach ($deps as $dep) { + $type = isset($dep['optional']) ? 'optional' : 'required'; + $min = isset($dep['min']) ? $dep['min'] : $dep['version']; + $max = isset($dep['max']) ? $dep['max'] : $dep['version']; + $rec = isset($dep['recommended']) ? $dep['recommended'] : $dep['version']; + + $this->pkg->addExtensionDep( + $type, $dep['name'], $min, $max, $rec + ); + }; + break; + + case 'maintainers': + $maintainers = $map->getValue(); + + foreach ($maintainers as $maintainer) { + if (!isset($maintainer['active'])) { + $maintainer['active'] = 'yes'; + } else { + $maintainer['active'] = $maintainer['active'] === false ? 'no' : 'yes'; + } + $this->pkg->addMaintainer( + $maintainer['role'], + $maintainer['handle'], + $maintainer['name'], + $maintainer['email'], + $maintainer['active'] + ); + } + break; + + case 'replacements': + $replacements = $map->getValue(); + + foreach($replacements as $replacement) { + $this->pkg->addReplacement( + $replacement['path'], + $replacement['type'], + $replacement['from'], + $replacement['to'] + ); + } + break; + + case 'role': + foreach ($map->getValue() as $role) { + $this->pkg->addRole($role['extension'], $role['role']); + } + break; + + default: + $newmaps[] = $map; + } + } + $this->mappings = $newmaps; + } + + /** + * Main entry point. + * @return void + */ + public function main() + { + if ($this->dir === null) { + throw new BuildException("You must specify the \"dir\" attribute for PEAR package 2 task."); + } + + if ($this->package === null) { + throw new BuildException("You must specify the \"name\" attribute for PEAR package 2 task."); + } + + $this->pkg = new PEAR_PackageFileManager2(); + + $this->setVersion2Options(); + $this->setOptions(); + + $this->pkg->addRelease(); + $this->pkg->generateContents(); + $e = $this->pkg->writePackageFile(); + if (PEAR::isError($e)) { + throw new BuildException("Unable to write package file.", new Exception($e->getMessage())); + } + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php index 4f8ee3ab..47945998 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: PearPackageTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 2078fd5bab3dd6dcea0345a12fce86a24586c765 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -74,15 +74,15 @@ include_once 'phing/types/FileSet.php'; * * @author Hans Lellelid <hans@xmpl.org> * @package phing.tasks.ext - * @version $Revision: 1.9 $ + * @version $Id: 2078fd5bab3dd6dcea0345a12fce86a24586c765 $ */ class PearPackageTask extends MatchingTask { /** */ - private $package; + protected $package; /** Base directory for reading files. */ - private $dir; + protected $dir; /** Package file */ private $packageFile; @@ -91,15 +91,21 @@ class PearPackageTask extends MatchingTask { private $filesets = array(); /** @var PEAR_PackageFileManager */ - private $pkg; + protected $pkg; private $preparedOptions = array(); /** @var array PearPkgOption[] */ - private $options = array(); + protected $options = array(); /** Nested <mapping> (complex options) types. */ - private $mappings = array(); + protected $mappings = array(); + + /** + * Nested <role> elements + * @var PearPkgRole[] + */ + protected $roles = array(); public function init() { include_once 'PEAR/PackageFileManager.php'; @@ -112,7 +118,7 @@ class PearPackageTask extends MatchingTask { * Sets PEAR package.xml options, based on class properties. * @return void */ - private function setOptions() { + protected function setOptions() { // 1) first prepare/populate options $this->populateOptions(); @@ -147,6 +153,11 @@ class PearPackageTask extends MatchingTask { if (PEAR::isError($e)) { throw new BuildException("Unable to set options.", new Exception($e->getMessage())); } + + // convert roles + foreach ($this->roles as $role) { + $this->pkg->addRole($role->getExtension(), $role->getRole()); + } } /** @@ -180,9 +191,9 @@ class PearPackageTask extends MatchingTask { $this->preparedOptions['packagefile'] = $f->getName(); // must end in trailing slash $this->preparedOptions['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR; - $this->log("Creating package file: " . $f->__toString(), PROJECT_MSG_INFO); + $this->log("Creating package file: " . $f->__toString(), Project::MSG_INFO); } else { - $this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO); + $this->log("Creating [default] package.xml file in base directory.", Project::MSG_INFO); } // converts option objects and mapping objects into @@ -244,11 +255,12 @@ class PearPackageTask extends MatchingTask { /** * Nested creator, creates a FileSet for this task * - * @return FileSet The created fileset object + * @param FileSet $fileset Set of files to add to the package + * + * @return void */ - function createFileSet() { - $num = array_push($this->filesets, new FileSet()); - return $this->filesets[$num-1]; + public function addFileSet(FileSet $fs) { + $this->filesets[] = $fs; } /** @@ -289,7 +301,7 @@ class PearPackageTask extends MatchingTask { /** * Handles nested generic <option> elements. */ - function createOption() { + public function createOption() { $o = new PearPkgOption(); $this->options[] = $o; return $o; @@ -298,17 +310,30 @@ class PearPackageTask extends MatchingTask { /** * Handles nested generic <option> elements. */ - function createMapping() { + public function createMapping() { $o = new PearPkgMapping(); $this->mappings[] = $o; return $o; } + + /** + * Handles nested <role> elements + * @return PearPkgRole + */ + public function createRole() + { + $role = new PearPkgRole(); + $this->roles[] = $role; + return $role; + } } /** * Generic option class is used for non-complex options. + * + * @package phing.tasks.ext */ class PearPkgOption { @@ -326,6 +351,8 @@ class PearPkgOption { /** * Handles complex options <mapping> elements which are hashes (assoc arrays). + * + * @package phing.tasks.ext */ class PearPkgMapping { @@ -369,6 +396,8 @@ class PearPkgMapping { /** * Sub-element of <mapping>. + * + * @package phing.tasks.ext */ class PearPkgMappingElement { @@ -419,3 +448,57 @@ class PearPkgMappingElement { } } + +/** + * Encapsulates file roles + * + * @package phing.tasks.ext + */ +class PearPkgRole +{ + /** + * @var string + */ + private $extension; + + /** + * @var string + */ + private $role; + + /** + * Sets the file extension + * @param string $extension + */ + public function setExtension($extension) + { + $this->extension = $extension; + } + + /** + * Retrieves the file extension + * @return string + */ + public function getExtension() + { + return $this->extension; + } + + /** + * Sets the role + * @param string $role + */ + public function setRole($role) + { + $this->role = $role; + } + + /** + * Retrieves the role + * @return string + */ + public function getRole() + { + return $this->role; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/PhpCodeSnifferTask.php b/buildscripts/phing/classes/phing/tasks/ext/PhpCodeSnifferTask.php new file mode 100644 index 00000000..de40ae36 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/PhpCodeSnifferTask.php @@ -0,0 +1,648 @@ +<?php +/* + * $Id: 8c8f9369e06a3467e34fc8d89f6355df048ece90 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * A PHP code sniffer task. Checking the style of one or more PHP source files. + * + * @author Dirk Thomas <dirk.thomas@4wdmedia.de> + * @version $Id: 8c8f9369e06a3467e34fc8d89f6355df048ece90 $ + * @package phing.tasks.ext + */ +class PhpCodeSnifferTask extends Task { + + protected $file; // the source file (from xml attribute) + protected $filesets = array(); // all fileset objects assigned to this task + + // parameters for php code sniffer + protected $standard = 'Generic'; + protected $sniffs = array(); + protected $showWarnings = true; + protected $showSources = false; + protected $reportWidth = 80; + protected $verbosity = 0; + protected $tabWidth = 0; + protected $allowedFileExtensions = array('php'); + protected $ignorePatterns = false; + protected $noSubdirectories = false; + protected $configData = array(); + protected $encoding = 'iso-8859-1'; + + // parameters to customize output + protected $showSniffs = false; + protected $format = 'default'; + protected $formatters = array(); + + /** + * Holds the type of the doc generator + * + * @var string + */ + protected $docGenerator = ''; + + /** + * Holds the outfile for the documentation + * + * @var PhingFile + */ + protected $docFile = null; + + private $haltonerror = false; + private $haltonwarning = false; + private $skipversioncheck = false; + + /** + * Load the necessary environment for running PHP_CodeSniffer. + * + * @return void + */ + public function init() + { + } + + /** + * File to be performed syntax check on + * @param PhingFile $file + */ + public function setFile(PhingFile $file) { + $this->file = $file; + } + + /** + * Nested creator, creates a FileSet for this task + * + * @return FileSet The created fileset object + */ + public function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Sets the coding standard to test for + * + * @param string $standard The coding standard + * + * @return void + */ + public function setStandard($standard) + { + $this->standard = $standard; + } + + /** + * Sets the sniffs which the standard should be restricted to + * @param string $sniffs + */ + public function setSniffs($sniffs) + { + $token = ' ,;'; + $sniff = strtok($sniffs, $token); + while ($sniff !== false) { + $this->sniffs[] = $sniff; + $sniff = strtok($token); + } + } + + /** + * Sets the type of the doc generator + * + * @param string $generator HTML or Text + * + * @return void + */ + public function setDocGenerator($generator) + { + $this->docGenerator = $generator; + } + + /** + * Sets the outfile for the documentation + * + * @param PhingFile $file The outfile for the doc + * + * @return void + */ + public function setDocFile(PhingFile $file) + { + $this->docFile = $file; + } + + /** + * Sets the flag if warnings should be shown + * @param boolean $show + */ + public function setShowWarnings($show) + { + $this->showWarnings = StringHelper::booleanValue($show); + } + + /** + * Sets the flag if sources should be shown + * + * @param boolean $show Whether to show sources or not + * + * @return void + */ + public function setShowSources($show) + { + $this->showSources = StringHelper::booleanValue($show); + } + + /** + * Sets the width of the report + * + * @param int $width How wide the screen reports should be. + * + * @return void + */ + public function setReportWidth($width) + { + $this->reportWidth = (int) $width; + } + + /** + * Sets the verbosity level + * @param int $level + */ + public function setVerbosity($level) + { + $this->verbosity = (int)$level; + } + + /** + * Sets the tab width to replace tabs with spaces + * @param int $width + */ + public function setTabWidth($width) + { + $this->tabWidth = (int)$width; + } + + /** + * Sets file encoding + * @param string $encoding + */ + public function setEncoding($encoding) + { + $this->encoding = $encoding; + } + + /** + * Sets the allowed file extensions when using directories instead of specific files + * @param array $extensions + */ + public function setAllowedFileExtensions($extensions) + { + $this->allowedFileExtensions = array(); + $token = ' ,;'; + $ext = strtok($extensions, $token); + while ($ext !== false) { + $this->allowedFileExtensions[] = $ext; + $ext = strtok($token); + } + } + + /** + * Sets the ignore patterns to skip files when using directories instead of specific files + * @param array $extensions + */ + public function setIgnorePatterns($patterns) + { + $this->ignorePatterns = array(); + $token = ' ,;'; + $pattern = strtok($patterns, $token); + while ($pattern !== false) { + $this->ignorePatterns[] = $pattern; + $pattern = strtok($token); + } + } + + /** + * Sets the flag if subdirectories should be skipped + * @param boolean $subdirectories + */ + public function setNoSubdirectories($subdirectories) + { + $this->noSubdirectories = StringHelper::booleanValue($subdirectories); + } + + /** + * Creates a config parameter for this task + * + * @return Parameter The created parameter + */ + public function createConfig() { + $num = array_push($this->configData, new Parameter()); + return $this->configData[$num-1]; + } + + /** + * Sets the flag if the used sniffs should be listed + * @param boolean $show + */ + public function setShowSniffs($show) + { + $this->showSniffs = StringHelper::booleanValue($show); + } + + /** + * Sets the output format + * @param string $format + */ + public function setFormat($format) + { + $this->format = $format; + } + + /** + * Create object for nested formatter element. + * @return CodeSniffer_FormatterElement + */ + public function createFormatter () { + $num = array_push($this->formatters, + new PhpCodeSnifferTask_FormatterElement()); + return $this->formatters[$num-1]; + } + + /** + * Sets the haltonerror flag + * @param boolean $value + */ + public function setHaltonerror($value) + { + $this->haltonerror = $value; + } + + /** + * Sets the haltonwarning flag + * @param boolean $value + */ + public function setHaltonwarning($value) + { + $this->haltonwarning = $value; + } + + /** + * Sets the skipversioncheck flag + * @param boolean $value + */ + public function setSkipVersionCheck($value) + { + $this->skipversioncheck = $value; + } + + /** + * Executes PHP code sniffer against PhingFile or a FileSet + */ + public function main() { + if (!class_exists('PHP_CodeSniffer')) { + @include_once 'PHP/CodeSniffer.php'; + + if (!class_exists('PHP_CodeSniffer')) { + throw new BuildException("This task requires the PHP_CodeSniffer package installed and available on the include path", $this->getLocation()); + } + } + + /** + * Determine PHP_CodeSniffer version number + */ + if (!$this->skipversioncheck) { + preg_match('/\d\.\d\.\d/', shell_exec('phpcs --version'), $version); + + if (version_compare($version[0], '1.2.2') < 0) { + throw new BuildException( + 'PhpCodeSnifferTask requires PHP_CodeSniffer version >= 1.2.2', + $this->getLocation() + ); + } + } + + if(!isset($this->file) and count($this->filesets) == 0) { + throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + } + + if (PHP_CodeSniffer::isInstalledStandard($this->standard) === false) { + // They didn't select a valid coding standard, so help them + // out by letting them know which standards are installed. + $installedStandards = PHP_CodeSniffer::getInstalledStandards(); + $numStandards = count($installedStandards); + $errMsg = ''; + + if ($numStandards === 0) { + $errMsg = 'No coding standards are installed.'; + } else { + $lastStandard = array_pop($installedStandards); + + if ($numStandards === 1) { + $errMsg = 'The only coding standard installed is ' . $lastStandard; + } else { + $standardList = implode(', ', $installedStandards); + $standardList .= ' and ' . $lastStandard; + $errMsg = 'The installed coding standards are ' . $standardList; + } + } + + throw new BuildException( + 'ERROR: the "' . $this->standard . '" coding standard is not installed. ' . $errMsg, + $this->getLocation() + ); + } + + if (count($this->formatters) == 0) { + // turn legacy format attribute into formatter + $fmt = new PhpCodeSnifferTask_FormatterElement(); + $fmt->setType($this->format); + $fmt->setUseFile(false); + $this->formatters[] = $fmt; + } + + if (!isset($this->file)) + { + $fileList = array(); + $project = $this->getProject(); + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $files = $ds->getIncludedFiles(); + $dir = $fs->getDir($this->project)->getAbsolutePath(); + foreach ($files as $file) { + $fileList[] = $dir.DIRECTORY_SEPARATOR.$file; + } + } + } + + $cwd = getcwd(); + // Save command line arguments because it confuses PHPCS (version 1.3.0) + $oldArgs = $_SERVER['argv']; + $_SERVER['argv'] = array(); + $_SERVER['argc'] = 0; + $codeSniffer = new PHP_CodeSniffer($this->verbosity, $this->tabWidth, $this->encoding); + $codeSniffer->setAllowedFileExtensions($this->allowedFileExtensions); + if (is_array($this->ignorePatterns)) $codeSniffer->setIgnorePatterns($this->ignorePatterns); + foreach ($this->configData as $configData) { + $codeSniffer->setConfigData($configData->getName(), $configData->getValue(), true); + } + + if ($this->file instanceof PhingFile) { + $codeSniffer->process($this->file->getPath(), $this->standard, $this->sniffs, $this->noSubdirectories); + + } else { + $codeSniffer->process($fileList, $this->standard, $this->sniffs, $this->noSubdirectories); + } + // Restore command line arguments + $_SERVER['argv'] = $oldArgs; + $_SERVER['argc'] = count($oldArgs); + chdir($cwd); + + $report = $this->printErrorReport($codeSniffer); + + // generate the documentation + if ($this->docGenerator !== '' && $this->docFile !== null) { + ob_start(); + + $codeSniffer->generateDocs($this->standard, $this->sniffs, $this->docGenerator); + + $output = ob_get_contents(); + ob_end_clean(); + + // write to file + $outputFile = $this->docFile->getPath(); + $check = file_put_contents($outputFile, $output); + + if (is_bool($check) && !$check) { + throw new BuildException('Error writing doc to ' . $outputFile); + } + } elseif ($this->docGenerator !== '' && $this->docFile === null) { + $codeSniffer->generateDocs($this->standard, $this->sniffs, $this->docGenerator); + } + + if ($this->haltonerror && $report['totals']['errors'] > 0) + { + throw new BuildException('phpcodesniffer detected ' . $report['totals']['errors']. ' error' . ($report['totals']['errors'] > 1 ? 's' : '')); + } + + if ($this->haltonwarning && $report['totals']['warnings'] > 0) + { + throw new BuildException('phpcodesniffer detected ' . $report['totals']['warnings'] . ' warning' . ($report['totals']['warnings'] > 1 ? 's' : '')); + } + } + + /** + * Prints the error report. + * + * @param PHP_CodeSniffer $phpcs The PHP_CodeSniffer object containing + * the errors. + * + * @return int The number of error and warning messages shown. + */ + protected function printErrorReport($phpcs) + { + if ($this->showSniffs) { + $sniffs = $phpcs->getSniffs(); + $sniffStr = ''; + foreach ($sniffs as $sniff) { + $sniffStr .= '- ' . $sniff.PHP_EOL; + } + $this->log('The list of used sniffs (#' . count($sniffs) . '): ' . PHP_EOL . $sniffStr, Project::MSG_INFO); + } + + $filesViolations = $phpcs->getFilesErrors(); + $reporting = new PHP_CodeSniffer_Reporting(); + $report = $reporting->prepare($filesViolations, $this->showWarnings); + + // process output + foreach ($this->formatters as $fe) { + switch ($fe->getType()) { + case 'default': + // default format goes to logs, no buffering + $this->outputCustomFormat($report); + $fe->setUseFile(false); + break; + + default: + $reportFile = null; + + if ($fe->getUseFile()) { + $reportFile = $fe->getOutfile(); + ob_start(); + } + + // Determine number of parameters required to + // ensure backwards compatibility + $rm = new ReflectionMethod('PHP_CodeSniffer_Reporting', 'printReport'); + + if ($rm->getNumberOfParameters() == 5) { + $reporting->printReport( + $fe->getType(), + $filesViolations, + $this->showSources, + $reportFile, + $this->reportWidth + ); + } else { + $reporting->printReport( + $fe->getType(), + $filesViolations, + $this->showWarnings, + $this->showSources, + $reportFile, + $this->reportWidth + ); + } + + // reporting class uses ob_end_flush(), but we don't want + // an output if we use a file + if ($fe->getUseFile()) { + ob_end_clean(); + } + break; + } + } + + return $report; + } + + /** + * Outputs the results with a custom format + * + * @param array $report Packaged list of all errors in each file + */ + protected function outputCustomFormat($report) { + $files = $report['files']; + foreach ($files as $file => $attributes) { + $errors = $attributes['errors']; + $warnings = $attributes['warnings']; + $messages = $attributes['messages']; + if ($errors > 0) { + $this->log($file . ': ' . $errors . ' error' . ($errors > 1 ? 's' : '') . ' detected', Project::MSG_ERR); + $this->outputCustomFormatMessages($messages, 'ERROR'); + } else { + $this->log($file . ': No syntax errors detected', Project::MSG_VERBOSE); + } + if ($warnings > 0) { + $this->log($file . ': ' . $warnings . ' warning' . ($warnings > 1 ? 's' : '') . ' detected', Project::MSG_WARN); + $this->outputCustomFormatMessages($messages, 'WARNING'); + } + } + + $totalErrors = $report['totals']['errors']; + $totalWarnings = $report['totals']['warnings']; + $this->log(count($files) . ' files where checked', Project::MSG_INFO); + if ($totalErrors > 0) { + $this->log($totalErrors . ' error' . ($totalErrors > 1 ? 's' : '') . ' detected', Project::MSG_ERR); + } else { + $this->log('No syntax errors detected', Project::MSG_INFO); + } + if ($totalWarnings > 0) { + $this->log($totalWarnings . ' warning' . ($totalWarnings > 1 ? 's' : '') . ' detected', Project::MSG_INFO); + } + } + + /** + * Outputs the messages of a specific type for one file + * @param array $messages + * @param string $type + */ + protected function outputCustomFormatMessages($messages, $type) { + foreach ($messages as $line => $messagesPerLine) { + foreach ($messagesPerLine as $column => $messagesPerColumn) { + foreach ($messagesPerColumn as $message) { + $msgType = $message['type']; + if ($type == $msgType) { + $logLevel = Project::MSG_INFO; + if ($msgType == 'ERROR') { + $logLevel = Project::MSG_ERR; + } else if ($msgType == 'WARNING') { + $logLevel = Project::MSG_WARN; + } + $text = $message['message']; + $string = $msgType . ' in line ' . $line . ' column ' . $column . ': ' . $text; + $this->log($string, $logLevel); + } + } + } + } + } + +} //end phpCodeSnifferTask + +/** + * @package phing.tasks.ext + */ +class PhpCodeSnifferTask_FormatterElement extends DataType { + + /** + * Type of output to generate + * @var string + */ + protected $type = ""; + + /** + * Output to file? + * @var bool + */ + protected $useFile = true; + + /** + * Output file. + * @var string + */ + protected $outfile = ""; + + /** + * Validate config. + */ + public function parsingComplete () { + if(empty($this->type)) { + throw new BuildException("Format missing required 'type' attribute."); + } + if ($useFile && empty($this->outfile)) { + throw new BuildException("Format requires 'outfile' attribute when 'useFile' is true."); + } + + } + + public function setType ($type) { + $this->type = $type; + } + + public function getType () { + return $this->type; + } + + public function setUseFile ($useFile) { + $this->useFile = $useFile; + } + + public function getUseFile () { + return $this->useFile; + } + + public function setOutfile ($outfile) { + $this->outfile = $outfile; + } + + public function getOutfile () { + return $this->outfile; + } + +} //end FormatterElement diff --git a/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php index 2fd89fc3..63ec1812 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php @@ -1,82 +1,278 @@ <?php +/* + * $Id: 524bae55e1007bc9778c232dd7b437964a66c5a4 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + require_once 'phing/Task.php'; +require_once 'phing/util/DataStore.php'; +require_once 'phing/system/io/FileWriter.php'; /** * A PHP lint task. Checking syntax of one or more PHP source file. * * @author Knut Urdalen <knut.urdalen@telio.no> + * @author Stefan Priebsch <stefan.priebsch@e-novative.de> + * @version $Id: 524bae55e1007bc9778c232dd7b437964a66c5a4 $ * @package phing.tasks.ext */ class PhpLintTask extends Task { - protected $file; // the source file (from xml attribute) - protected $filesets = array(); // all fileset objects assigned to this task - - /** - * 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"); + protected $file; // the source file (from xml attribute) + protected $filesets = array(); // all fileset objects assigned to this task + + protected $errorProperty; + protected $haltOnFailure = false; + protected $hasErrors = false; + protected $badFiles = array(); + protected $interpreter = ''; // php interpreter to use for linting + + protected $logLevel = Project::MSG_VERBOSE; + + protected $cache = null; + + protected $tofile = null; + + protected $deprecatedAsError = false; + + /** + * Initialize the interpreter with the Phing property + */ + public function __construct() { + $this->setInterpreter(Phing::getProperty('php.interpreter')); + } + + /** + * Override default php interpreter + * @todo Do some sort of checking if the path is correct but would + * require traversing the systems executeable path too + * @param string $sPhp + */ + public function setInterpreter($sPhp) { + $this->Interpreter = $sPhp; + } + + /** + * The haltonfailure property + * @param boolean $aValue + */ + public function setHaltOnFailure($aValue) { + $this->haltOnFailure = $aValue; + } + + /** + * File to be performed syntax check on + * @param PhingFile $file + */ + public function setFile(PhingFile $file) { + $this->file = $file; + } + + /** + * Set an property name in which to put any errors. + * @param string $propname + */ + public function setErrorproperty($propname) + { + $this->errorProperty = $propname; + } + + /** + * Whether to store last-modified times in cache + * + * @param PhingFile $file + */ + public function setCacheFile(PhingFile $file) + { + $this->cache = new DataStore($file); + } + + /** + * File to save error messages to + * + * @param PhingFile $file + */ + public function setToFile(PhingFile $tofile) + { + $this->tofile = $tofile; + } + + /** + * Nested creator, creates a FileSet for this task + * + * @return FileSet The created fileset object + */ + public function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Set level of log messages generated (default = info) + * @param string $level + */ + public function setLevel($level) + { + switch ($level) + { + case "error": $this->logLevel = Project::MSG_ERR; break; + case "warning": $this->logLevel = Project::MSG_WARN; break; + case "info": $this->logLevel = Project::MSG_INFO; break; + case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; + case "debug": $this->logLevel = Project::MSG_DEBUG; break; + } + } + + /** + * Sets whether to treat deprecated warnings (introduced in PHP 5.3) as errors + * @param boolean $deprecatedAsError + */ + public function setDeprecatedAsError($deprecatedAsError) + { + $this->deprecatedAsError = $deprecatedAsError; } - 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); - } - } + /** + * Execute lint check against PhingFile or a FileSet + */ + public function main() { + if(!isset($this->file) and count($this->filesets) == 0) { + throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + } + + if($this->file instanceof PhingFile) { + $this->lint($this->file->getPath()); + } else { // process filesets + $project = $this->getProject(); + foreach($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $files = $ds->getIncludedFiles(); + $dir = $fs->getDir($this->project)->getPath(); + foreach($files as $file) { + $this->lint($dir.DIRECTORY_SEPARATOR.$file); + } + } + } + + // write list of 'bad files' to file (if specified) + if ($this->tofile) { + $writer = new FileWriter($this->tofile); + + foreach ($this->badFiles as $file => $messages) { + foreach ($messages as $msg) { + $writer->write($file . "=" . $msg . PHP_EOL); + } + } + + $writer->close(); + } + + $message = ''; + foreach ($this->badFiles as $file => $messages) { + foreach ($messages as $msg) { + $message .= $file . "=" . $msg . PHP_EOL; + } + } + + // save list of 'bad files' with errors to property errorproperty (if specified) + if ($this->errorProperty) { + $this->project->setProperty($this->errorProperty, $message); + } + + if (!empty($this->cache)) { + $this->cache->commit(); + } + + if ($this->haltOnFailure && $this->hasErrors) { + throw new BuildException('Syntax error(s) in PHP files: ' . $message); + } } - } - - /** - * Performs the actual syntax check - * - * @param string $file - * @return void - */ - protected function lint($file) { - $command = '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); + + /** + * Performs the actual syntax check + * + * @param string $file + * @return void + */ + protected function lint($file) { + $command = $this->Interpreter == '' + ? 'php' + : $this->Interpreter; + $command .= ' -n -l '; + + if ($this->deprecatedAsError) { + $command .= '-d error_reporting=32767 '; + } + + if(file_exists($file)) { + if(is_readable($file)) { + if ($this->cache) + { + $lastmtime = $this->cache->get($file); + + if ($lastmtime >= filemtime($file)) + { + $this->log("Not linting '" . $file . "' due to cache", Project::MSG_DEBUG); + return false; + } + } + + $messages = array(); + $errorCount = 0; + + exec($command.'"'.$file.'" 2>&1', $messages); + + for ($i = 0; $i < count($messages) - 1; $i++) { + $message = $messages[$i]; + if (trim($message) == '') { + continue; + } + + if ((!preg_match('/^(.*)Deprecated:/', $message) || $this->deprecatedAsError) && !preg_match('/^No syntax errors detected/', $message)) { + $this->log($message, Project::MSG_ERR); + + if (!isset($this->badFiles[$file])) { + $this->badFiles[$file] = array(); + } + + array_push($this->badFiles[$file], $message); + + $this->hasErrors = true; + $errorCount++; + } + } + + if (!$errorCount) { + $this->log($file.': No syntax errors detected', $this->logLevel); + + if ($this->cache) + { + $this->cache->put($file, filemtime($file)); + } + } + } else { + throw new BuildException('Permission denied: '.$file); + } + } else { + throw new BuildException('File not found: '.$file); + } } - } } -?>
\ No newline at end of file + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/ReplaceRegexpTask.php b/buildscripts/phing/classes/phing/tasks/ext/ReplaceRegexpTask.php new file mode 100644 index 00000000..dc4ccbf7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ReplaceRegexpTask.php @@ -0,0 +1,204 @@ +<?php +/* + * $Id: f81043cad2c0ffe0a2571a0a8dc16a98651eac51 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * ReplaceRegExp is a directory based task for replacing the occurrence of a given regular expression with a substitution + * pattern in a selected file or set of files. + * + * <code> + * <replaceregexp file="${src}/build.properties" + * match="OldProperty=(.*)" + * replace="NewProperty=\1" + * byline="true"/> + * </code> + * + * @author Jonathan Bond-Caron <jbondc@openmv.com> + * @version $Id: f81043cad2c0ffe0a2571a0a8dc16a98651eac51 $ + * @package phing.tasks.system + * @link http://ant.apache.org/manual/OptionalTasks/replaceregexp.html + */ +class ReplaceRegexpTask extends Task { + + /** Single file to process. */ + private $file; + + /** Any filesets that should be processed. */ + private $filesets = array(); + + /** + * Regular expression + * + * @var RegularExpression + */ + private $_regexp; + + /** + * File to apply regexp on + * + * @param string $path + */ + public function setFile(PhingFile $path) + { + $this->file = $path; + } + + /** + * Sets the regexp match pattern + * + * @param string $regexp + */ + public function setMatch( $regexp ) + { + $this->_regexp->setPattern( $regexp ); + } + + /** + * @see setMatch() + */ + public function setPattern( $regexp ) + { + $this->setMatch( $regexp ); + } + + /** + * Sets the replacement string + * + * @param string $string + */ + public function setReplace( $string ) + { + $this->_regexp->setReplace( $string ); + } + + /** + * Sets the regexp flags + * + * @param string $flags + */ + public function setFlags( $flags ) + { + // TODO... $this->_regexp->setFlags( $flags ); + } + + /** + * Match only per line + * + * @param bool $yesNo + */ + public function setByline( $yesNo ) + { + // TODO... $this->_regexp-> + } + + /** Nested creator, adds a set of files (nested fileset attribute). */ + public function createFileSet() + { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + public function init() + { + $this->_regexp = new RegularExpression; + } + + public function main() + { + if ($this->file === null && empty($this->filesets)) { + throw new BuildException("You must specify a file or fileset(s) for the <ReplaceRegexp> task."); + } + + // compile a list of all files to modify, both file attrib and fileset elements + // can be used. + $files = array(); + + if ($this->file !== null) { + $files[] = $this->file; + } + + if (!empty($this->filesets)) { + $filenames = array(); + foreach($this->filesets as $fs) { + try { + $ds = $fs->getDirectoryScanner($this->project); + $filenames = $ds->getIncludedFiles(); // get included filenames + $dir = $fs->getDir($this->project); + foreach ($filenames as $fname) { + $files[] = new PhingFile($dir, $fname); + } + } catch (BuildException $be) { + $this->log($be->getMessage(), Project::MSG_WARN); + } + } + } + + $this->log("Applying Regexp processing to " . count($files) . " files."); + + // These "slots" allow filters to retrieve information about the currently-being-process files + $slot = $this->getRegisterSlot("currentFile"); + $basenameSlot = $this->getRegisterSlot("currentFile.basename"); + + $filter = new FilterChain($this->project); + + $r = new ReplaceRegexp; + $r->setRegexps(array($this->_regexp)); + + $filter->addReplaceRegexp($r); + $filters = array($filter); + + foreach($files as $file) { + // set the register slots + + $slot->setValue($file->getPath()); + $basenameSlot->setValue($file->getName()); + + // 1) read contents of file, pulling through any filters + $in = null; + try { + $contents = ""; + $in = FileUtils::getChainedReader(new FileReader($file), $filters, $this->project); + while(-1 !== ($buffer = $in->read())) { + $contents .= $buffer; + } + $in->close(); + } catch (Exception $e) { + if ($in) $in->close(); + $this->log("Error reading file: " . $e->getMessage(), Project::MSG_WARN); + } + + try { + // now create a FileWriter w/ the same file, and write to the file + $out = new FileWriter($file); + $out->write($contents); + $out->close(); + $this->log("Applying regexp processing to " . $file->getPath(), Project::MSG_VERBOSE); + } catch (Exception $e) { + if ($out) $out->close(); + $this->log("Error writing file back: " . $e->getMessage(), Project::MSG_WARN); + } + + } + + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/ScpTask.php b/buildscripts/phing/classes/phing/tasks/ext/ScpTask.php new file mode 100644 index 00000000..f6ceadd1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/ScpTask.php @@ -0,0 +1,380 @@ +<?php +/* + * $Id: 300efdab5b721c6312491450bc2ba93ffc8124b4 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * Copy files to and from a remote host using scp. + * + * @author Michiel Rook <mrook@php.net> + * @author Johan Van den Brande <johan@vandenbrande.com> + * @version $Id: 300efdab5b721c6312491450bc2ba93ffc8124b4 $ + * @package phing.tasks.ext + */ + +class ScpTask extends Task +{ + protected $file = ""; + protected $filesets = array(); // all fileset objects assigned to this task + protected $todir = ""; + protected $mode = null; + + protected $host = ""; + protected $port = 22; + protected $username = ""; + protected $password = ""; + protected $autocreate = true; + protected $fetch = false; + protected $localEndpoint = ""; + protected $remoteEndpoint = ""; + + protected $pubkeyfile = ''; + protected $privkeyfile = ''; + protected $privkeyfilepassphrase = ''; + + protected $connection = null; + protected $sftp = null; + + protected $count = 0; + + protected $logLevel = Project::MSG_VERBOSE; + + /** + * Sets the remote host + */ + public function setHost($h) + { + $this->host = $h; + } + + /** + * Returns the remote host + */ + public function getHost() + { + return $this->host; + } + + /** + * Sets the remote host port + */ + public function setPort($p) + { + $this->port = $p; + } + + /** + * Returns the remote host port + */ + public function getPort() + { + return $this->port; + } + + /** + * Sets the mode value + */ + public function setMode($value) + { + $this->mode = $value; + } + + /** + * Returns the mode value + */ + public function getMode() + { + return $this->mode; + } + + /** + * Sets the username of the user to scp + */ + public function setUsername($username) + { + $this->username = $username; + } + + /** + * Returns the username + */ + public function getUsername() + { + return $this->username; + } + + /** + * Sets the password of the user to scp + */ + public function setPassword($password) + { + $this->password = $password; + } + + /** + * Returns the password + */ + public function getPassword() + { + return $this->password; + } + + /** + * Sets the public key file of the user to scp + */ + public function setPubkeyfile($pubkeyfile) + { + $this->pubkeyfile = $pubkeyfile; + } + + /** + * Returns the pubkeyfile + */ + public function getPubkeyfile() + { + return $this->pubkeyfile; + } + + /** + * Sets the private key file of the user to scp + */ + public function setPrivkeyfile($privkeyfile) + { + $this->privkeyfile = $privkeyfile; + } + + /** + * Returns the private keyfile + */ + public function getPrivkeyfile() + { + return $this->privkeyfile; + } + + /** + * Sets the private key file passphrase of the user to scp + */ + public function setPrivkeyfilepassphrase($privkeyfilepassphrase) + { + $this->privkeyfilepassphrase = $privkeyfilepassphrase; + } + + /** + * Returns the private keyfile passphrase + */ + public function getPrivkeyfilepassphrase($privkeyfilepassphrase) + { + return $this->privkeyfilepassphrase; + } + + /** + * Sets whether to autocreate remote directories + */ + public function setAutocreate($autocreate) + { + $this->autocreate = (bool) $autocreate; + } + + /** + * Returns whether to autocreate remote directories + */ + public function getAutocreate() + { + return $this->autocreate; + } + + /** + * Set destination directory + */ + public function setTodir($todir) + { + $this->todir = $todir; + } + + /** + * Returns the destination directory + */ + public function getTodir() + { + return $this->todir; + } + + /** + * Sets local filename + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Returns local filename + */ + public function getFile() + { + return $this->file; + } + + /** + * Sets whether to send (default) or fetch files + */ + public function setFetch($fetch) + { + $this->fetch = (bool) $fetch; + } + + /** + * Returns whether to send (default) or fetch files + */ + public function getFetch() + { + return $this->fetch; + } + + /** + * Nested creator, creates a FileSet for this task + * + * @return FileSet The created fileset object + */ + public function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Set level of log messages generated (default = verbose) + * @param string $level + */ + public function setLevel($level) + { + switch ($level) + { + case "error": $this->logLevel = Project::MSG_ERR; break; + case "warning": $this->logLevel = Project::MSG_WARN; break; + case "info": $this->logLevel = Project::MSG_INFO; break; + case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; + case "debug": $this->logLevel = Project::MSG_DEBUG; break; + } + } + + public function init() + { + } + + public function main() + { + if (!function_exists('ssh2_connect')) { + throw new BuildException("To use ScpTask, you need to install the PHP SSH2 extension."); + } + + if ($this->file == "" && empty($this->filesets)) { + throw new BuildException("Missing either a nested fileset or attribute 'file'"); + } + + if ($this->host == "" || $this->username == "") { + throw new BuildException("Attribute 'host' and 'username' must be set"); + } + + $this->connection = ssh2_connect($this->host, $this->port); + if (is_null($this->connection)) { + throw new BuildException("Could not establish connection to " . $this->host . ":" . $this->port . "!"); + } + + $could_auth = null; + if ( $this->pubkeyfile ) { + $could_auth = ssh2_auth_pubkey_file($this->connection, $this->username, $this->pubkeyfile, $this->privkeyfile, $this->privkeyfilepassphrase); + } else { + $could_auth = ssh2_auth_password($this->connection, $this->username, $this->password); + } + if (!$could_auth) { + throw new BuildException("Could not authenticate connection!"); + } + + // prepare sftp resource + if ($this->autocreate) { + $this->sftp = ssh2_sftp($this->connection); + } + + if ($this->file != "") { + $this->copyFile($this->file, basename($this->file)); + } else { + if ($this->fetch) { + throw new BuildException("Unable to use filesets to retrieve files from remote server"); + } + + foreach($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($this->project); + $files = $ds->getIncludedFiles(); + $dir = $fs->getDir($this->project)->getPath(); + foreach($files as $file) { + $path = $dir.DIRECTORY_SEPARATOR.$file; + + // Translate any Windows paths + $this->copyFile($path, strtr($file, '\\', '/')); + } + } + } + + $this->log("Copied " . $this->counter . " file(s) " . ($this->fetch ? "from" : "to") . " '" . $this->host . "'"); + + // explicitly close ssh connection + @ssh2_exec($this->connection, 'exit'); + } + + protected function copyFile($local, $remote) + { + $path = rtrim($this->todir, "/") . "/"; + + if ($this->fetch) { + $localEndpoint = $path . $remote; + $remoteEndpoint = $local; + + $this->log('Will fetch ' . $remoteEndpoint . ' to ' . $localEndpoint, $this->logLevel); + + $ret = @ssh2_scp_recv($this->connection, $remoteEndpoint, $localEndpoint); + + if ($ret === false) { + throw new BuildException("Could not fetch remote file '" . $remoteEndpoint . "'"); + } + } else { + $localEndpoint = $local; + $remoteEndpoint = $path . $remote; + + if ($this->autocreate) { + ssh2_sftp_mkdir($this->sftp, dirname($remoteEndpoint), (is_null($this->mode) ? 0777 : $this->mode), true); + } + + $this->log('Will copy ' . $localEndpoint . ' to ' . $remoteEndpoint, $this->logLevel); + + if (!is_null($this->mode)) { + $ret = @ssh2_scp_send($this->connection, $localEndpoint, $remoteEndpoint, $this->mode); + } else { + $ret = @ssh2_scp_send($this->connection, $localEndpoint, $remoteEndpoint); + } + + if ($ret === false) { + throw new BuildException("Could not create remote file '" . $remoteEndpoint . "'"); + } + } + + $this->counter++; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon.php new file mode 100644 index 00000000..6e8fa8e0 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon.php @@ -0,0 +1,120 @@ +<?php + +/* + * $Id: 81e9d8cbc94bac15a6a32ed0bb23c04d2b0ff439 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once "phing/Task.php"; + +/** + * Abstract Service_Amazon class. + * + * Implements common methods & properties used by all Amazon services + * + * @extends Task + * @version $ID$ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @abstract + */ +abstract class Service_Amazon extends Task +{ + /** + * Collection of set options + * + * We set these magically so we can also load then from the environment + * + * (default value: array()) + * + * @var array + * @access protected + */ + protected $_options = array(); + + public function __set($var, $val) + { + $this->_options[$var] = $val; + } + + /** + * Property getter + * + * If the property hasn't been previously set (through the task call normally), + * it will try to load it from the project + * + * This way, we can define global properties for the "Amazon" service, like key and secret + * + * @access public + * @param mixed $var + * @return void + */ + public function __get($var) + { + if(!isset($this->$var)) { + if(!($val = $this->getProject()->getProperty('amazon.' . strtolower($var)))) { + return false; + } else { + return $val; + } + } + + return $this->_options[$var]; + } + + public function __isset($var) + { + return array_key_exists($var, $this->_options); + } + + public function setKey($key) + { + if(empty($key) || !is_string($key)) { + throw new BuildException('Key must be a non empty string'); + } + + $this->key = $key; + } + + public function getKey() + { + if(!($key = $this->key)) { + throw new BuildException('Key is not set'); + } + + return $key; + } + + public function setSecret($secret) + { + if(empty($secret) || !is_string($secret)) { + throw new BuildException('Secret must be a non empty string'); + } + + $this->secret = $secret; + } + + public function getSecret() + { + if(!($secret = $this->secret)) { + throw new BuildException('Secret is not set'); + } + + return $this->secret; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3.php new file mode 100644 index 00000000..7bed642e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3.php @@ -0,0 +1,188 @@ +<?php + +/* + * $Id: a205dcffd1f42b70a8101808242d66620e3dabbd $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once dirname(dirname(__FILE__)) . "/Amazon.php"; + +/** + * Abstract Service_Amazon_S3 class. + * + * Provides common methods and properties to all of the S3 tasks + * + * @extends Service_Amazon + * @version $ID$ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @abstract + */ +abstract class Service_Amazon_S3 extends Service_Amazon +{ + /** + * Services_Amazon_S3 client + * + * (default value: null) + * + * @var Services_Amazon_S3 + * @see Services_Amazon_S3 + * @access protected + */ + protected $_client = null; + + /** + * We only instantiate the client once per task call + * + * @access public + * @return Services_Amazon_S3 + */ + public function getClient() + { + require_once "Services/Amazon/S3.php"; + + if($this->_client === null) { + $this->_client = Services_Amazon_S3::getAccount($this->getKey(), $this->getSecret()); + } + + return $this->_client; + } + + public function setBucket($bucket) + { + if(empty($bucket) || !is_string($bucket)) { + throw new BuildException('Bucket must be a non-empty string'); + } + + $this->bucket = (string) $bucket; + } + + public function getBucket() + { + if(!($bucket = $this->bucket)) { + throw new BuildException('Bucket is not set'); + } + + return $this->bucket; + } + + /** + * Returns an instance of Services_Amazon_S3_Resource_Object + * + * @access public + * @param mixed $object + * @return Services_Amazon_S3_Resource_Object + */ + public function getObjectInstance($object) + { + return $this->getBucketInstance()->getObject($object); + } + + /** + * Check if the object already exists in the current bucket + * + * @access public + * @param mixed $object + * @return bool + */ + public function isObjectAvailable($object) + { + return (bool) $this->getObjectInstance($object)->load(Services_Amazon_S3_Resource_Object::LOAD_METADATA_ONLY); + } + + /** + * Returns an instance of Services_Amazon_S3_Resource_Bucket + * + * @access public + * @return Services_Amazon_S3_Resource_Bucket + */ + public function getBucketInstance() + { + return $this->getClient()->getBucket($this->getBucket()); + } + + /** + * Check if the current bucket is available + * + * @access public + * @return bool + */ + public function isBucketAvailable() + { + return (bool) $this->getBucketInstance($this->getBucket())->load(); + } + + /** + * Get the contents of an object (by it's name) + * + * @access public + * @param string $object + * @return mixed + */ + public function getObjectContents($object) + { + if(!$this->isBucketAvailable($this->getBucket())) { + throw new BuildException('Bucket doesn\'t exist or wrong permissions'); + } + + $bucket = $this->getClient()->getBucket($this->getBucket()); + if(!$this->isObjectAvailable($object)) { + throw new BuildException('Object not available: ' . $object); + } + + $object = $this->getObjectInstance($object); + $object->load(); + return $object->data; + } + + /** + * Create a bucket + * + * @access public + * @return void + */ + public function createBucket() + { + $bucket = $this->getBucketInstance(); + $bucket->name = $this->getBucket(); + $bucket->save(); + + return $this->isBucketAvailable(); + } + + /** + * Main entry point, doesn't do anything + * + * @access public + * @final + * @return void + */ + final public function main() + { + $this->execute(); + } + + /** + * Entry point to children tasks + * + * @access public + * @abstract + * @return void + */ + abstract public function execute(); +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php new file mode 100644 index 00000000..37b4e817 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php @@ -0,0 +1,108 @@ +<?php + +/* + * $Id: 214ed107be71d8dbc0f68ffc90bfd8b11a76b36d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once dirname(dirname(__FILE__)) . '/S3.php'; + +/** + * Downloads an object off S3 + * + * @version $Id: 214ed107be71d8dbc0f68ffc90bfd8b11a76b36d $ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @extends Service_Amazon_S3 + */ +class S3GetTask extends Service_Amazon_S3 +{ + /** + * This is where we'll store the object + * + * (default value: null) + * + * @var mixed + * @access protected + */ + protected $_target = null; + + /** + * The S3 object we're working with + * + * (default value: null) + * + * @var mixed + * @access protected + */ + protected $_object = null; + + public function setObject($object) + { + if(empty($object) || !is_string($object)) { + throw new BuildException('Object must be a non-empty string'); + } + + $this->_object = $object; + } + + public function getObject() + { + if($this->_object === null) { + throw new BuildException('Object is not set'); + } + + return $this->_object; + } + + public function setTarget($target) + { + if(!is_file($target) && !is_dir($target) && !is_link($target)) { + if(!is_writable(dirname($target))) { + throw new BuildException('Target is not writable: ' . $target); + } + } else { + if(!is_writable($target)) { + throw new BuildException('Target is not writable: ' . $target); + } + } + + $this->_target = $target; + } + + public function getTarget() + { + if($this->_target === null) { + throw new BuildException('Target is not set'); + } + + return $this->_target; + } + + public function execute() + { + $target = $this->getTarget(); + + // Use the object name as the target if the current target is a directory + if(is_dir($target)) { + $target = rtrim($target, '/') . '/' . $this->getObject(); + } + + file_put_contents($target, $this->getObjectContents($this->getObject())); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php new file mode 100644 index 00000000..dbb18b56 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php @@ -0,0 +1,243 @@ +<?php +/* + * $Id: 84b1d6039427591cbf43dbe1a82691063ae4238a $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once dirname(dirname(__FILE__)) . '/S3.php'; + +/** + * Stores an object on S3 + * + * @version $Id: 84b1d6039427591cbf43dbe1a82691063ae4238a $ + * @package phing.tasks.ext + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @extends Service_Amazon_S3 + */ +class S3PutTask extends Service_Amazon_S3 +{ + /** + * File we're trying to upload + * + * (default value: null) + * + * @var string + * @access protected + */ + protected $_source = null; + + /** + * Content we're trying to upload + * + * The user can specify either a file to upload or just a bit of content + * + * (default value: null) + * + * @var mixed + * @access protected + */ + protected $_content = null; + + /** + * Collection of filesets + * Used for uploading multiple files + * + * (default value: array()) + * + * @var array + * @access protected + */ + protected $_filesets = array(); + + /** + * Whether to try to create buckets or not + * + * (default value: false) + * + * @var bool + * @access protected + */ + protected $_createBuckets = false; + + public function setSource($source) + { + if(!is_readable($source)) { + throw new BuildException('Source is not readable: ' . $source); + } + + $this->_source = $source; + } + + public function getSource() + { + if($this->_source === null) { + throw new BuildException('Source is not set'); + } + + return $this->_source; + } + + public function setContent($content) + { + if(empty($content) || !is_string($content)) { + throw new BuildException('Content must be a non-empty string'); + } + + $this->_content = $content; + } + + public function getContent() + { + if($this->_content === null) { + throw new BuildException('Content is not set'); + } + + return $this->_content; + } + + public function setObject($object) + { + if(empty($object) || !is_string($object)) { + throw new BuildException('Object must be a non-empty string'); + } + + $this->_object = $object; + } + + public function getObject() + { + if($this->_object === null) { + throw new BuildException('Object is not set'); + } + + return $this->_object; + } + + public function setCreateBuckets($createBuckets) + { + $this->_createBuckets = (bool) $createBuckets; + } + + public function getCreateBuckets() + { + return (bool) $this->_createBuckets; + } + + /** + * creator for _filesets + * + * @access public + * @return FileSet + */ + public function createFileset() + { + $num = array_push($this->_filesets, new FileSet()); + return $this->_filesets[$num-1]; + } + + /** + * getter for _filesets + * + * @access public + * @return array + */ + public function getFilesets() + { + return $this->_filesets; + } + + /** + * Determines what we're going to store in the object + * + * If _content has been set, this will get stored, + * otherwise, we read from _source + * + * @access public + * @return string + */ + public function getObjectData() + { + try { + $content = $this->getContent(); + } catch(BuildException $e) { + $source = $this->getSource(); + + if(!is_file($source)) { + throw new BuildException('Currently only files can be used as source'); + } + + $content = file_get_contents($source); + } + + return $content; + } + + /** + * Store the object on S3 + * + * @access public + * @return void + */ + public function execute() + { + if(!$this->isBucketAvailable()) { + if(!$this->getCreateBuckets()) { + throw new BuildException('Bucket doesn\'t exist and createBuckets not specified'); + } else{ + if(!$this->createBucket()) { + throw new BuildException('Bucket cannot be created'); + } + } + } + + // Filesets take precedence + if(!empty($this->_filesets)) { + $objects = array(); + + foreach($this->_filesets as $fs) { + if(!($fs instanceof FileSet)) { + continue; + } + + $ds = $fs->getDirectoryScanner($this->getProject()); + $objects = array_merge($objects, $ds->getIncludedFiles()); + } + + $fromDir = $fs->getDir($this->getProject())->getAbsolutePath(); + + foreach($objects as $object) { + $this->saveObject($object, file_get_contents($fromDir . DIRECTORY_SEPARATOR . $object)); + } + + return true; + } + + $this->saveObject($this->getObject(), $this->getObjectData()); + } + + protected function saveObject($object, $data) + { + $object = $this->getObjectInstance($object); + $object->data = $data; + $object->save(); + + if(!$this->isObjectAvailable($object->key)) { + throw new BuildException('Upload failed'); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php b/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php index 97eada3d..69c7b8f8 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: SmartyTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 1fe8b2aa2668db628554e59b3099520c0e1c03e4 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -37,7 +37,7 @@ include_once 'phing/util/StringHelper.php'; * @author Hans Lellelid <hans@xmpl.org> (SmartyTask) * @author Jason van Zyl <jvanzyl@apache.org> (TexenTask) * @author Robert Burrell Donkin <robertdonkin@mac.com> - * @version $Id: SmartyTask.php 59 2006-04-28 14:49:47Z mrook $ + * @version $Id: 1fe8b2aa2668db628554e59b3099520c0e1c03e4 $ * @package phing.tasks.ext */ class SmartyTask extends Task { @@ -233,7 +233,7 @@ class SmartyTask extends Task { public function setOutputDirectory(PhingFile $outputDirectory) { try { if (!$outputDirectory->exists()) { - $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE); + $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),Project::MSG_VERBOSE); if (!$outputDirectory->mkdirs()) { throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath()); } @@ -494,7 +494,7 @@ class SmartyTask extends Task { $smartyCompilePath = new PhingFile($this->context->compile_dir); if (!$smartyCompilePath->exists()) { - $this->log("Compile directory does not exist, creating: " . $smartyCompilePath->getPath(), PROJECT_MSG_VERBOSE); + $this->log("Compile directory does not exist, creating: " . $smartyCompilePath->getPath(), Project::MSG_VERBOSE); if (!$smartyCompilePath->mkdirs()) { throw new BuildException("Smarty needs a place to compile templates; specify a 'compilePath' or create ".$this->context->compile_dir); } @@ -543,7 +543,7 @@ class SmartyTask extends Task { // reset value, and then // read in teh contents of the file into that var $value = ""; - $f = new PhingFile($project->resolveFile($value)->getCanonicalPath()); + $f = new PhingFile($this->project->resolveFile($value)->getCanonicalPath()); if ($f->exists()) { try { $fr = new FileReader($f); diff --git a/buildscripts/phing/classes/phing/tasks/ext/SshTask.php b/buildscripts/phing/classes/phing/tasks/ext/SshTask.php new file mode 100644 index 00000000..9c2349a8 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SshTask.php @@ -0,0 +1,224 @@ +<?php +/* + * $Id: e0fe77ed287d359bd7449d459769370e6192417f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * Execute commands on a remote host using ssh. + * + * @author Johan Van den Brande <johan@vandenbrande.com> + * @version $Id: e0fe77ed287d359bd7449d459769370e6192417f $ + * @package phing.tasks.ext + */ +class SshTask extends Task { + + private $host = ""; + private $port = 22; + private $username = ""; + private $password = ""; + private $command = ""; + private $pubkeyfile = ''; + private $privkeyfile = ''; + private $privkeyfilepassphrase = ''; + + /** + * The name of the property to capture (any) output of the command + * @var string + */ + private $property = ""; + + /** + * Whether to display the output of the command + * @var boolean + */ + private $display = true; + + public function setHost($host) + { + $this->host = $host; + } + + public function getHost() + { + return $this->host; + } + + public function setPort($port) + { + $this->port = $port; + } + + public function getPort() + { + return $this->port; + } + + public function setUsername($username) + { + $this->username = $username; + } + + public function getUsername() + { + return $this->username; + } + + public function setPassword($password) + { + $this->password = $password; + } + + public function getPassword() + { + return $this->password; + } + + /** + * Sets the public key file of the user to scp + */ + public function setPubkeyfile($pubkeyfile) + { + $this->pubkeyfile = $pubkeyfile; + } + + /** + * Returns the pubkeyfile + */ + public function getPubkeyfile() + { + return $this->pubkeyfile; + } + + /** + * Sets the private key file of the user to scp + */ + public function setPrivkeyfile($privkeyfile) + { + $this->privkeyfile = $privkeyfile; + } + + /** + * Returns the private keyfile + */ + public function getPrivkeyfile() + { + return $this->privkeyfile; + } + + /** + * Sets the private key file passphrase of the user to scp + */ + public function setPrivkeyfilepassphrase($privkeyfilepassphrase) + { + $this->privkeyfilepassphrase = $privkeyfilepassphrase; + } + + /** + * Returns the private keyfile passphrase + */ + public function getPrivkeyfilepassphrase($privkeyfilepassphrase) + { + return $this->privkeyfilepassphrase; + } + + public function setCommand($command) + { + $this->command = $command; + } + + public function getCommand() + { + return $this->command; + } + + /** + * Sets the name of the property to capture (any) output of the command + * @param string $property + */ + public function setProperty($property) + { + $this->property = $property; + } + + /** + * Sets whether to display the output of the command + * @param boolean $display + */ + public function setDisplay($display) + { + $this->display = (boolean) $display; + } + + public function init() + { + } + + public function main() + { + if (!function_exists('ssh2_connect')) { + throw new BuildException("To use SshTask, you need to install the PHP SSH2 extension."); + } + + $this->connection = ssh2_connect($this->host, $this->port); + if (is_null($this->connection)) { + throw new BuildException("Could not establish connection to " . $this->host . ":" . $this->port . "!"); + } + + $could_auth = null; + if ( $this->pubkeyfile ) { + $could_auth = ssh2_auth_pubkey_file($this->connection, $this->username, $this->pubkeyfile, $this->privkeyfile, $this->privkeyfilepassphrase); + } else { + $could_auth = ssh2_auth_password($this->connection, $this->username, $this->password); + } + if (!$could_auth) { + throw new BuildException("Could not authenticate connection!"); + } + + $stream = ssh2_exec($this->connection, $this->command); + if (!$stream) { + throw new BuildException("Could not execute command!"); + } + + $this->log("Executing command {$this->command}", Project::MSG_VERBOSE); + + stream_set_blocking($stream, true); + $result = stream_get_contents($stream); + + if (!strlen($result)) { + $stderr_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR); + stream_set_blocking($stderr_stream, true); + $result = stream_get_contents($stderr_stream); + } + + if ($this->display) { + print($result); + } + + if (!empty($this->property)) { + $this->project->setProperty($this->property, $result); + } + + fclose($stream); + if (isset($stderr_stream)) { + fclose($stderr_stream); + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/Arg.php b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/Arg.php new file mode 100644 index 00000000..564fdef4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/Arg.php @@ -0,0 +1,96 @@ +<?php +require_once "phing/types/DataType.php"; + + +/** + * Implementation of console argument + * + * @author nuno costa <nuno@francodacosta.com> + * @license GPL + */ +class Arg extends DataType +{ + private $name = null; + private $value = null; + private $quotes = false; + + /** + * Gets the argment name + * @return String + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the argument name + * @param String $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Gets the argument value + * @return String + */ + public function getValue() + { + return $this->value; + } + + /** + * Sets the argument value + * @param String $value + */ + public function setValue($value) + { + $this->value = $value; + } + + /** + * Should the argument value be enclosed in double quotes + * @return boolean + */ + public function getQuotes() + { + return $this->quotes; + } + + /** + * Should the argument value be enclosed in double quotes + * @param boolean $quotes + */ + public function setQuotes( $quotes) + { + $this->quotes = $quotes; + } + + /** + * Transforms the argument object into a string, takes into consideration + * the quotes and the argument value + * @return String + */ + public function __toString() + { + $name = ""; + $value = ""; + $quote = $this->getQuotes() ? '"' : ''; + + if (!is_null($this->getValue())) { + $value = $quote . $this->getValue() . $quote ; + } + + if (!is_null($this->getName())) { + $name = '--' . $this->getName(); + } + + if (strlen($name) > 0 && strlen($value) > 0) { + $value = '=' . $value; + } + return $name . ' ' . $value; + } + +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php new file mode 100644 index 00000000..64c1f02b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php @@ -0,0 +1,113 @@ +<?php +require_once "phing/Task.php"; +require_once dirname(__FILE__) . "/Arg.php"; +/** + * Symfony Console Task + * @author nuno costa <nuno@francodacosta.com> + * @license GPL + * + */ +class SymfonyConsoleTask extends Task +{ + + /** + * + * @var Array of Arg a collection of Arg objects + */ + private $args = array(); + + /** + * + * @var string the Symfony console command to execute + */ + private $command = null; + + /** + * + * @var string path to symfony console application + */ + private $console = 'app/console'; + + + /** + * sets the symfony console command to execute + * @param string $command + */ + public function setCommand($command) + { + $this->command = $command; + } + + /** + * return the symfony console command to execute + * @return String + */ + public function getCommand() + { + return $this->command; + } + + /** + * sets the path to symfony console application + * @param string $console + */ + public function setConsole($console) + { + $this->console = $console; + } + + /** + * returns the path to symfony console application + * @return string + */ + public function getConsole() + { + return $this->console; + } + + /** + * appends an arg tag to the arguments stack + * + * @return Arg Argument object + */ + + public function createArg() + { + $num = array_push($this->args, new Arg());
+ return $this->args[$num-1]; + } + + /** + * return the argumments passed to this task + * @return array of Arg() + */ + public function getArgs() + { + return $this->args; + } + + + /** + * Gets the command string to be executed + * @return string + */ + public function getCmdString() { + $cmd = array(
+ $this->console,
+ $this->command,
+ implode(' ', $this->args)
+ );
+ $cmd = implode(' ', $cmd); + return $cmd; + } + /** + * executes the synfony consile application + */ + public function main() + { + $cmd = $this->getCmdString(); + + $this->log("executing $cmd"); + passthru ($cmd); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/SymlinkTask.php b/buildscripts/phing/classes/phing/tasks/ext/SymlinkTask.php new file mode 100644 index 00000000..57738398 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/SymlinkTask.php @@ -0,0 +1,309 @@ +<?php + +/* + * $Id: 6efb50d5b7cb94f2f22db6e876010e718aa25b22 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once "phing/Task.php"; + +/** + * Generates symlinks based on a target / link combination. + * Can also symlink contents of a directory, individually + * + * Single target symlink example: + * <code> + * <symlink target="/some/shared/file" link="${project.basedir}/htdocs/my_file" /> + * </code> + * + * Symlink entire contents of directory + * + * This will go through the contents of "/my/shared/library/*" + * and create a symlink for each entry into ${project.basedir}/library/ + * <code> + * <symlink link="${project.basedir}/library"> + * <fileset dir="/my/shared/library"> + * <include name="*" /> + * </fileset> + * </symlink> + * </code> + * + * @author Andrei Serdeliuc <andrei@serdeliuc.ro> + * @extends Task + * @version $ID$ + * @package phing.tasks.ext + */ +class SymlinkTask extends Task +{ + /** + * What we're symlinking from + * + * (default value: null) + * + * @var string + * @access private + */ + private $_target = null; + + /** + * Symlink location + * + * (default value: null) + * + * @var string + * @access private + */ + private $_link = null; + + /** + * Collection of filesets + * Used when linking contents of a directory + * + * (default value: array()) + * + * @var array + * @access private + */ + private $_filesets = array(); + + /** + * Whether to override the symlink if it exists but points + * to a different location + * + * (default value: false) + * + * @var boolean + * @access private + */ + private $_overwrite = false; + + /** + * setter for _target + * + * @access public + * @param string $target + * @return void + */ + public function setTarget($target) + { + $this->_target = $target; + } + + /** + * setter for _link + * + * @access public + * @param string $link + * @return void + */ + public function setLink($link) + { + $this->_link = $link; + } + + /** + * creator for _filesets + * + * @access public + * @return FileSet + */ + public function createFileset() + { + $num = array_push($this->_filesets, new FileSet()); + return $this->_filesets[$num-1]; + } + + /** + * setter for _overwrite + * + * @access public + * @param boolean $overwrite + * @return void + */ + public function setOverwrite($overwrite) + { + $this->_overwrite = $overwrite; + } + + /** + * getter for _target + * + * @access public + * @return string + */ + public function getTarget() + { + if($this->_target === null) { + throw new BuildException('Target not set'); + } + + return $this->_target; + } + + /** + * getter for _link + * + * @access public + * @return string + */ + public function getLink() + { + if($this->_link === null) { + throw new BuildException('Link not set'); + } + + return $this->_link; + } + + /** + * getter for _filesets + * + * @access public + * @return array + */ + public function getFilesets() + { + return $this->_filesets; + } + + /** + * getter for _overwrite + * + * @access public + * @return boolean + */ + public function getOverwrite() + { + return $this->_overwrite; + } + + /** + * Generates an array of directories / files to be linked + * If _filesets is empty, returns getTarget() + * + * @access protected + * @return array|string + */ + protected function getMap() + { + $fileSets = $this->getFilesets(); + + // No filesets set + // We're assuming single file / directory + if(empty($fileSets)) { + return $this->getTarget(); + } + + $targets = array(); + + foreach($fileSets as $fs) { + if(!($fs instanceof FileSet)) { + continue; + } + + // We need a directory to store the links + if(!is_dir($this->getLink())) { + throw new BuildException('Link must be an existing directory when using fileset'); + } + + $fromDir = $fs->getDir($this->getProject())->getAbsolutePath(); + + if(!is_dir($fromDir)) { + $this->log('Directory doesn\'t exist: ' . $fromDir, Project::MSG_WARN); + continue; + } + + $fsTargets = array(); + + $ds = $fs->getDirectoryScanner($this->getProject()); + + $fsTargets = array_merge( + $fsTargets, + $ds->getIncludedDirectories(), + $ds->getIncludedFiles() + ); + + // Add each target to the map + foreach($fsTargets as $target) { + if(!empty($target)) { + $targets[$target] = $fromDir . DIRECTORY_SEPARATOR . $target; + } + } + } + + return $targets; + } + + /** + * Main entry point for task + * + * @access public + * @return bool + */ + public function main() + { + $map = $this->getMap(); + + // Single file symlink + if(is_string($map)) { + return $this->symlink($map, $this->getLink()); + } + + // Multiple symlinks + foreach($map as $name => $targetPath) { + $this->symlink($targetPath, $this->getLink() . DIRECTORY_SEPARATOR . $name); + } + + return true; + } + + /** + * Create the actual link + * + * @access protected + * @param string $target + * @param string $link + * @return bool + */ + protected function symlink($target, $link) + { + $fs = FileSystem::getFileSystem(); + + if (is_link($link) && readlink($link) == $target) { + $this->log('Link exists: ' . $link, Project::MSG_INFO); + return true; + } elseif (file_exists($link)) { + if (!$this->getOverwrite()) { + $this->log('Not overwriting existing link ' . $link, Project::MSG_ERR); + return false; + } + + if (is_link($link) || is_file($link)) { + $fs->unlink($link); + $this->log('Link removed: ' . $link, Project::MSG_INFO); + } else { + $fs->rmdir($link, true); + $this->log('Directory removed: ' . $link, Project::MSG_INFO); + } + } + + $this->log('Linking: ' . $target . ' to ' . $link, Project::MSG_INFO); + + return $fs->symlink($target, $link); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/TarTask.php b/buildscripts/phing/classes/phing/tasks/ext/TarTask.php index 8d6bb47f..95d915d7 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/TarTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/TarTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: TarTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c3ac5fcdf4d7cdb199d57b021e3f015c9c7fd3f8 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/util/StringHelper.php'; * @author Stefano Mazzocchi <stefano@apache.org> (Ant) * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) * @author Magesh Umasankar - * @version $Revision: 1.10 $ + * @version $Id: c3ac5fcdf4d7cdb199d57b021e3f015c9c7fd3f8 $ * @package phing.tasks.ext */ class TarTask extends MatchingTask { @@ -44,7 +44,8 @@ class TarTask extends MatchingTask { private $tarFile; private $baseDir; - + private $includeEmpty = true; // Whether to include empty dirs in the TAR + private $longFileMode = "warn"; private $filesets = array(); @@ -59,6 +60,13 @@ class TarTask extends MatchingTask { * Compression mode. Available options "gzip", "bzip2", "none" (null). */ private $compression = null; + + /** + * File path prefix in the tar archive + * + * @var string + */ + private $prefix = null; /** * Ensures that PEAR lib exists. @@ -108,6 +116,16 @@ class TarTask extends MatchingTask { } /** + * Set the include empty dirs flag. + * @param boolean Flag if empty dirs should be tarred too + * @return void + * @access public + */ + public function setIncludeEmptyDirs($bool) { + $this->includeEmpty = (boolean) $bool; + } + + /** * Set how to handle long files, those with a path>100 chars. * Optional, default=warn. * <p> @@ -145,10 +163,21 @@ class TarTask extends MatchingTask { $this->compression = null; break; default: - $this->log("Ignoring unknown compression mode: ".$mode, PROJECT_MSG_WARN); + $this->log("Ignoring unknown compression mode: ".$mode, Project::MSG_WARN); $this->compression = null; } } + + /** + * Sets the file path prefix for file in the tar file. + * + * @param string $prefix Prefix + * + * @return void + */ + public function setPrefix($prefix) { + $this->prefix = $prefix; + } /** * do the work @@ -175,13 +204,14 @@ class TarTask extends MatchingTask { try { if ($this->baseDir !== null) { if (!$this->baseDir->exists()) { - throw new BuildException("basedir does not exist!", $this->getLocation()); + throw new BuildException("basedir '" . (string) $this->baseDir . "' does not exist!", $this->getLocation()); + } + if (empty($this->filesets)) { // if there weren't any explicit filesets specivied, then + // create a default, all-inclusive fileset using the specified basedir. + $mainFileSet = new TarFileSet($this->fileset); + $mainFileSet->setDir($this->baseDir); + $this->filesets[] = $mainFileSet; } - - // add the main fileset to the list of filesets to process. - $mainFileSet = new TarFileSet($this->fileset); - $mainFileSet->setDir($this->baseDir); - $this->filesets[] = $mainFileSet; } if (empty($this->filesets)) { @@ -190,27 +220,27 @@ class TarTask extends MatchingTask { $this->getLocation()); } - // check if tar is out of date with respect to each - // fileset - $upToDate = true; - foreach($this->filesets as $fs) { - $files = $fs->getFiles($this->project); - if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) { - $upToDate = false; - } - for ($i=0, $fcount=count($files); $i < $fcount; $i++) { - if ($this->tarFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) { - throw new BuildException("A tar file cannot include itself", $this->getLocation()); + // check if tar is out of date with respect to each fileset + if($this->tarFile->exists()) { + $upToDate = true; + foreach($this->filesets as $fs) { + $files = $fs->getFiles($this->project, $this->includeEmpty); + if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) { + $upToDate = false; + } + for ($i=0, $fcount=count($files); $i < $fcount; $i++) { + if ($this->tarFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) { + throw new BuildException("A tar file cannot include itself", $this->getLocation()); + } } } + if ($upToDate) { + $this->log("Nothing to do: " . $this->tarFile->__toString() . " is up to date.", Project::MSG_INFO); + return; + } } - if ($upToDate) { - $this->log("Nothing to do: " . $this->tarFile->__toString() . " is up to date.", PROJECT_MSG_INFO); - return; - } - - $this->log("Building tar: " . $this->tarFile->__toString(), PROJECT_MSG_INFO); + $this->log("Building tar: " . $this->tarFile->__toString(), Project::MSG_INFO); $tar = new Archive_Tar($this->tarFile->getAbsolutePath(), $this->compression); @@ -218,25 +248,21 @@ class TarTask extends MatchingTask { $tar->setErrorHandling(PEAR_ERROR_PRINT); foreach($this->filesets as $fs) { - $files = $fs->getFiles($this->project); + $files = $fs->getFiles($this->project, $this->includeEmpty); if (count($files) > 1 && strlen($fs->getFullpath()) > 0) { throw new BuildException("fullpath attribute may only " . "be specified for " . "filesets that specify a " . "single file."); } - // FIXME - // Current model is only adding directories implicitly. This - // won't add any empty directories. Perhaps modify TarFileSet::getFiles() - // to also include empty directories. Not high priority, since non-inclusion - // of empty dirs is probably not unexpected behavior for TarTask. $fsBasedir = $fs->getDir($this->project); $filesToTar = array(); for ($i=0, $fcount=count($files); $i < $fcount; $i++) { $f = new PhingFile($fsBasedir, $files[$i]); - $filesToTar[] = $f->getAbsolutePath(); + $filesToTar[] = $f->getAbsolutePath(); + $this->log("Adding file " . $f->getPath() . " to archive.", Project::MSG_VERBOSE); } - $tar->addModify($filesToTar, '', $fsBasedir->getAbsolutePath()); + $tar->addModify($filesToTar, $this->prefix, $fsBasedir->getAbsolutePath()); } @@ -270,6 +296,7 @@ class TarTask extends MatchingTask { * Permissions are currently not implemented by PEAR Archive_Tar, * but hopefully they will be in the future. * + * @package phing.tasks.ext */ class TarFileSet extends FileSet { @@ -288,11 +315,49 @@ class TarFileSet extends FileSet { * @return array a list of file and directory names, relative to * the baseDir for the project. */ - public function getFiles(Project $p) { + public function getFiles(Project $p, $includeEmpty = true) { + if ($this->files === null) { + $ds = $this->getDirectoryScanner($p); $this->files = $ds->getIncludedFiles(); - } + + if ($includeEmpty) { + + // first any empty directories that will not be implicitly added by any of the files + $implicitDirs = array(); + foreach($this->files as $file) { + $implicitDirs[] = dirname($file); + } + + $incDirs = $ds->getIncludedDirectories(); + + // we'll need to add to that list of implicit dirs any directories + // that contain other *directories* (and not files), since otherwise + // we get duplicate directories in the resulting tar + foreach($incDirs as $dir) { + foreach($incDirs as $dircheck) { + if (!empty($dir) && $dir == dirname($dircheck)) { + $implicitDirs[] = $dir; + } + } + } + + $implicitDirs = array_unique($implicitDirs); + + // Now add any empty dirs (dirs not covered by the implicit dirs) + // to the files array. + + foreach($incDirs as $dir) { // we cannot simply use array_diff() since we want to disregard empty/. dirs + if ($dir != "" && $dir != "." && !in_array($dir, $implicitDirs)) { + // it's an empty dir, so we'll add it. + $this->files[] = $dir; + } + } + } // if $includeEmpty + + } // if ($this->files===null) + return $this->files; } diff --git a/buildscripts/phing/classes/phing/tasks/ext/UntarTask.php b/buildscripts/phing/classes/phing/tasks/ext/UntarTask.php new file mode 100644 index 00000000..74777322 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/UntarTask.php @@ -0,0 +1,89 @@ +<?php
+/*
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/ExtractBaseTask.php';
+
+/**
+ * Extracts one or several tar archives using PEAR Archive_Tar
+ *
+ * @author Joakim Bodin <joakim.bodin+phing@gmail.com>
+ * @version $Id: f77612833e0415725e7b816a0515db4a4f0f4c93 $
+ * @package phing.tasks.ext
+ * @since 2.2.0
+ */
+class UntarTask extends ExtractBaseTask {
+
+ /**
+ * Ensures that PEAR lib exists.
+ */
+ public function init() {
+ include_once 'Archive/Tar.php';
+ if (!class_exists('Archive_Tar')) {
+ throw new BuildException("You must have installed the PEAR Archive_Tar class in order to use UntarTask.");
+ }
+ }
+
+ protected function extractArchive(PhingFile $tarfile)
+ {
+ $this->log("Extracting tar file: " . $tarfile->__toString() . ' to ' . $this->todir->__toString(), Project::MSG_INFO);
+
+ try {
+ $tar = $this->initTar($tarfile);
+ if(!$tar->extractModify($this->todir->getAbsolutePath(), $this->removepath)) {
+ throw new BuildException('Failed to extract tar file: ' . $tarfile->getAbsolutePath());
+ }
+ } catch (IOException $ioe) {
+ $msg = "Could not extract tar file: " . $ioe->getMessage();
+ throw new BuildException($msg, $ioe, $this->getLocation());
+ }
+ }
+
+ protected function listArchiveContent(PhingFile $tarfile)
+ {
+ $tar = $this->initTar($tarfile);
+ return $tar->listContent();
+ }
+
+ /**
+ * Init a Archive_Tar class with correct compression for the given file.
+ *
+ * @param PhingFile $tarfile
+ * @return Archive_Tar the tar class instance
+ */
+ private function initTar(PhingFile $tarfile)
+ {
+ $compression = null;
+ $tarfileName = $tarfile->getName();
+ $mode = strtolower(substr($tarfileName, strrpos($tarfileName, '.')));
+
+ $compressions = array(
+ 'gz' => array('.gz', '.tgz',),
+ 'bz2' => array('.bz2',),
+ );
+ foreach ($compressions as $algo => $ext) {
+ if (array_search($mode, $ext) !== false) {
+ $compression = $algo;
+ break;
+ }
+ }
+
+ return new Archive_Tar($tarfile->getAbsolutePath(), $compression);
+ }
+}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/UnzipTask.php b/buildscripts/phing/classes/phing/tasks/ext/UnzipTask.php new file mode 100644 index 00000000..ef7c3e7d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/UnzipTask.php @@ -0,0 +1,77 @@ +<?php +/* + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/ExtractBaseTask.php'; +require_once 'phing/system/io/FileSystem.php'; + +/** + * Extracts one or several zip archives using ZipArchive class. + * + * @author Joakim Bodin <joakim.bodin+phing@gmail.com> + * @author George Miroshnikov <laggy.luke@gmail.com> + * @version $Id: 9c4afd9af5e81250ca6c7afbc6e646c2a0f0148c $ + * @package phing.tasks.ext + */ +class UnzipTask extends ExtractBaseTask +{ + /** + * Extract archive content into $this->todir directory + * @param PhingFile Zip file to extract + * @return boolean + */ + protected function extractArchive(PhingFile $zipfile) + { + $this->log("Extracting zip: " . $zipfile->__toString() . ' to ' . $this->todir->__toString(), Project::MSG_INFO); + + $zip = new ZipArchive(); + + $result = $zip->open($zipfile->getAbsolutePath()); + if (!$result) { + $this->log("Unable to open zipfile " . $zipfile->__toString(), Project::MSG_ERR); + return false; + } + + $result = $zip->extractTo($this->todir->getAbsolutePath()); + if (!$result) { + $this->log("Unable to extract zipfile " . $zipfile->__toString(), Project::MSG_ERR); + return false; + } + + return true; + } + + /** + * List archive content + * @param PhingFile Zip file to list content + * @return array List of files inside $zipfile + */ + protected function listArchiveContent(PhingFile $zipfile) + { + $zip = new ZipArchive(); + $zip->open($zipfile->getAbsolutePath()); + + $content = array(); + for ($i = 0; $i < $zip->numFiles; $i++) { + $content[] = $zip->getNameIndex($i); + } + return $content; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/VersionTask.php b/buildscripts/phing/classes/phing/tasks/ext/VersionTask.php new file mode 100755 index 00000000..b8268870 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/VersionTask.php @@ -0,0 +1,217 @@ +<?php +/* + * $Id: 7fb6793b55e9c1c8c7b3cd8a87b694d720b32749 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ +require_once 'phing/Task.php'; + +/** + * VersionTask + * + * Increments a three-part version number from a given file + * and writes it back to the file. + * Incrementing is based on given releasetype, which can be one + * of Major, Minor and Bugfix. + * Resulting version number is also published under supplied property. + * + * @author Mike Wittje <mw@mike.wittje.de> + * @version $Id: 7fb6793b55e9c1c8c7b3cd8a87b694d720b32749 $ $Rev $Id$ $Author$ + * @package phing.tasks.ext + */ +class VersionTask extends Task +{ + /** + * Property for Releasetype + * @var string $releasetype + */ + private $releasetype; + + /** + * Property for File + * @var PhingFile file + */ + private $file; + + /** + * Property to be set + * @var string $property + */ + private $property; + + /* Allowed Releastypes */ + const RELEASETYPE_MAJOR = 'MAJOR'; + const RELEASETYPE_MINOR = 'MINOR'; + const RELEASETYPE_BUGFIX = 'BUGFIX'; + + /** + * Set Property for Releasetype (Minor, Major, Bugfix) + * @param string $releasetype + */ + public function setReleasetype($releasetype) + { + $this->releasetype = strtoupper($releasetype); + } + + /** + * Set Property for File containing versioninformation + * @param PhingFile $file + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Set name of property to be set + * @param $property + * @return void + */ + public function setProperty($property) + { + $this->property = $property; + } + + /** + * Main-Method for the Task + * + * @return void + * @throws BuildException + */ + public function main() + { + // check supplied attributes + $this->checkReleasetype(); + $this->checkFile(); + $this->checkProperty(); + + // read file + $filecontent = trim(file_get_contents($this->file)); + + // get new version + $newVersion = $this->getVersion($filecontent); + + // write new Version to file + file_put_contents($this->file, $newVersion . "\n"); + + // publish new version number as property + $this->project->setProperty($this->property, $newVersion); + + } + + /** + * Returns new version number corresponding to Release type + * + * @param string $filecontent + * @return string + */ + private function getVersion($filecontent) + { + // init + $newVersion = ''; + + // Extract version + list($major, $minor, $bugfix) = explode(".", $filecontent); + + // Return new version number + switch ($this->releasetype) { + case self::RELEASETYPE_MAJOR: + $newVersion = sprintf("%d.%d.%d", ++$major, + 0, + 0); + break; + + case self::RELEASETYPE_MINOR: + $newVersion = sprintf("%d.%d.%d", $major, + ++$minor, + 0); + break; + + case self::RELEASETYPE_BUGFIX: + $newVersion = sprintf("%d.%d.%d", $major, + $minor, + ++$bugfix); + break; + } + + return $newVersion; + } + + + /** + * checks releasetype attribute + * @return void + * @throws BuildException + */ + private function checkReleasetype() + { + // check Releasetype + if (is_null($this->releasetype)) { + throw new BuildException('releasetype attribute is required', $this->location); + } + // known releasetypes + $releaseTypes = array( + self::RELEASETYPE_MAJOR, + self::RELEASETYPE_MINOR, + self::RELEASETYPE_BUGFIX + ); + + if (!in_array($this->releasetype, $releaseTypes)) { + throw new BuildException(sprintf('Unknown Releasetype %s..Must be one of Major, Minor or Bugfix', + $this->releasetype), $this->location); + } + } + + /** + * checks file attribute + * @return void + * @throws BuildException + */ + private function checkFile() + { + // check File + if ($this->file === null || + strlen($this->file) == 0) { + throw new BuildException('You must specify a file containing the version number', $this->location); + } + + $content = file_get_contents($this->file); + if (strlen($content) == 0) { + throw new BuildException(sprintf('Supplied file %s is empty', $this->file), $this->location); + } + + // check for three-part number + $split = explode('.', $content); + if (count($split) !== 3) { + throw new BuildException('Unknown version number format', $this->location); + } + + } + + /** + * checks property attribute + * @return void + * @throws BuildException + */ + private function checkProperty() + { + if (is_null($this->property) || + strlen($this->property) === 0) { + throw new BuildException('Property for publishing version number is not set', $this->location); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php index 866e954d..15200d37 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php @@ -1,10 +1,31 @@ <?php +/* + * $Id: 6261b2f19844b353c379c46daf3ffb13b7a2ddb8 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + require_once 'phing/Task.php'; /** * A XML lint task. Checking syntax of one or more XML files against an XML Schema using the DOM extension. * * @author Knut Urdalen <knut.urdalen@telio.no> + * @version $Id: 6261b2f19844b353c379c46daf3ffb13b7a2ddb8 $ * @package phing.tasks.ext */ class XmlLintTask extends Task { @@ -12,6 +33,9 @@ class XmlLintTask extends Task { protected $file; // the source file (from xml attribute) protected $schema; // the schema file (from xml attribute) protected $filesets = array(); // all fileset objects assigned to this task + protected $useRNG = false; + + protected $haltonfailure = true; /** * File to be performed syntax check on @@ -31,26 +55,42 @@ class XmlLintTask extends Task { $this->schema = $schema; } + + /** + * Use RNG instead of DTD schema validation + * + * @param bool $bool + */ + public function setUseRNG($bool) { + $this->useRNG = (boolean)$bool; + } + + /** * Nested creator, creates a FileSet for this task * * @return FileSet The created fileset object */ - function createFileSet() { + public function createFileSet() { $num = array_push($this->filesets, new FileSet()); return $this->filesets[$num-1]; } + + /** + * Sets the haltonfailure attribute + * + * @param bool $haltonfailure + */ + public function setHaltonfailure($haltonfailure) { + $this->haltonfailure = (bool) $haltonfailure; + } /** * Execute lint check against PhingFile or a FileSet */ public function main() { - if(!isset($this->schema)) { - throw new BuildException("Missing attribute 'schema'"); - } - $schema = $this->schema->getPath(); - if(!file_exists($schema)) { - throw new BuildException("File not found: ".$schema); + if(isset($this->schema) && !file_exists($this->schema->getPath())) { + throw new BuildException("Schema file not found: ".$this->schema->getPath()); } if(!isset($this->file) and count($this->filesets) == 0) { throw new BuildException("Missing either a nested fileset or attribute 'file' set"); @@ -62,16 +102,24 @@ class XmlLintTask extends Task { } else { // process filesets $project = $this->getProject(); foreach($this->filesets as $fs) { - $ds = $fs->getDirectoryScanner($project); - $files = $ds->getIncludedFiles(); - $dir = $fs->getDir($this->project)->getPath(); - foreach($files as $file) { - $this->lint($dir.DIRECTORY_SEPARATOR.$file); - } + $ds = $fs->getDirectoryScanner($project); + $files = $ds->getIncludedFiles(); + $dir = $fs->getDir($this->project)->getPath(); + foreach($files as $file) { + $this->lint($dir.DIRECTORY_SEPARATOR.$file); + } } } restore_error_handler(); } + + protected function logError($message) { + if ($this->haltonfailure) { + throw new BuildException($message); + } else { + $this->log($message, Project::MSG_ERR); + } + } /** * Performs validation @@ -81,19 +129,35 @@ class XmlLintTask extends Task { */ protected function lint($file) { if(file_exists($file)) { - if(is_readable($file)) { - $dom = new DOMDocument(); - $dom->load($file); - if($dom->schemaValidate($this->schema->getPath())) { - $this->log($file.' validated', PROJECT_MSG_INFO); - } else { - $this->log($file.' fails to validate (See messages above)', PROJECT_MSG_ERR); - } + if(is_readable($file)) { + $dom = new DOMDocument(); + if ($dom->load($file) === false) { + $error = libxml_get_last_error(); + $this->logError($file.' is not well-formed (See messages above)'); + } else { + if(isset($this->schema)) { + if( $this->useRNG ) { + if($dom->relaxNGValidate($this->schema->getPath())) { + $this->log($file.' validated with RNG grammar', Project::MSG_INFO); + } else { + $this->logError($file.' fails to validate (See messages above)'); + } + } else { + if($dom->schemaValidate($this->schema->getPath())) { + $this->log($file.' validated with schema', Project::MSG_INFO); + } else { + $this->logError($file.' fails to validate (See messages above)'); + } + } + } else { + $this->log($file.' is well-formed (not validated due to missing schema specification)', Project::MSG_INFO); + } + } } else { - throw new BuildException('Permission denied: '.$file); + $this->logError('Permission denied to read file: '.$file); } } else { - throw new BuildException('File not found: '.$file); + $this->logError('File not found: '.$file); } } @@ -108,9 +172,8 @@ class XmlLintTask extends Task { public function errorHandler($level, $message, $file, $line, $context) { $matches = array(); preg_match('/^.*\(\): (.*)$/', $message, $matches); - $this->log($matches[1], PROJECT_MSG_ERR); + $this->log($matches[1], Project::MSG_ERR); } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/XmlPropertyTask.php b/buildscripts/phing/classes/phing/tasks/ext/XmlPropertyTask.php new file mode 100755 index 00000000..d32cd78e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/XmlPropertyTask.php @@ -0,0 +1,273 @@ +<?php + +/* + * $Id: c7a3e7eff0b94828f9ec634c3612d89f2740fead $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/tasks/system/PropertyTask.php'; + +/** + * Task for setting properties from an XML file in buildfiles. + * + * @author Jonathan Bond-Caron <jbondc@openmv.com> + * @version $Id: c7a3e7eff0b94828f9ec634c3612d89f2740fead $ + * @package phing.tasks.ext + * @since 2.4.0 + * @link http://ant.apache.org/manual/CoreTasks/xmlproperty.html + */ +class XmlPropertyTask extends PropertyTask { + + private $_keepRoot = true; + private $_collapseAttr = false; + private $_delimiter = ','; + private $_required = false; + + /** Set a file to use as the source for properties. */ + public function setFile($file) { + if (is_string($file)) { + $file = new PhingFile($file); + } + $this->file = $file; + } + + /** Get the PhingFile that is being used as property source. */ + public function getFile() { + return $this->file; + } + + /** + * Prefix to apply to properties loaded using <code>file</code>. + * A "." is appended to the prefix if not specified. + * @param string $prefix prefix string + * @return void + * @since 2.0 + */ + public function setPrefix($prefix) { + $this->prefix = $prefix; + if (!StringHelper::endsWith(".", $prefix)) { + $this->prefix .= "."; + } + } + + /** + * @return string + * @since 2.0 + */ + public function getPrefix() { + return $this->prefix; + } + + /** + * Keep the xml root tag as the first value in the property name + * + * @param bool $yesNo + */ + public function setKeepRoot($yesNo) { + $this->_keepRoot = (bool)$yesNo; + } + + /** + * @return bool + */ + public function getKeepRoot() { + return $this->_keepRoot; + } + + /** + * Treat attributes as nested elements. + * + * @param bool $yesNo + */ + public function setCollapseAttributes($yesNo) { + $this->_collapseAttr = (bool)$yesNo; + } + + /** + * @return bool + */ + public function getCollapseAttributes() { + return $this->_collapseAttr; + } + + /** + * Delimiter for splitting multiple values. + * + * @param string $d + */ + public function setDelimiter($d) { + $this->_delimiter = $d; + } + + /** + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } + + /** + * File required or not. + * + * @param string $d + */ + public function setRequired($d) { + $this->_required = $d; + } + + /** + * @return string + */ + public function getRequired() { + return $this->_required; + } + + /** + * set the property in the project to the value. + * if the task was give a file or env attribute + * here is where it is loaded + */ + public function main() { + + if ($this->file === null ) { + throw new BuildException("You must specify file to load properties from", $this->getLocation()); + } + + $this->loadFile($this->file); + } + + /** + * load properties from an XML file. + * @param PhingFile $file + */ + protected function loadFile(PhingFile $file) { + $props = new Properties(); + $this->log("Loading ". $file->getAbsolutePath(), Project::MSG_INFO); + try { // try to load file + if ($file->exists()) { + + $this->addProperties($this->_getProperties($file)); + + } else { + if ($this->getRequired()){ + throw new BuildException("Could not load required properties file.", $ioe); + } else { + $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", Project::MSG_WARN); + } + } + } catch (IOException $ioe) { + throw new BuildException("Could not load properties from file.", $ioe); + } + } + + /** + * Parses an XML file and returns properties + * + * @param string $filePath + * + * @return Properties + */ + protected function _getProperties($filePath) { + + // load() already made sure that file is readable + // but we'll double check that when reading the file into + // an array + + if (($lines = @file($filePath)) === false) { + throw new IOException("Unable to parse contents of $filePath"); + } + + $prop = new Properties; + + $xml = simplexml_load_file($filePath); + + if($xml === false) + throw new IOException("Unable to parse XML file $filePath"); + + $path = array(); + + if($this->_keepRoot) { + $path[] = dom_import_simplexml($xml)->tagName; + + $prefix = implode('.', $path); + + if (!empty($prefix)) + $prefix .= '.'; + + // Check for attributes + foreach($xml->attributes() as $attribute => $val) { + if($this->_collapseAttr) + $prop->setProperty($prefix . "$attribute", (string)$val); + else + $prop->setProperty($prefix . "($attribute)", (string)$val); + } + } + + $this->_addNode($xml, $path, $prop); + + return $prop; + } + + /** + * Adds an XML node + * + * @param SimpleXMLElement $node + * @param array $path Path to this node + * @param Properties $prop Properties will be added as they are found (by reference here) + * + * @return void + */ + protected function _addNode($node, $path, $prop) { + foreach($node as $tag => $value) { + + $prefix = implode('.', $path); + + if (!empty($prefix) > 0) + $prefix .= '.'; + + // Check for attributes + foreach($value->attributes() as $attribute => $val) { + if($this->_collapseAttr) + $prop->setProperty($prefix . "$tag.$attribute", (string)$val); + else + $prop->setProperty($prefix . "$tag($attribute)", (string)$val); + } + + // Add tag + if(count($value->children())) { + $this->_addNode($value, array_merge($path, array($tag)), $prop); + } else { + $val = (string)$value; + + /* Check for * and ** on 'exclude' and 'include' tag / ant seems to do this? could use FileSet here + if($tag == 'exclude') { + }*/ + + // When property already exists, i.e. multiple xml tag + // <project> + // <exclude>file/a.php</exclude> + // <exclude>file/a.php</exclude> + // </project> + // + // Would be come project.exclude = file/a.php,file/a.php + $p = empty($prefix) ? $tag : $prefix . $tag; + $prop->append($p, (string)$val, $this->_delimiter); + } + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php b/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php index 490ee797..5093fabe 100644 --- a/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php @@ -1,4 +1,24 @@ <?php +/* + * $Id: 5b7e3fb304bb5f406c919407d6881449a70b8a28 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + require_once 'phing/Task.php'; /** @@ -6,7 +26,7 @@ require_once 'phing/Task.php'; * * Available warnings: * <b>zend-error</b> - %s(line %d): %s - * <b>oneline-comment</b> - One-line comment ends with ?> tag. + * <b>oneline-comment</b> - One-line comment ends with tag. * <b>bool-assign</b> - Assignment seen where boolean expression is expected. Did you mean '==' instead of '='? * <b>bool-print</b> - Print statement used when boolean expression is expected. * <b>bool-array</b> - Array used when boolean expression is expected. @@ -38,126 +58,150 @@ require_once 'phing/Task.php'; * <b>empty-cond</b> - Condition without a body * <b>expr-unused</b> - Expression result is never used * - * @author Knut Urdalen <knut.urdalen@telio.no> + * @author Knut Urdalen <knut.urdalen@gmail.com> + * @version $Id: 5b7e3fb304bb5f406c919407d6881449a70b8a28 $ * @package phing.tasks.ext */ -class ZendCodeAnalyzerTask extends Task { - - protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary - protected $file = ""; // the source file (from xml attribute) - protected $filesets = array(); // all fileset objects assigned to this task - protected $warnings = array(); - protected $counter = 0; - protected $disable = array(); - protected $enable = array(); - - /** - * File to be analyzed - * - * @param PhingFile $file - */ - public function setFile(PhingFile $file) { - $this->file = $file; - } - - /** - * Path to ZendCodeAnalyzer binary - * - * @param string $analyzerPath - */ - public function setAnalyzerPath($analyzerPath) { - $this->analyzerPath = $analyzerPath; - } - - /** - * Disable warning levels. Seperate warning levels with ',' - * - * @param string $disable - */ - public function setDisable($disable) { - $this->disable = explode(",", $disable); - } - - /** - * Enable warning levels. Seperate warning levels with ',' - * - * @param string $enable - */ - public function setEnable($enable) { - $this->enable = explode(",", $enable); - } - - /** - * Nested creator, creates a FileSet for this task - * - * @return FileSet The created fileset object - */ - function createFileSet() { - $num = array_push($this->filesets, new FileSet()); - return $this->filesets[$num-1]; - } +class ZendCodeAnalyzerTask extends Task +{ + protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary + protected $file = ""; // the source file (from xml attribute) + protected $filesets = array(); // all fileset objects assigned to this task + protected $counter = 0; + protected $disable = array(); + protected $enable = array(); + + private $haltonwarning = false; - /** - * Analyze against PhingFile or a FileSet - */ - public function main() { - if(!isset($this->analyzerPath)) { - throw new BuildException("Missing attribute 'analyzerPath'"); + /** + * File to be analyzed + * + * @param PhingFile $file + */ + public function setFile(PhingFile $file) { + $this->file = $file; } - if(!isset($this->file) and count($this->filesets) == 0) { - throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + + /** + * Path to ZendCodeAnalyzer binary + * + * @param string $analyzerPath + */ + public function setAnalyzerPath($analyzerPath) { + $this->analyzerPath = $analyzerPath; + } + + /** + * Disable warning levels. Seperate warning levels with ',' + * + * @param string $disable + */ + public function setDisable($disable) { + $this->disable = explode(",", $disable); + } + + /** + * Enable warning levels. Seperate warning levels with ',' + * + * @param string $enable + */ + public function setEnable($enable) { + $this->enable = explode(",", $enable); + } + + /** + * Sets the haltonwarning flag + * @param boolean $value + */ + public function setHaltonwarning($value) + { + $this->haltonwarning = $value; } - if($this->file instanceof PhingFile) { - $this->analyze($this->file->getPath()); - } else { // process filesets - $project = $this->getProject(); - foreach($this->filesets as $fs) { - $ds = $fs->getDirectoryScanner($project); - $files = $ds->getIncludedFiles(); - $dir = $fs->getDir($this->project)->getPath(); - foreach($files as $file) { - $this->analyze($dir.DIRECTORY_SEPARATOR.$file); - } - } + /** + * Nested creator, creates a FileSet for this task + * + * @return FileSet The created fileset object + */ + public function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Analyze against PhingFile or a FileSet + */ + public function main() { + if(!isset($this->analyzerPath)) { + throw new BuildException("Missing attribute 'analyzerPath'"); + } + + if(!isset($this->file) and count($this->filesets) == 0) { + throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + } + + if($this->file instanceof PhingFile) { + $this->analyze($this->file->getPath()); + } else { // process filesets + $project = $this->getProject(); + + foreach($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $files = $ds->getIncludedFiles(); + $dir = $fs->getDir($this->project)->getPath(); + + foreach($files as $file) { + $this->analyze($dir.DIRECTORY_SEPARATOR.$file); + } + } + } + + $this->log("Number of findings: ".$this->counter, Project::MSG_INFO); } - $this->log("Number of findings: ".$this->counter, PROJECT_MSG_INFO); - } - /** - * Analyze file - * - * @param string $file - * @return void - */ - protected function analyze($file) { - if(file_exists($file)) { - if(is_readable($file)) { - - // Construct shell command - $cmd = $this->analyzerPath." "; - foreach($this->enable as $enable) { // Enable warning levels - $cmd .= " --enable $enable "; - } - foreach($this->disable as $disable) { // Disable warning levels - $cmd .= " --disable $disable "; - } - $cmd .= "$file 2>&1"; - - // Execute command - $result = shell_exec($cmd); - $result = explode("\n", $result); - for($i=2, $size=count($result); $i<($size-1); $i++) { - $this->counter++; - $this->log($result[$i], PROJECT_MSG_WARN); - } - } else { - throw new BuildException('Permission denied: '.$file); - } - } else { - throw new BuildException('File not found: '.$file); + /** + * Analyze file + * + * @param string $file + * @return void + */ + protected function analyze($file) { + if(file_exists($file)) { + if(is_readable($file)) { + // Construct shell command + $cmd = $this->analyzerPath." "; + + foreach($this->enable as $enable) { // Enable warning levels + $cmd .= " --enable $enable "; + } + + foreach($this->disable as $disable) { // Disable warning levels + $cmd .= " --disable $disable "; + } + + $cmd .= "$file 2>&1"; + + // Execute command + $result = shell_exec($cmd); + $result = explode("\n", $result); + + for($i=2, $size=count($result); $i<($size-1); $i++) { + $this->counter++; + $this->log($result[$i], Project::MSG_WARN); + } + + $total = count($result) - 3; + + if ($total > 0 && $this->haltonwarning) { + throw new BuildException('zendcodeanalyzer detected ' . $total . ' warning' . ($total > 1 ? 's' : '') . ' in ' . $file); + } + } + else + { + throw new BuildException('Permission denied: '.$file); + } + } else { + throw new BuildException('File not found: '.$file); + } } - } } - -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php b/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php index 33ef16ae..72bf42fd 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ZipTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 6997b3f3abffedf1b2efabc40c3b2d012b2379cb $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,31 +23,48 @@ require_once 'phing/tasks/system/MatchingTask.php'; include_once 'phing/util/SourceFileScanner.php'; include_once 'phing/mappers/MergeMapper.php'; include_once 'phing/util/StringHelper.php'; -include_once 'phing/lib/Zip.php'; /** - * Creates a zip archive using PEAR Archive_Zip (which is presently unreleased - * and included with Phing). + * Creates a zip archive using PHP ZipArchive extension/ * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Revision: 1.2 $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 6997b3f3abffedf1b2efabc40c3b2d012b2379cb $ * @package phing.tasks.ext * @since 2.1.0 */ class ZipTask extends MatchingTask { + /** + * @var PhingFile + */ private $zipFile; + + /** + * @var PhingFile + */ private $baseDir; - + + /** + * Whether to include empty dirs in the archive. + */ + private $includeEmpty = true; + private $filesets = array(); private $fileSetFiles = array(); /** + * File path prefix in zip archive + * + * @var string + */ + private $prefix = null; + + /** * Add a new fileset. * @return FileSet */ public function createFileSet() { - $this->fileset = new FileSet(); + $this->fileset = new ZipFileSet(); $this->filesets[] = $this->fileset; return $this->fileset; } @@ -69,6 +86,27 @@ class ZipTask extends MatchingTask { } /** + * Sets the file path prefix for file in the zip file. + * + * @param string $prefix Prefix + * + * @return void + */ + public function setPrefix($prefix) { + $this->prefix = $prefix; + } + + /** + * Set the include empty dirs flag. + * @param boolean Flag if empty dirs should be tarred too + * @return void + * @access public + */ + public function setIncludeEmptyDirs($bool) { + $this->includeEmpty = (boolean) $bool; + } + + /** * do the work * @throws BuildException */ @@ -93,13 +131,16 @@ class ZipTask extends MatchingTask { try { if ($this->baseDir !== null) { if (!$this->baseDir->exists()) { - throw new BuildException("basedir does not exist!", $this->getLocation()); + throw new BuildException("basedir '" . (string) $this->baseDir . "' does not exist!", $this->getLocation()); + } + + if (empty($this->filesets)) + { + // add the main fileset to the list of filesets to process. + $mainFileSet = new ZipFileSet($this->fileset); + $mainFileSet->setDir($this->baseDir); + $this->filesets[] = $mainFileSet; } - - // add the main fileset to the list of filesets to process. - $mainFileSet = new FileSet($this->fileset); - $mainFileSet->setDir($this->baseDir); - $this->filesets[] = $mainFileSet; } if (empty($this->filesets)) { @@ -112,8 +153,7 @@ class ZipTask extends MatchingTask { // fileset $upToDate = true; foreach($this->filesets as $fs) { - $ds = $fs->getDirectoryScanner($this->project); - $files = $ds->getIncludedFiles(); + $files = $fs->getFiles($this->project, $this->includeEmpty); if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) { $upToDate = false; } @@ -125,33 +165,47 @@ class ZipTask extends MatchingTask { } if ($upToDate) { - $this->log("Nothing to do: " . $this->zipFile->__toString() . " is up to date.", PROJECT_MSG_INFO); + $this->log("Nothing to do: " . $this->zipFile->__toString() . " is up to date.", Project::MSG_INFO); return; } - $this->log("Building zip: " . $this->zipFile->__toString(), PROJECT_MSG_INFO); + $this->log("Building zip: " . $this->zipFile->__toString(), Project::MSG_INFO); - $zip = new Archive_Zip($this->zipFile->getAbsolutePath()); + $zip = new ZipArchive(); + $res = $zip->open($this->zipFile->getAbsolutePath(), ZIPARCHIVE::CREATE); - foreach($this->filesets as $fs) { - $ds = $fs->getDirectoryScanner($this->project); - $files = $ds->getIncludedFiles(); - - // FIXME - // Current model is only adding directories implicitly. This - // won't add any empty directories. Perhaps modify FileSet::getFiles() - // to also include empty directories. Not high priority, since non-inclusion - // of empty dirs is probably not unexpected behavior for ZipTask. - $fsBasedir = $fs->getDir($this->project); + if ($res !== true) + { + throw new Exception("ZipArchive::open() failed with code " . $res); + } + + foreach($this->filesets as $fs) { + $fsBasedir = (null != $this->baseDir) ? $this->baseDir : + $fs->getDir($this->project); + + $files = $fs->getFiles($this->project, $this->includeEmpty); + $filesToZip = array(); for ($i=0, $fcount=count($files); $i < $fcount; $i++) { $f = new PhingFile($fsBasedir, $files[$i]); - $filesToZip[] = $f->getAbsolutePath(); - } - $zip->add($filesToZip, array('remove_path' => $fsBasedir->getPath())); + + $pathInZip = $this->prefix + . $f->getPathWithoutBase($fsBasedir); + + $pathInZip = str_replace('\\', '/', $pathInZip); + + if ($f->isDirectory()) { + if ($pathInZip != '.') { + $zip->addEmptyDir($pathInZip); + } + } else { + $zip->addFile($f->getPath(), $pathInZip); + } + $this->log("Adding " . $f->getPath() . " as " . $pathInZip . " to archive.", Project::MSG_VERBOSE); + } } - - + + $zip->close(); } catch (IOException $ioe) { $msg = "Problem creating ZIP: " . $ioe->getMessage(); $this->filesets = $savedFileSets; @@ -174,3 +228,74 @@ class ZipTask extends MatchingTask { } } + + + + +/** + * This is a FileSet with the to specify permissions. + * + * Permissions are currently not implemented by PEAR Archive_Tar, + * but hopefully they will be in the future. + * + * @package phing.tasks.ext + */ +class ZipFileSet extends FileSet { + + private $files = null; + + /** + * Get a list of files and directories specified in the fileset. + * @return array a list of file and directory names, relative to + * the baseDir for the project. + */ + public function getFiles(Project $p, $includeEmpty = true) { + + if ($this->files === null) { + + $ds = $this->getDirectoryScanner($p); + $this->files = $ds->getIncludedFiles(); + + // build a list of directories implicitly added by any of the files + $implicitDirs = array(); + foreach($this->files as $file) { + $implicitDirs[] = dirname($file); + } + + $incDirs = $ds->getIncludedDirectories(); + + // we'll need to add to that list of implicit dirs any directories + // that contain other *directories* (and not files), since otherwise + // we get duplicate directories in the resulting tar + foreach($incDirs as $dir) { + foreach($incDirs as $dircheck) { + if (!empty($dir) && $dir == dirname($dircheck)) { + $implicitDirs[] = $dir; + } + } + } + + $implicitDirs = array_unique($implicitDirs); + + $emptyDirectories = array(); + + if ($includeEmpty) { + // Now add any empty dirs (dirs not covered by the implicit dirs) + // to the files array. + + foreach($incDirs as $dir) { // we cannot simply use array_diff() since we want to disregard empty/. dirs + if ($dir != "" && $dir != "." && !in_array($dir, $implicitDirs)) { + // it's an empty dir, so we'll add it. + $emptyDirectories[] = $dir; + } + } + } // if $includeEmpty + + $this->files = array_merge($implicitDirs, $emptyDirectories, $this->files); + sort($this->files); + } // if ($this->files===null) + + return $this->files; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/apigen/ApiGenTask.php b/buildscripts/phing/classes/phing/tasks/ext/apigen/ApiGenTask.php new file mode 100644 index 00000000..d8438b3e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/apigen/ApiGenTask.php @@ -0,0 +1,439 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * ApiGen task (http://apigen.org). + * + * @package phing.tasks.ext.apigen + * @author Martin Srank <martin@smasty.net> + * @author Jaroslav HanslÃk <kukulich@kukulich.cz> + * @since 2.4.10 + */ +class ApiGenTask extends Task +{ + /** + * Default ApiGen executable name. + * + * @var string + */ + private $executable = 'apigen'; + + /** + * Default options for ApiGen. + * + * @var array + */ + private $options = array( + 'progressbar' => false, + 'colors' => false, + 'update-check' => false + ); + + /** + * Sets the ApiGen executable name. + * + * @param string $executable + */ + public function setExecutable($executable) + { + $this->executable = (string) $executable; + } + + /** + * Sets the config file name. + * + * @param string $config + */ + public function setConfig($config) + { + $this->options['config'] = (string) $config; + } + + /** + * Sets source files or directories. + * + * @param string $source + */ + public function setSource($source) + { + $this->options['source'] = explode(',', $source); + } + + /** + * Sets the destination directory. + * + * @param string $destination + */ + public function setDestination($destination) + { + $this->options['destination'] = (string) $destination; + } + + /** + * Sets list of allowed file extensions. + * + * @param string $extensions + */ + public function setExtensions($extensions) + { + $this->options['extensions'] = explode(',', $extensions); + } + + /** + * Sets masks (case sensitive) to exclude files or directories from processing. + * + * @param string $exclude + */ + public function setExclude($exclude) + { + $this->options['exclude'] = explode(',', $exclude); + } + + /** + * Sets masks to exclude elements from documentation generating. + * + * @param string $skipDocPath + */ + public function setSkipDocPath($skipDocPath) + { + $this->options['skip-doc-path'] = explode(',', $skipDocPath); + } + + /** + * Sets a name prefix to exclude elements from documentation generating. + * + * @param string $skipDocPrefix + */ + public function setSkipDocPrefix($skipDocPrefix) + { + $this->options['skip-doc-prefix'] = explode(',', $skipDocPrefix); + } + + /** + * Sets the character set of source files. + * + * @param string $charset + */ + public function setCharset($charset) + { + $this->options['charset'] = explode(',', $charset); + } + + /** + * Sets the main project name prefix. + * + * @param string $main + */ + public function setMain($main) + { + $this->options['main'] = (string) $main; + } + + /** + * Sets the title of generated documentation. + * + * @param string $title + */ + public function setTitle($title) + { + $this->options['title'] = (string) $title; + } + + /** + * Sets the documentation base URL. + * + * @param string $baseUrl + */ + public function setBaseUrl($baseUrl) + { + $this->options['base-url'] = (string) $baseUrl; + } + + /** + * Sets the Google Custom Search ID. + * + * @param string $googleCseId + */ + public function setGoogleCseId($googleCseId) + { + $this->options['google-cse-id'] = (string) $googleCseId; + } + + /** + * Sets the Google Custom Search label. + * + * @param string $googleCseLabel + */ + public function setGoogleCseLabel($googleCseLabel) + { + $this->options['google-cse-label'] = (string) $googleCseLabel; + } + + /** + * Sets the Google Analytics tracking code. + * + * @param string $googleAnalytics + */ + public function setGoogleAnalytics($googleAnalytics) + { + $this->options['google-analytics'] = (string) $googleAnalytics; + } + + /** + * Sets the template config file name. + * + * @param string $templateConfig + */ + public function setTemplateConfig($templateConfig) + { + $this->options['template-config'] = (string) $templateConfig; + } + + /** + * Sets a list of HTML tags allowed in the documentation. + * + * @param string $allowedHtml + */ + public function setAllowedHtml($allowedHtml) + { + $this->options['allowed-html'] = (string) $allowedHtml; + } + + /** + * Sets how elements should be grouped in the menu. + * + * @param string $groups + */ + public function setGroups($groups) + { + $this->options['groups'] = (string) $groups; + } + + /** + * Sets element types for search input autocomplete. + * + * @param string $autocomplete + */ + public function setAutocomplete($autocomplete) + { + $this->options['autocomplete'] = (string) $autocomplete; + } + + /** + * Sets the element access levels. + * + * Documentation only for methods and properties with the given access level will be generated. + * + * @param string $accessLevels + */ + public function setAccessLevels($accessLevels) + { + $this->options['access-levels'] = (string) $accessLevels; + } + + /** + * Sets if documentation for elements marked as internal and internal documentation parts should be generated. + * + * @param boolean $internal + */ + public function setInternal($internal) + { + $this->options['internal'] = (bool) $internal; + } + + /** + * Sets if documentation for PHP internal classes should be generated. + * + * @param boolean $php + */ + public function setPhp($php) + { + $this->options['php'] = (bool) $php; + } + + /** + * Sets if tree view of classes, interfaces, traits and exceptions should be generated. + * + * @param boolean $tree + */ + public function setTree($tree) + { + $this->options['tree'] = (bool) $tree; + } + + /** + * Sets if documentation for deprecated elements should be generated. + * + * @param boolean $deprecated + */ + public function setDeprecated($deprecated) + { + $this->options['deprecated'] = (bool) $deprecated; + } + + /** + * Sets if documentation of tasks should be generated. + * + * @param boolean $todo + */ + public function setTodo($todo) + { + $this->options['todo'] = (bool) $todo; + } + + /** + * Sets if highlighted source code files should be generated. + * + * @param boolean $sourceCode + */ + public function setSourceCode($sourceCode) + { + $this->options['source-code'] = (bool) $sourceCode; + } + + /** + * Sets if a link to download documentation as a ZIP archive should be generated. + * + * @param boolean $download + */ + public function setDownload($download) + { + $this->options['download'] = (bool) $download; + } + + /** + * Sets a file name for checkstyle report of poorly documented elements. + * + * @param string $report + */ + public function setReport($report) + { + $this->options['report'] = (string) $report; + } + + /** + * Sets if the destination directory should be wiped out first. + * + * @param boolean $wipeout + */ + public function setWipeout($wipeout) + { + $this->options['wipeout'] = (bool) $wipeout; + } + + /** + * Enables/disables scaning and generating messages. + * + * @param boolean $quiet + */ + public function setQuiet($quiet) + { + $this->options['quiet'] = (bool) $quiet; + } + + /** + * Enables/disables the check for ApiGen updates. + * + * @param boolean $updateCheck + */ + public function setUpdateCheck($updateCheck) + { + $this->options['update-check'] = (bool) $updateCheck; + } + + /** + * Enables/disables the debug mode. + * + * @param boolean $debug + */ + public function setDebug($debug) + { + $this->options['debug'] = (bool) $debug; + } + + /** + * Runs ApiGen. + * + * @throws BuildException If something is wrong. + * @see Task::main() + */ + public function main() + { + if ('apigen' !== $this->executable && !is_file($this->executable)) { + throw new BuildException(sprintf('Executable %s not found', $this->executable), $this->getLocation()); + } + + if (!empty($this->options['config'])) { + // Config check + if (!is_file($this->options['config'])) { + throw new BuildException(sprintf('Config file %s doesn\'t exist', $this->options['config']), $this->getLocation()); + } + } else { + // Source check + if (empty($this->options['source'])) { + throw new BuildException('Source is not set', $this->getLocation()); + } + // Destination check + if (empty($this->options['destination'])) { + throw new BuildException('Destination is not set', $this->getLocation()); + } + } + + // Source check + if (!empty($this->options['source'])) { + foreach ($this->options['source'] as $source) { + if (!file_exists($source)) { + throw new BuildException(sprintf('Source %s doesn\'t exist', $source), $this->getLocation()); + } + } + } + + // Execute ApiGen + exec(escapeshellcmd($this->executable) . ' ' . $this->constructArguments(), $output, $return); + + $logType = 0 === $return ? Project::MSG_INFO : Project::MSG_ERR; + foreach ($output as $line) { + $this->log($line, $logType); + } + } + + /** + * Generates command line arguments for the ApiGen executable. + * + * @return string + */ + protected function constructArguments() + { + $args = array(); + foreach ($this->options as $option => $value) { + if (is_bool($value)) { + $args[] = '--' . $option . '=' . ($value ? 'yes' : 'no'); + } elseif (is_array($value)) { + foreach ($value as $v) { + $args[] = '--' . $option . '=' . escapeshellarg($v); + } + } else { + $args[] = '--' . $option . '=' . escapeshellarg($value); + } + } + return implode(' ', $args); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php index 99bcc7c4..71eba460 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php @@ -1,6 +1,6 @@ <?php /** - * $Id: CoverageMerger.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 83f3748d0690f9fc69c2618191f272e5661c0501 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,104 +24,131 @@ require_once 'phing/system/util/Properties.php'; /** * Saves coverage output of the test to a specified database * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageMerger.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 83f3748d0690f9fc69c2618191f272e5661c0501 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageMerger { - private static function mergeCodeCoverage($left, $right) - { - $coverageMerged = array(); - - 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); - } -} -?>
\ No newline at end of file + private static function mergeCodeCoverage($left, $right) + { + $coverageMerged = array(); + + reset($left); + reset($right); + + while (current($left) !== false && current($right) !== false) { + $linenr_left = key($left); + $linenr_right = key($right); + + if ($linenr_left < $linenr_right) { + $coverageMerged[$linenr_left] = current($left); + next($left); + } elseif ($linenr_right < $linenr_left) { + $coverageMerged[$linenr_right] = current($right); + next($right); + } else { + if ((current($left) < 0) || (current($right) < 0)) { + $coverageMerged[$linenr_right] = current($right); + } else { + $coverageMerged[$linenr_right] = current($left) + current($right); + } + + next($left); + next($right); + } + } + + while (current($left) !== false) { + $coverageMerged[key($left)] = current($left); + next($left); + } + + while (current($right) !== false) { + $coverageMerged[key($right)] = current($right); + next($right); + } + + return $coverageMerged; + } + + /** + * @param Project $project + * @return Properties + * @throws BuildException + */ + protected static function _getDatabase($project) + { + $coverageDatabase = $project->getProperty('coverage.database'); + + if (!$coverageDatabase) { + throw new BuildException("Property coverage.database is not set - please include coverage-setup in your build file"); + } + + $database = new PhingFile($coverageDatabase); + + $props = new Properties(); + $props->load($database); + + return $props; + } + + public static function getWhiteList($project) + { + $whitelist = array(); + $props = self::_getDatabase($project); + + foreach ($props->getProperties() as $property) { + $data = unserialize($property); + $whitelist[] = $data['fullname']; + } + + return $whitelist; + } + + public static function merge($project, $codeCoverageInformation) + { + $props = self::_getDatabase($project); + + $coverageTotal = $codeCoverageInformation; + + foreach ($coverageTotal as $filename => $data) { + $ignoreLines = PHP_CodeCoverage_Util::getLinesToBeIgnored($filename); + + $lines = array(); + $filename = strtolower($filename); + + if ($props->getProperty($filename) != null) { + foreach ($data as $_line => $_data) { + if (is_array($_data)) { + $count = count($_data); + } else if(isset($ignoreLines[$_line])) { + // line is marked as ignored + $count = 1; + } else if ($_data == -1) { + // not executed + $count = -1; + } else if ($_data == -2) { + // dead code + $count = -2; + } + + $lines[$_line] = $count; + } + + ksort($lines); + + $file = unserialize($props->getProperty($filename)); + $left = $file['coverage']; + + $coverageMerged = CoverageMerger::mergeCodeCoverage($left, $lines); + + $file['coverage'] = $coverageMerged; + $props->setProperty($filename, serialize($file)); + } + } + + $props->store(); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php index 4a78df6f..fd141cb5 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: CoverageMergerTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 324ec42a8015e3b82e90ee3bfaad1bc069fec409 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,65 +28,65 @@ require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; /** * Merges code coverage snippets into a code coverage database * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageMergerTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 324ec42a8015e3b82e90ee3bfaad1bc069fec409 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageMergerTask extends Task { - /** the list of filesets containing the .php filename rules */ - private $filesets = array(); + /** the list of filesets containing the .php filename rules */ + private $filesets = array(); - /** - * Add a new fileset containing the .php files to process - * - * @param FileSet the new fileset containing .php files - */ - function addFileSet(FileSet $fileset) - { - $this->filesets[] = $fileset; - } + /** + * Add a new fileset containing the .php files to process + * + * @param FileSet the new fileset containing .php files + */ + function addFileSet(FileSet $fileset) + { + $this->filesets[] = $fileset; + } - /** - * Iterate over all filesets and return all the filenames. - * - * @return array an array of filenames - */ - private function getFilenames() - { - $files = array(); + /** + * Iterate over all filesets and return all the filenames. + * + * @return array an array of filenames + */ + private function getFilenames() + { + $files = array(); - foreach ($this->filesets as $fileset) - { - $ds = $fileset->getDirectoryScanner($this->project); - $ds->scan(); + foreach ($this->filesets as $fileset) + { + $ds = $fileset->getDirectoryScanner($this->project); + $ds->scan(); - $includedFiles = $ds->getIncludedFiles(); - - foreach ($includedFiles as $file) - { - $fs = new PhingFile(basename($ds->getBaseDir()), $file); - - $files[] = $fs->getAbsolutePath(); - } - } + $includedFiles = $ds->getIncludedFiles(); + + foreach ($includedFiles as $file) + { + $fs = new PhingFile(basename($ds->getBaseDir()), $file); + + $files[] = $fs->getAbsolutePath(); + } + } - return $files; - } - - function main() - { - $files = $this->getFilenames(); - - $this->log("Merging " . count($files) . " coverage files"); + return $files; + } + + function main() + { + $files = $this->getFilenames(); + + $this->log("Merging " . count($files) . " coverage files"); - foreach ($files as $file) - { - $coverageInformation = unserialize(file_get_contents($file)); - - CoverageMerger::merge($this->project, array($coverageInformation)); - } - } + foreach ($files as $file) + { + $coverageInformation = unserialize(file_get_contents($file)); + + CoverageMerger::merge($this->project, array($coverageInformation)); + } + } } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php index 72fa57a7..dbfc3093 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: CoverageReportTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 564bbde3ec5084ed2db570958548af2b9d1c1127 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -23,384 +23,542 @@ require_once 'phing/Task.php'; require_once 'phing/system/io/PhingFile.php'; require_once 'phing/system/io/Writer.php'; require_once 'phing/system/util/Properties.php'; -require_once 'phing/tasks/ext/phpunit2/PHPUnit2Util.php'; +require_once 'phing/tasks/ext/phpunit/PHPUnitUtil.php'; require_once 'phing/tasks/ext/coverage/CoverageReportTransformer.php'; /** * Transforms information in a code coverage database to XML * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageReportTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 564bbde3ec5084ed2db570958548af2b9d1c1127 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageReportTask extends Task { - private $outfile = "coverage.xml"; - - private $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) - { - $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; - - end($coverageInformation); - unset($coverageInformation[key($coverageInformation)]); - - // Strange PHP5 reflection bug, classes without parent class or implemented interfaces seem to start one line off - if ($reflection->getParentClass() == NULL && count($reflection->getInterfaces()) == 0) - { - unset($coverageInformation[$classStartLine + 1]); - } - else - { - unset($coverageInformation[$classStartLine]); - } - - reset($coverageInformation); - - foreach ($methods as $method) - { - // PHP5 reflection considers methods of a parent class to be part of a subclass, we don't - if ($method->getDeclaringClass()->getName() != $reflection->getName()) - { - continue; - } - - // 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 < $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); + 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 = PHPUnitUtil::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); + } + + /** + * Adds a subpackage to their package + * + * @param string $packageName The name of the package + * @param string $subpackageName The name of the subpackage + * + * @author Benjamin Schultz <bschultz@proqrent.de> + * @return void + */ + protected function addSubpackageToPackage($packageName, $subpackageName) + { + $package = $this->getPackageElement($packageName); + $subpackage = $this->getSubpackageElement($subpackageName); + + if ($package === null) { + $package = $this->doc->createElement('package'); + $package->setAttribute('name', $packageName); + $this->doc->documentElement->appendChild($package); + } + + if ($subpackage === null) { + $subpackage = $this->doc->createElement('subpackage'); + $subpackage->setAttribute('name', $subpackageName); + } + + $package->appendChild($subpackage); + } + + /** + * Returns the subpackage element + * + * @param string $subpackageName The name of the subpackage + * + * @author Benjamin Schultz <bschultz@proqrent.de> + * @return DOMNode|null null when no DOMNode with the given name exists + */ + protected function getSubpackageElement($subpackageName) + { + $subpackages = $this->doc->documentElement->getElementsByTagName('subpackage'); + + foreach ($subpackages as $subpackage) { + if ($subpackage->getAttribute('name') == $subpackageName) { + return $subpackage; + } + } + + return null; + } + + /** + * Adds a class to their subpackage + * + * @param string $classname The name of the class + * @param DOMNode $element The dom node to append to the subpackage element + * + * @author Benjamin Schultz <bschultz@proqrent.de> + * @return void + */ + protected function addClassToSubpackage($classname, $element) + { + $subpackageName = PHPUnitUtil::getSubpackageName($classname); + + $subpackage = $this->getSubpackageElement($subpackageName); + + if ($subpackage === null) { + $subpackage = $this->doc->createElement('subpackage'); + $subpackage->setAttribute('name', $subpackageName); + $this->doc->documentElement->appendChild($subpackage); + } + + $subpackage->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 = preg_split("#</?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); + + if (function_exists('mb_check_encoding') && mb_check_encoding($line, 'UTF-8')) { + $lines[$i] = $line; + } + else if (function_exists('mb_convert_encoding')) + { + $lines[$i] = mb_convert_encoding($line, 'UTF-8'); + } + else + { + $lines[$i] = utf8_encode($line); + } + } + + return $lines; + } + } + + protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1) + { + $sourceElement = $this->doc->createElement('sourcefile'); + $sourceElement->setAttribute('name', basename($filename)); + + /** + * Add original/full filename to document + */ + $sourceElement->setAttribute('sourcefile', $filename); + + $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; + } + + /** + * Transforms the coverage information + * + * @param string $filename The filename + * @param array $coverageInformation Array with covergae information + * + * @author Michiel Rook <mrook@php.net> + * @author Benjamin Schultz <bschultz@proqrent.de> + * @return void + */ + protected function transformCoverageInformation($filename, $coverageInformation) + { + $classes = PHPUnitUtil::getDefinedClasses($filename, $this->classpath); + + if (is_array($classes)) + { + foreach ($classes as $classname) + { + $reflection = new ReflectionClass($classname); + + $methods = $reflection->getMethods(); + + $classElement = $this->doc->createElement('class'); + $classElement->setAttribute('name', $reflection->getName()); + + $packageName = PHPUnitUtil::getPackageName($reflection->getName()); + $subpackageName = PHPUnitUtil::getSubpackageName($reflection->getName()); + + if ($subpackageName !== null) { + $this->addSubpackageToPackage($packageName, $subpackageName); + $this->addClassToSubpackage($reflection->getName(), $classElement); + } else { + $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]); + } + + // Remove out-of-bounds info + unset($coverageInformation[0]); + + reset($coverageInformation); + + foreach ($methods as $method) + { + // PHP5 reflection considers methods of a parent class to be part of a subclass, we don't + if ($method->getDeclaringClass()->getName() != $reflection->getName()) + { + continue; + } + + // 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); + } + + $methodCoveredCount = 0; + $methodTotalCount = 0; + + $methodHasCoveredLine = false; + + while ($linenr !== null && $linenr <= $method->getEndLine()) { + $methodTotalCount++; + $methodHasCoveredLine = true; + + // set covered when CODE is other than -1 (not executed) + if ($coverageInformation[$linenr] > 0 || $coverageInformation[$linenr] == -2) { + $methodCoveredCount++; + } + + next($coverageInformation); + $linenr = key($coverageInformation); + } + + if (($methodTotalCount == $methodCoveredCount) && $methodHasCoveredLine) { + $methodscovered++; + } + + $methodcount++; + } + + $statementcount = count(array_filter( + $coverageInformation, + create_function('$var', 'return ($var != -2);') + )); + + $statementscovered = count(array_filter( + $coverageInformation, + create_function('$var', 'return ($var >= 0);') + )); + + $classElement->appendChild($this->transformSourceFile($filename, $coverageInformation, $classStartLine)); + + $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; + + $subpackages = $package->getElementsByTagName('subpackage'); + + foreach ($subpackages as $subpackage) { + $subpackageMethodCount = 0; + $subpackageMethodsCovered = 0; + + $subpackageStatementCount = 0; + $subpackageStatementsCovered = 0; + + $subpackageClasses = $subpackage->getElementsByTagName('class'); + + foreach ($subpackageClasses as $subpackageClass) { + $subpackageMethodCount += $subpackageClass->getAttribute('methodcount'); + $subpackageMethodsCovered += $subpackageClass->getAttribute('methodscovered'); + + $subpackageStatementCount += $subpackageClass->getAttribute('statementcount'); + $subpackageStatementsCovered += $subpackageClass->getAttribute('statementscovered'); + } + + $subpackage->setAttribute('methodcount', $subpackageMethodCount); + $subpackage->setAttribute('methodscovered', $subpackageMethodsCovered); + + $subpackage->setAttribute('statementcount', $subpackageStatementCount); + $subpackage->setAttribute('statementscovered', $subpackageStatementsCovered); + + $subpackage->setAttribute('totalcount', $subpackageMethodCount + $subpackageStatementCount); + $subpackage->setAttribute('totalcovered', $subpackageMethodsCovered + $subpackageStatementsCovered); + } + + $classes = $package->getElementsByTagName('class'); + + foreach ($classes as $class) { + $methodcount += $class->getAttribute('methodcount'); + $methodscovered += $class->getAttribute('methodscovered'); + + $statementcount += $class->getAttribute('statementcount'); + $statementscovered += $class->getAttribute('statementscovered'); + } + + $package->setAttribute('methodcount', $methodcount); + $package->setAttribute('methodscovered', $methodscovered); + + $package->setAttribute('statementcount', $statementcount); + $package->setAttribute('statementscovered', $statementscovered); + + $package->setAttribute('totalcount', $methodcount + $statementcount); + $package->setAttribute('totalcovered', $methodscovered + $statementscovered); + + $totalmethodcount += $methodcount; + $totalmethodscovered += $methodscovered; + + $totalstatementcount += $statementcount; + $totalstatementscovered += $statementscovered; + } + + $this->doc->documentElement->setAttribute('methodcount', $totalmethodcount); + $this->doc->documentElement->setAttribute('methodscovered', $totalmethodscovered); + + $this->doc->documentElement->setAttribute('statementcount', $totalstatementcount); + $this->doc->documentElement->setAttribute('statementscovered', $totalstatementscovered); + + $this->doc->documentElement->setAttribute('totalcount', $totalmethodcount + $totalstatementcount); + $this->doc->documentElement->setAttribute('totalcovered', $totalmethodscovered + $totalstatementscovered); + } + + function main() + { + $coverageDatabase = $this->project->getProperty('coverage.database'); + + if (!$coverageDatabase) + { + throw new BuildException("Property coverage.database is not set - please include coverage-setup in your build file"); + } + + $database = new PhingFile($coverageDatabase); - foreach ($props->keys() as $filename) - { - $file = unserialize($props->getProperty($filename)); + $this->log("Transforming coverage report"); + + $props = new Properties(); + $props->load($database); - $this->transformCoverageInformation($file['fullname'], $file['coverage']); - } - - $this->calculateStatistics(); - - $this->doc->save($this->outfile); + foreach ($props->keys() as $filename) + { + $file = unserialize($props->getProperty($filename)); + + $this->transformCoverageInformation($file['fullname'], $file['coverage']); + } + + $this->calculateStatistics(); - foreach ($this->transformers as $transformer) - { - $transformer->setXmlDocument($this->doc); - $transformer->transform(); - } - } + $this->doc->save($this->outfile); + + foreach ($this->transformers as $transformer) + { + $transformer->setXmlDocument($this->doc); + $transformer->transform(); + } + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php index b7fee32f..cc37800f 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php @@ -1,6 +1,6 @@ <?php /** - * $Id: CoverageReportTransformer.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c1667521b5959687560a1bf015905d627785a3c6 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,94 +28,149 @@ require_once 'phing/util/ExtendedFileStream.php'; * Transform a Phing/Xdebug code coverage xml report. * The default transformation generates an html report in framed style. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageReportTransformer.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: c1667521b5959687560a1bf015905d627785a3c6 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageReportTransformer { - private $task = NULL; - private $styleDir = ""; - private $toDir = ""; - private $document = NULL; - - 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()) + private $task = NULL; + private $styleDir = ""; + + /** + * @var PhingFile + */ + private $toDir = ""; + + private $document = NULL; + + /** title of the project, used in the coverage report */ + private $title = ""; + + /** + * Whether to use the sorttable JavaScript library, defaults to false + * See {@link http://www.kryogenix.org/code/browser/sorttable/)} + * + * @var boolean + */ + private $useSortTable = false; + + function __construct(Task $task) + { + $this->task = $task; + } + + function setStyleDir($styleDir) + { + $this->styleDir = $styleDir; + } + + function setToDir(PhingFile $toDir) + { + $this->toDir = $toDir; + } + + function setXmlDocument($document) + { + $this->document = $document; + } + + /** + * Setter for title parameter + */ + function setTitle($title) { + $this->title = $title; + } + + /** + * Sets whether to use the sorttable JavaScript library, defaults to false + * See {@link http://www.kryogenix.org/code/browser/sorttable/)} + * + * @param boolean $useSortTable + */ + public function setUseSortTable($useSortTable) + { + $this->useSortTable = (boolean) $useSortTable; + } + + function transform() + { + if (!$this->toDir->exists()) { throw new BuildException("Directory '" . $this->toDir . "' does not exist"); } - $xslfile = $this->getStyleSheet(); - - $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; - } + $xslfile = $this->getStyleSheet(); + + $xsl = new DOMDocument(); + $xsl->load($xslfile->getAbsolutePath()); + + $proc = new XSLTProcessor(); + if (defined('XSL_SECPREF_WRITE_FILE')) + { + if (version_compare(PHP_VERSION,'5.4',"<")) + { + ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); + } + else + { + $proc->setSecurityPrefs(XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); + } + } + + $proc->importStyleSheet($xsl); + + ExtendedFileStream::registerStream(); + + $toDir = (string) $this->toDir; + + // urlencode() the path if we're on Windows + if (FileSystem::getFileSystem()->getSeparator() == '\\') { + $toDir = urlencode($toDir); + } + + // no output for the framed report + // it's all done by extension... + $proc->setParameter('', 'output.dir', $toDir); + + $proc->setParameter('', 'output.sorttable', $this->useSortTable); + $proc->setParameter('', 'document.title', $this->title); + $proc->transformToXML($this->document); + + ExtendedFileStream::unregisterStream(); + } + + 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; + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php index 058b891b..889a9042 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: CoverageSetupTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: da84ff4b224cdf3a8061e02d782320ccc492c253 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,136 +28,137 @@ require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; /** * Initializes a code coverage database * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: CoverageSetupTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: da84ff4b224cdf3a8061e02d782320ccc492c253 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageSetupTask extends Task { - /** the list of filesets containing the .php filename rules */ - private $filesets = array(); - - /** the 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)); - } - } + /** the list of filesets containing the .php filename rules */ + private $filesets = array(); + + /** Any filelists of files containing the .php filenames */ + private $filelists = 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; + } + + /** + * Supports embedded <filelist> element. + * @return FileList + */ + function createFileList() { + $num = array_push($this->filelists, new FileList()); + return $this->filelists[$num-1]; + } + + /** + * 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. + * + * @return array an array of (basedir, filenames) pairs + */ + private function getFilenames() + { + $files = array(); + + foreach($this->filelists as $fl) { + try { + $list = $fl->getFiles($this->project); + foreach($list as $file) { + $fs = new PhingFile(strval($fl->getDir($this->project)), $file); + $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); + } + } catch (BuildException $be) { + $this->log($be->getMessage(), Project::MSG_WARN); + } + } + + + foreach ($this->filesets as $fileset) + { + $ds = $fileset->getDirectoryScanner($this->project); + $ds->scan(); + + $includedFiles = $ds->getIncludedFiles(); + + foreach ($includedFiles as $file) + { + $fs = new PhingFile(realpath($ds->getBaseDir()), $file); + + $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); + } + } + + return $files; + } + + function init() + { + } + + 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()); + } } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageThresholdTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageThresholdTask.php new file mode 100644 index 00000000..d9afbb00 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageThresholdTask.php @@ -0,0 +1,458 @@ +<?php +/** + * $Id: ed00d6f1d05bb5dc7c9967c9ec67fa6f958682ec $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/util/Properties.php'; +require_once 'phing/types/Excludes.php'; + +/** + * Stops the build if any of the specified coverage threshold was not reached + * + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: ed00d6f1d05bb5dc7c9967c9ec67fa6f958682ec $ + * @package phing.tasks.ext.coverage + * @since 2.4.1 + */ +class CoverageThresholdTask extends Task +{ + /** + * Holds an optional classpath + * + * @var Path + */ + private $_classpath = null; + + /** + * Holds the exclusions + * + * @var Excludes + */ + private $_excludes = null; + + /** + * Holds an optional database file + * + * @var PhingFile + */ + private $_database = null; + + /** + * Holds the coverage threshold for the entire project + * + * @var integer + */ + private $_perProject = 25; + + /** + * Holds the coverage threshold for any class + * + * @var integer + */ + private $_perClass = 25; + + /** + * Holds the coverage threshold for any method + * + * @var integer + */ + private $_perMethod = 25; + + /** + * Holds the minimum found coverage value for a class + * + * @var integer + */ + private $_minClassCoverageFound = null; + + /** + * Holds the minimum found coverage value for a method + * + * @var integer + */ + private $_minMethodCoverageFound = null; + + /** + * Number of statements in the entire project + * + * @var integer + */ + private $_projectStatementCount = 0; + + /** + * Number of covered statements in the entire project + * + * @var integer + */ + private $_projectStatementsCovered = 0; + + /** + * Whether to enable detailed logging + * + * @var boolean + */ + private $_verbose = false; + + /** + * Sets an optional classpath + * + * @param Path $classpath The classpath + */ + public function setClasspath(Path $classpath) + { + if ($this->_classpath === null) { + $this->_classpath = $classpath; + } else { + $this->_classpath->append($classpath); + } + } + + /** + * Sets the optional coverage database to use + * + * @param PhingFile The database file + */ + public function setDatabase(PhingFile $database) + { + $this->_database = $database; + } + + /** + * Create classpath object + * + * @return Path + */ + public function createClasspath() + { + $this->classpath = new Path(); + return $this->classpath; + } + + /** + * Sets the coverage threshold for entire project + * + * @param integer $threshold Coverage threshold for entire project + */ + public function setPerProject($threshold) + { + $this->_perProject = $threshold; + } + + /** + * Sets the coverage threshold for any class + * + * @param integer $threshold Coverage threshold for any class + */ + public function setPerClass($threshold) + { + $this->_perClass = $threshold; + } + + /** + * Sets the coverage threshold for any method + * + * @param integer $threshold Coverage threshold for any method + */ + public function setPerMethod($threshold) + { + $this->_perMethod = $threshold; + } + + /** + * Sets whether to enable detailed logging or not + * + * @param boolean $verbose + */ + public function setVerbose($verbose) + { + $this->_verbose = StringHelper::booleanValue($verbose); + } + + /** + * Filter covered statements + * + * @param integer $var Coverage CODE/count + * @return boolean + */ + protected function filterCovered($var) + { + return ($var >= 0 || $var === -2); + } + + /** + * Create excludes object + * + * @return Excludes + */ + public function createExcludes() + { + $this->_excludes = new Excludes($this->project); + return $this->_excludes; + } + + /** + * Calculates the coverage threshold + * + * @param string $filename The filename to analyse + * @param array $coverageInformation Array with coverage information + */ + protected function calculateCoverageThreshold($filename, $coverageInformation) + { + $classes = PHPUnitUtil::getDefinedClasses($filename, $this->_classpath); + + if (is_array($classes)) { + foreach ($classes as $className) { + // Skip class if excluded from coverage threshold validation + if ($this->_excludes !== null) { + if (in_array($className, $this->_excludes->getExcludedClasses())) { + continue; + } + } + + $reflection = new ReflectionClass($className); + $classStartLine = $reflection->getStartLine(); + + // Strange PHP5 reflection bug, classes without parent class + // or implemented interfaces seem to start one line off + if ($reflection->getParentClass() === null + && count($reflection->getInterfaces()) === 0 + ) { + unset($coverageInformation[$classStartLine + 1]); + } else { + unset($coverageInformation[$classStartLine]); + } + + reset($coverageInformation); + + $methods = $reflection->getMethods(); + + foreach ($methods as $method) { + // PHP5 reflection considers methods of a parent class + // to be part of a subclass, we don't + if ($method->getDeclaringClass()->getName() != $reflection->getName()) { + continue; + } + + // Skip method if excluded from coverage threshold validation + if ($this->_excludes !== null) { + $excludedMethods = $this->_excludes->getExcludedMethods(); + + if (isset($excludedMethods[$className])) { + if (in_array($method->getName(), $excludedMethods[$className]) + || in_array($method->getName() . '()', $excludedMethods[$className]) + ) { + continue; + } + } + } + + $methodStartLine = $method->getStartLine(); + $methodEndLine = $method->getEndLine(); + + // small fix for XDEBUG_CC_UNUSED + if (isset($coverageInformation[$methodStartLine])) { + unset($coverageInformation[$methodStartLine]); + } + + if (isset($coverageInformation[$methodEndLine])) { + unset($coverageInformation[$methodEndLine]); + } + + if ($method->isAbstract()) { + continue; + } + + $lineNr = key($coverageInformation); + + while ($lineNr !== null && $lineNr < $methodStartLine) { + next($coverageInformation); + $lineNr = key($coverageInformation); + } + + $methodStatementsCovered = 0; + $methodStatementCount = 0; + + while ($lineNr !== null && $lineNr <= $methodEndLine) { + $methodStatementCount++; + + $lineCoverageInfo = $coverageInformation[$lineNr]; + // set covered when CODE is other than -1 (not executed) + if ($lineCoverageInfo > 0 || $lineCoverageInfo === -2) { + $methodStatementsCovered++; + } + + next($coverageInformation); + $lineNr = key($coverageInformation); + } + + if ($methodStatementCount > 0) { + $methodCoverage = ( $methodStatementsCovered + / $methodStatementCount) * 100; + } else { + $methodCoverage = 0; + } + + if ($methodCoverage < $this->_perMethod + && !$method->isAbstract() + ) { + throw new BuildException( + 'The coverage (' . round($methodCoverage, 2) . '%) ' + . 'for method "' . $method->getName() . '" is lower' + . ' than the specified threshold (' + . $this->_perMethod . '%), see file: "' + . $filename . '"' + ); + } elseif ($methodCoverage < $this->_perMethod + && $method->isAbstract() + && $this->_verbose === true + ) { + $this->log( + 'Skipped coverage threshold for abstract method "' + . $method->getName() . '"' + ); + } + + // store the minimum coverage value for logging (see #466) + if ($this->_minMethodCoverageFound !== null) { + if ($this->_minMethodCoverageFound > $methodCoverage) { + $this->_minMethodCoverageFound = $methodCoverage; + } + } else { + $this->_minMethodCoverageFound = $methodCoverage; + } + } + + $classStatementCount = count($coverageInformation); + $classStatementsCovered = count( + array_filter( + $coverageInformation, + array($this, 'filterCovered') + ) + ); + + if ($classStatementCount > 0) { + $classCoverage = ( $classStatementsCovered + / $classStatementCount) * 100; + } else { + $classCoverage = 0; + } + + if ($classCoverage < $this->_perClass + && !$reflection->isAbstract() + ) { + throw new BuildException( + 'The coverage (' . round($classCoverage, 2) . '%) for class "' + . $reflection->getName() . '" is lower than the ' + . 'specified threshold (' . $this->_perClass . '%), ' + . 'see file: "' . $filename . '"' + ); + } elseif ($classCoverage < $this->_perClass + && $reflection->isAbstract() + && $this->_verbose === true + ) { + $this->log( + 'Skipped coverage threshold for abstract class "' + . $reflection->getName() . '"' + ); + } + + // store the minimum coverage value for logging (see #466) + if ($this->_minClassCoverageFound !== null) { + if ($this->_minClassCoverageFound > $classCoverage) { + $this->_minClassCoverageFound = $classCoverage; + } + } else { + $this->_minClassCoverageFound = $classCoverage; + } + + $this->_projectStatementCount += $classStatementCount; + $this->_projectStatementsCovered += $classStatementsCovered; + } + } + } + + public function main() + { + if ($this->_database === null) { + $coverageDatabase = $this->project + ->getProperty('coverage.database'); + + if (! $coverageDatabase) { + throw new BuildException( + 'Either include coverage-setup in your build file or set ' + . 'the "database" attribute' + ); + } + + $database = new PhingFile($coverageDatabase); + } else { + $database = $this->_database; + } + + $this->log( + 'Calculating coverage threshold: min. ' + . $this->_perProject . '% per project, ' + . $this->_perClass . '% per class and ' + . $this->_perMethod . '% per method is required' + ); + + $props = new Properties(); + $props->load($database); + + foreach ($props->keys() as $filename) { + $file = unserialize($props->getProperty($filename)); + + // Skip file if excluded from coverage threshold validation + if ($this->_excludes !== null) { + if (in_array($file['fullname'], $this->_excludes->getExcludedFiles())) { + continue; + } + } + + $this->calculateCoverageThreshold( + $file['fullname'], + $file['coverage'] + ); + } + + if ($this->_projectStatementCount > 0) { + $coverage = ( $this->_projectStatementsCovered + / $this->_projectStatementCount) * 100; + } else { + $coverage = 0; + } + + if ($coverage < $this->_perProject) { + throw new BuildException( + 'The coverage (' . round($coverage, 2) . '%) for the entire project ' + . 'is lower than the specified threshold (' + . $this->_perProject . '%)' + ); + } + + $this->log( + 'Passed coverage threshold. Minimum found coverage values are: ' + . round($coverage, 2) . '% per project, ' + . round($this->_minClassCoverageFound, 2) . '% per class and ' + . round($this->_minMethodCoverageFound, 2) . '% per method' + ); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleSQLExecTask.php index d35e44f4..1ea3d5ba 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleSQLExecTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: CreoleSQLExecTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: f8f62d67a784faced2621d2ffc3b1c92e8703b05 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,7 +19,7 @@ * <http://phing.info>. */ -require_once 'phing/tasks/ext/CreoleTask.php'; +require_once 'phing/tasks/ext/creole/CreoleTask.php'; include_once 'phing/system/io/StringReader.php'; /** @@ -48,8 +48,8 @@ include_once 'phing/system/io/StringReader.php'; * @author Jeff Martin <jeff@custommonkey.org> (Ant) * @author Michael McCallum <gholam@xtra.co.nz> (Ant) * @author Tim Stephenson <tim.stephenson@sybase.com> (Ant) - * @package phing.tasks.ext - * @version $Revision: 1.21 $ + * @package phing.tasks.ext.creole + * @version $Id: f8f62d67a784faced2621d2ffc3b1c92e8703b05 $ */ class CreoleSQLExecTask extends CreoleTask { @@ -70,6 +70,11 @@ class CreoleSQLExecTask extends CreoleTask { private $filesets = array(); /** + * all filterchains objects assigned to this task + */ + private $filterChains = array(); + + /** * SQL statement */ private $statement = null; @@ -155,6 +160,17 @@ class CreoleSQLExecTask extends CreoleTask { } /** + * Creates a filterchain + * + * @access public + * @return object The created filterchain object + */ + function createFilterChain() { + $num = array_push($this->filterChains, new FilterChain($this->project)); + return $this->filterChains[$num-1]; + } + + /** * Add a SQL transaction to execute */ public function createTransaction() { @@ -303,7 +319,7 @@ class CreoleSQLExecTask extends CreoleTask { try { if ($this->output !== null) { - $this->log("Opening output file " . $this->output, PROJECT_MSG_VERBOSE); + $this->log("Opening output file " . $this->output, Project::MSG_VERBOSE); $out = new BufferedWriter(new FileWriter($this->output->getAbsolutePath(), $this->append)); } @@ -311,7 +327,7 @@ class CreoleSQLExecTask extends CreoleTask { for ($i=0,$size=count($this->transactions); $i < $size; $i++) { $this->transactions[$i]->runTransaction($out); if (!$this->isAutocommit()) { - $this->log("Commiting transaction", PROJECT_MSG_VERBOSE); + $this->log("Commiting transaction", Project::MSG_VERBOSE); $this->conn->commit(); } } @@ -357,9 +373,25 @@ class CreoleSQLExecTask extends CreoleTask { public function runStatements(Reader $reader, $out = null) { $sql = ""; $line = ""; - $in = new BufferedReader($reader); - try { + + $buffer = ''; + + if ((is_array($this->filterChains)) && (!empty($this->filterChains))) { + $in = FileUtils::getChainedReader(new BufferedReader($reader), $this->filterChains, $this->getProject()); + while(-1 !== ($read = $in->read())) { // -1 indicates EOF + $buffer .= $read; + } + $lines = explode("\n", $buffer); + } else { + $in = new BufferedReader($reader); + while (($line = $in->readLine()) !== null) { + $lines[] = $line; + } + } + + try { + foreach ($lines as $line) { $line = trim($line); $line = ProjectConfigurator::replaceProperties($this->project, $line, $this->project->getProperties()); @@ -389,8 +421,8 @@ class CreoleSQLExecTask extends CreoleTask { && StringHelper::endsWith($this->delimiter, $sql) || $this->delimiterType == self::DELIM_ROW && $line == $this->delimiter) { - $this->log("SQL: " . $sql, PROJECT_MSG_VERBOSE); - $this->execSQL(StringHelper::substring($sql, 0, strlen($sql) - strlen($this->delimiter)) - 1, $out); + $this->log("SQL: " . $sql, Project::MSG_VERBOSE); + $this->execSQL(StringHelper::substring($sql, 0, strlen($sql) - strlen($this->delimiter)), $out); $sql = ""; } } @@ -418,7 +450,7 @@ class CreoleSQLExecTask extends CreoleTask { try { $this->totalSql++; if (!$this->statement->execute($sql)) { - $this->log($this->statement->getUpdateCount() . " rows affected", PROJECT_MSG_VERBOSE); + $this->log($this->statement->getUpdateCount() . " rows affected", Project::MSG_VERBOSE); } else { if ($this->print) { $this->printResults($out); @@ -428,27 +460,27 @@ class CreoleSQLExecTask extends CreoleTask { $this->goodSql++; } catch (SQLException $e) { - $this->log("Failed to execute: " . $sql, PROJECT_MSG_ERR); + $this->log("Failed to execute: " . $sql, Project::MSG_ERR); if ($this->onError != "continue") { throw new BuildException("Failed to execute SQL", $e); } - $this->log($e->getMessage(), PROJECT_MSG_ERR); + $this->log($e->getMessage(), Project::MSG_ERR); } } /** * print any results in the statement. - * @throw SQLException + * @throws SQLException */ protected function printResults($out = null) { - $lSep = Phing::getProperty('line.separator'); + $rs = null; do { $rs = $this->statement->getResultSet(); if ($rs !== null) { - $this->log("Processing new result set.", PROJECT_MSG_VERBOSE); + $this->log("Processing new result set.", Project::MSG_VERBOSE); $line = ""; @@ -467,7 +499,7 @@ class CreoleSQLExecTask extends CreoleTask { $out->write($line); $out->newLine(); } else { - print($line.$lSep); + print($line.PHP_EOL); } $line = ""; $colsprinted = true; @@ -492,14 +524,14 @@ class CreoleSQLExecTask extends CreoleTask { $out->write($line); $out->newLine(); } else { - print($line . $lSep); + print($line . PHP_EOL); } $line = ""; } // while rs->next() } } while ($this->statement->getMoreResults()); - print($lSep); + print(PHP_EOL); if ($out !== null) $out->newLine(); } } @@ -510,6 +542,8 @@ class CreoleSQLExecTask extends CreoleTask { * Transactions allow several files or blocks of statements * to be executed using the same JDBC connection and commit * operation in between. + * + * @package phing.tasks.ext.creole */ class SQLExecTransaction { @@ -539,14 +573,16 @@ class SQLExecTransaction { public function runTransaction($out = null) { if (!empty($this->tSqlCommand)) { - $this->parent->log("Executing commands", PROJECT_MSG_INFO); + $this->parent->log("Executing commands", Project::MSG_INFO); $this->parent->runStatements(new StringReader($this->tSqlCommand), $out); } if ($this->tSrcFile !== null) { $this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(), - PROJECT_MSG_INFO); + Project::MSG_INFO); + $reader = new FileReader($this->tSrcFile); + $this->parent->runStatements($reader, $out); $reader->close(); } diff --git a/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleTask.php index a1b439e5..6cff2033 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/creole/CreoleTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: CreoleTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 91a6dbbd682e6afa8befa95f01ae5fbaed11a72a $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/types/Reference.php'; * @author Jeff Martin <jeff@custommonkey.org> (Ant) * @author Michael McCallum <gholam@xtra.co.nz> (Ant) * @author Tim Stephenson <tim.stephenson@sybase.com> (Ant) - * @version $Revision: 1.13 $ + * @version $Id$ * @package phing.tasks.system */ abstract class CreoleTask extends Task { @@ -164,7 +164,7 @@ abstract class CreoleTask extends Task { try { - $this->log("Connecting to " . $this->getUrl(), PROJECT_MSG_VERBOSE); + $this->log("Connecting to " . $this->getUrl(), Project::MSG_VERBOSE); $info = new Properties(); $dsn = Creole::parseDSN($this->url); diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbDeployTask.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbDeployTask.php new file mode 100755 index 00000000..a5cc23ff --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbDeployTask.php @@ -0,0 +1,436 @@ +<?php +/* + * $Id: 035d43c0c50ca9567e9c8a016fef6a3053164acb $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php'; + + +/** + * Generate SQL script for db using dbdeploy schema version table + * and delta scripts + * + * <dbdeploy url="mysql:host=localhost;dbname=test" + * userid="dbdeploy" password="dbdeploy" dir="db" outputfile=""> + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ +class DbDeployTask extends Task +{ + /** + * The tablename to use from the database for storing all changes + * This cannot be changed + * + * @var string + */ + public static $TABLE_NAME = 'changelog'; + + /** + * Connection string for the database connection + * + * @var string + */ + protected $url; + + /** + * The userid for the database connection + * + * @var string + */ + protected $userid; + + /** + * The password of the database user + * + * @var string + */ + protected $password; + + /** + * Path to the directory that holds the database patch files + * + * @var string + */ + protected $dir; + + /** + * Output file for performing all database patches of this deployment + * Contains all the SQL statements that need to be executed + * + * @var string + */ + protected $outputFile = 'dbdeploy_deploy.sql'; + + /** + * Outputfile for undoing the database patches of this deployment + * Contains all the SQL statements that need to be executed + * + * @var string + */ + protected $undoOutputFile = 'dbdeploy_undo.sql'; + + /** + * The deltaset that's being used + * + * @var string + */ + protected $deltaSet = 'Main'; + + /** + * The number of the last change to apply + * + * @var int + */ + protected $lastChangeToApply = 999; + + /** + * Contains the object for the DBMS that is used + * + * @var object + */ + protected $dbmsSyntax = null; + + /** + * Array with all change numbers that are applied already + * + * @var array + */ + protected $appliedChangeNumbers = array(); + + /** + * Checkall attribute + * False means dbdeploy will only apply patches that have a higher number + * than the last patchnumber that was applied + * True means dbdeploy will apply all changes that aren't applied + * already (in ascending order) + * + * @var int + */ + protected $checkall = false; + + /** + * The main function for the task + * + * @throws BuildException + * @return void + */ + public function main() + { + try { + // get correct DbmsSyntax object + $dbms = substr($this->url, 0, strpos($this->url, ':')); + $dbmsSyntaxFactory = new DbmsSyntaxFactory($dbms); + $this->dbmsSyntax = $dbmsSyntaxFactory->getDbmsSyntax(); + + // figure out which revisions are in the db already + $this->appliedChangeNumbers = $this->getAppliedChangeNumbers(); + $this->log('Current db revision: '.$this->getLastChangeAppliedInDb()); + $this->log('Checkall: ' . $this->checkall); + + $this->deploy(); + + } catch (Exception $e) { + throw new BuildException($e); + } + } + + /** + * Get the numbers of all the patches that are already applied according to + * the changelog table in the database + * + * @return array + */ + protected function getAppliedChangeNumbers() + { + if (count($this->appliedChangeNumbers) == 0) { + $this->log('Getting applied changed numbers from DB: ' . $this->url); + $appliedChangeNumbers = array(); + $dbh = new PDO($this->url, $this->userid, $this->password); + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $sql = "SELECT * + FROM " . DbDeployTask::$TABLE_NAME . " + WHERE delta_set = '$this->deltaSet' + ORDER BY change_number"; + foreach ($dbh->query($sql) as $change) { + $appliedChangeNumbers[] = $change['change_number']; + } + $this->appliedChangeNumbers = $appliedChangeNumbers; + } + return $this->appliedChangeNumbers; + } + + /** + * Get the number of the last patch applied to the database + * + * @return int|mixed The highest patch number that is applied in the db + */ + protected function getLastChangeAppliedInDb() + { + return (count($this->appliedChangeNumbers) > 0) + ? max($this->appliedChangeNumbers) : 0; + } + + /** + * Create the deploy and undo deploy outputfiles + * + * @return void + */ + protected function deploy() + { + // create deploy outputfile + $this->createOutputFile($this->outputFile, false); + + // create undo deploy outputfile + $this->createOutputFile($this->undoOutputFile, true); + } + + /** + * Generate the sql for doing/undoing the deployment and write it to a file + * + * @param string $file + * @param bool $undo + * @return void + */ + protected function createOutputFile($file, $undo = false) + { + $fileHandle = fopen($file, "w+"); + $sql = $this->generateSql($undo); + fwrite($fileHandle, $sql); + } + + /** + * Generate the sql for doing/undoing this deployment + * + * @param bool $undo + * @return string The sql + */ + protected function generateSql($undo = false) + { + $sql = ''; + $lastChangeAppliedInDb = $this->getLastChangeAppliedInDb(); + $files = $this->getDeltasFilesArray(); + $this->sortFiles($files, $undo); + + foreach ($files as $fileChangeNumber => $fileName) { + if ($this->fileNeedsToBeRead($fileChangeNumber, $lastChangeAppliedInDb)) { + $sql .= '-- Fragment begins: ' . $fileChangeNumber . ' --' . "\n"; + + if (!$undo) { + $sql .= 'INSERT INTO ' . DbDeployTask::$TABLE_NAME . ' + (change_number, delta_set, start_dt, applied_by, description)' . + ' VALUES (' . $fileChangeNumber . ', \'' . $this->deltaSet . '\', ' . + $this->dbmsSyntax->generateTimestamp() . + ', \'dbdeploy\', \'' . $fileName . '\');' . "\n"; + } + + // read the file + $fullFileName = $this->dir . '/' . $fileName; + $fh = fopen($fullFileName, 'r'); + $contents = fread($fh, filesize($fullFileName)); + // allow construct with and without space added + $split = strpos($contents, '-- //@UNDO'); + if ($split === false) + $split = strpos($contents, '--//@UNDO'); + + if ($undo) { + $sql .= substr($contents, $split + 10) . "\n"; + $sql .= 'DELETE FROM ' . DbDeployTask::$TABLE_NAME . ' + WHERE change_number = ' . $fileChangeNumber . ' + AND delta_set = \'' . $this->deltaSet . '\';' . "\n"; + } else { + $sql .= substr($contents, 0, $split); + $sql .= 'UPDATE ' . DbDeployTask::$TABLE_NAME . ' + SET complete_dt = ' . $this->dbmsSyntax->generateTimestamp() . ' + WHERE change_number = ' . $fileChangeNumber . ' + AND delta_set = \'' . $this->deltaSet . '\';' . "\n"; + } + + $sql .= '-- Fragment ends: ' . $fileChangeNumber . ' --' . "\n"; + } + } + + return $sql; + } + + /** + * Get a list of all the patch files in the patch file directory + * + * @return array + */ + protected function getDeltasFilesArray() + { + $files = array(); + $baseDir = realpath($this->dir); + $dh = opendir($baseDir); + $fileChangeNumberPrefix = ''; + while (($file = readdir($dh)) !== false) { + if (preg_match('[\d+]', $file, $fileChangeNumberPrefix)) { + $files[intval($fileChangeNumberPrefix[0])] = $file; + } + } + return $files; + } + + /** + * Sort files in the patch files directory (ascending or descending depending on $undo boolean) + * + * @param array $files + * @param bool $undo + * @return void + */ + protected function sortFiles(&$files, $undo) + { + if ($undo) { + krsort($files); + } else { + ksort($files); + } + } + + /** + * Determine if this patch file need to be deployed + * (using fileChangeNumber, lastChangeAppliedInDb and $this->checkall) + * + * @param int $fileChangeNumber + * @param string $lastChangeAppliedInDb + * @return bool True or false if patch file needs to be deployed + */ + protected function fileNeedsToBeRead($fileChangeNumber, $lastChangeAppliedInDb) + { + if ($this->checkall) { + return (!in_array($fileChangeNumber, $this->appliedChangeNumbers)); + } else { + return ($fileChangeNumber > $lastChangeAppliedInDb && $fileChangeNumber <= $this->lastChangeToApply); + } + } + + /** + * Set the url for the database connection + * + * @param string $url + * @return void + */ + public function setUrl($url) + { + $this->url = $url; + } + + /** + * Set the userid for the database connection + * + * @param string $userid + * @return void + */ + public function setUserId($userid) + { + $this->userid = $userid; + } + + /** + * Set the password for the database connection + * + * @param string $password + * @return void + */ + public function setPassword($password) + { + $this->password = $password; + } + + /** + * Set the directory where to find the patchfiles + * + * @param string $dir + * @return void + */ + public function setDir($dir) + { + $this->dir = $dir; + } + + /** + * Set the outputfile which contains all patch sql statements for this deployment + * + * @param string $outputFile + * @return void + */ + public function setOutputFile($outputFile) + { + $this->outputFile = $outputFile; + } + + /** + * Set the undo outputfile which contains all undo statements for this deployment + * + * @param string $undoOutputFile + * @return void + */ + public function setUndoOutputFile($undoOutputFile) + { + $this->undoOutputFile = $undoOutputFile; + } + + /** + * Set the lastchangetoapply property + * + * @param int $lastChangeToApply + * @return void + */ + public function setLastChangeToApply($lastChangeToApply) + { + $this->lastChangeToApply = $lastChangeToApply; + } + + /** + * Set the deltaset property + * + * @param string $deltaSet + * @return void + */ + public function setDeltaSet($deltaSet) + { + $this->deltaSet = $deltaSet; + } + + /** + * Set the checkall property + * + * @param bool $checkall + * @return void + */ + public function setCheckAll($checkall) + { + $this->checkall = (int)$checkall; + } + + /** + * Add a new fileset. + * @return FileSet + */ + public function createFileSet() + { + $this->fileset = new FileSet(); + $this->filesets[] = $this->fileset; + return $this->fileset; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php new file mode 100755 index 00000000..f20d2df4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php @@ -0,0 +1,34 @@ +<?php +/* + * $Id: 40826765e423da7500094b84f0025f75c8fdde87 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Utility class for generating necessary server-specific SQL commands + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ + +abstract class DbmsSyntax +{ + public abstract function generateTimestamp(); +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php new file mode 100755 index 00000000..1cc163f5 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php @@ -0,0 +1,67 @@ +<?php +/* + * $Id: 0efe41b73233dd4396055518a125e4ff642693c5 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/dbdeploy/DbmsSyntax.php'; + +/** + * Factory for generating dbms-specific syntax-generating objects + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxFactory +{ + private $dbms; + + public function __construct($dbms) + { + $this->dbms = $dbms; + } + + public function getDbmsSyntax() + { + switch ($this->dbms){ + case('sqlite') : + require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php'; + return new DbmsSyntaxSQLite(); + case('mysql'): + require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php'; + return new DbmsSyntaxMysql(); + case 'odbc': + case('mssql'): + case 'dblib': + require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php'; + return new DbmsSyntaxMsSql(); + case('pgsql'): + require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php'; + return new DbmsSyntaxPgSQL(); + case 'oci': + require_once 'phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php'; + return new DbmsSyntaxOracle(); + default: + throw new Exception($this->dbms . ' is not supported by dbdeploy task.'); + } + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php new file mode 100755 index 00000000..0b505d8e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php @@ -0,0 +1,37 @@ +<?php +/* + * $Id: 10012c2626ef9befc8c18efa5898704e269d6164 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Utility class for generating necessary server-specific SQL commands + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxMsSql extends DbmsSyntax +{ + public function generateTimestamp() + { + return "DATEDIFF(s, '19700101', GETDATE())"; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php new file mode 100755 index 00000000..86bf8ae0 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php @@ -0,0 +1,37 @@ +<?php +/* + * $Id: 3a8bab5e99f20e29f5c7dfe7d02f7a91fb8ccecd $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Utility class for generating necessary server-specific SQL commands + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxMysql extends DbmsSyntax +{ + public function generateTimestamp() + { + return "NOW()"; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php new file mode 100755 index 00000000..15b0b0a0 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.php @@ -0,0 +1,37 @@ +<?php +/* + * $Id: be6f99d787b94f7f2c1c8e359def3d465386bba9 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Utility class for generating necessary server-specific SQL commands + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxOracle extends DbmsSyntax +{ + public function generateTimestamp() + { + return "(sysdate - to_date('01-JAN-1970','DD-MON-YYYY')) * (86400)"; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php new file mode 100755 index 00000000..6c07931c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.php @@ -0,0 +1,36 @@ +<?php +/* + * $Id: 17845f06b311dbe508e7cb1244cd849a1d3fcada $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Utility class for generating necessary server-specific SQL commands + * + * @author R�my BREUILS + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ +class DbmsSyntaxPgSQL extends DbmsSyntax +{ + public function generateTimestamp() + { + return "NOW()"; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php new file mode 100755 index 00000000..32aa023e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php @@ -0,0 +1,37 @@ +<?php +/* + * $Id: a48723b4c3ef1e5c15417f5ea6e495960e5e018b $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Utility class for generating necessary server-specific SQL commands + * + * @author Luke Crouch at SourceForge (http://sourceforge.net) + * @version $Id$ + * @package phing.tasks.ext.dbdeploy + */ + +class DbmsSyntaxSQLite extends DbmsSyntax +{ + public function generateTimestamp() + { + return "strftime('%s','now')"; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/docblox/DocBloxTask.php b/buildscripts/phing/classes/phing/tasks/ext/docblox/DocBloxTask.php new file mode 100755 index 00000000..0c1556c8 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/docblox/DocBloxTask.php @@ -0,0 +1,221 @@ +<?php +/* + * $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/FileOutputStream.php'; + +/** + * DocBlox Task (http://www.docblox-project.org) + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * @since 2.4.6 + * @package phing.tasks.ext.docblox + */ +class DocBloxTask extends Task +{ + /** + * List of filesets + * @var FileSet[] + */ + private $filesets = array(); + + /** + * Destination/target directory + * @var PhingFile + */ + private $destDir = null; + + /** + * name of the template to use + * @var string + */ + private $template = "new_black"; + + /** + * Title of the project + * @var string + */ + private $title = ""; + + /** + * Force DocBlox to be quiet + * @var boolean + */ + private $quiet = true; + + /** + * Nested creator, adds a set of files (nested fileset attribute). + * + * @return FileSet + */ + public function createFileSet() + { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Sets destination/target directory + * @param PhingFile $destDir + */ + public function setDestDir(PhingFile $destDir) + { + $this->destDir = $destDir; + } + + /** + * Convenience setter (@see setDestDir) + * @param PhingFile $output + */ + public function setOutput(PhingFile $output) + { + $this->destDir = $output; + } + + /** + * Sets the template to use + * @param strings $template + */ + public function setTemplate($template) + { + $this->template = (string) $template; + } + + /** + * Sets the title of the project + * @param strings $title + */ + public function setTitle($title) + { + $this->title = (string) $title; + } + + /** + * Forces DocBlox to be quiet + * @param boolean $quiet + */ + public function setQuiet($quiet) + { + $this->quiet = (boolean) $quiet; + } + + /** + * Finds and initializes the DocBlox installation + */ + private function initializeDocBlox() + { + $docbloxPath = null; + + foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) { + $testDocBloxPath = $path . DIRECTORY_SEPARATOR . 'DocBlox' . DIRECTORY_SEPARATOR . 'src'; + + if (file_exists($testDocBloxPath)) { + $docbloxPath = $testDocBloxPath; + } + } + + if (empty($docbloxPath)) { + throw new BuildException("Please make sure DocBlox is installed and on the include_path.", $this->getLocation()); + } + + set_include_path($docbloxPath . PATH_SEPARATOR . get_include_path()); + + require_once $docbloxPath.'/DocBlox/Bootstrap.php'; + + $bootstrap = DocBlox_Bootstrap::createInstance(); + + $autoloader = $bootstrap->registerAutoloader(); + + if ($this->quiet) { + DocBlox_Core_Abstract::config()->logging->level = 'quiet'; + } else { + DocBlox_Core_Abstract::config()->logging->level = 'debug'; + } + + $bootstrap->registerPlugins($autoloader); + } + + /** + * Build a list of files (from the fileset elements) and call the DocBlox parser + * @return string + */ + private function parseFiles() + { + $parser = new DocBlox_Parser(); + + //Only initialize the dispatcher when not already done + if (is_null(DocBlox_Parser_Abstract::$event_dispatcher)) { + DocBlox_Parser_Abstract::$event_dispatcher = new sfEventDispatcher(); + } + $parser->setTitle($this->title); + + $paths = array(); + + // filesets + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($this->project); + $dir = $fs->getDir($this->project); + $srcFiles = $ds->getIncludedFiles(); + + foreach ($srcFiles as $file) { + $paths[] = $dir . FileSystem::getFileSystem()->getSeparator() . $file; + } + } + + $this->log("Will parse " . count($paths) . " file(s)", Project::MSG_VERBOSE); + + $files = new DocBlox_Parser_Files(); + $files->addFiles($paths); + + $parser->setPath($files->getProjectRoot()); + + return $parser->parseFiles($files); + } + + /** + * Task entry point + * @see Task::main() + */ + public function main() + { + if (empty($this->destDir)) { + throw new BuildException("You must supply the 'destdir' attribute", $this->getLocation()); + } + + if (empty($this->filesets)) { + throw new BuildException("You have not specified any files to include (<fileset>)", $this->getLocation()); + } + + $this->initializeDocBlox(); + + $xml = $this->parseFiles(); + + $this->log("Transforming...", Project::MSG_VERBOSE); + + $transformer = new DocBlox_Transformer(); + $transformer->setTemplatesPath(DocBlox_Core_Abstract::config()->paths->templates); + $transformer->setTemplates($this->template); + $transformer->setSource($xml); + $transformer->setTarget($this->destDir->getAbsolutePath()); + $transformer->execute(); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitBaseTask.php new file mode 100644 index 00000000..8381cc64 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitBaseTask.php @@ -0,0 +1,134 @@ +<?php +/* + * $Id: 5ffc8c9c51dfa9bd0d691a88db670cdeb5f985c1 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/BuildException.php'; + +/** + * Base class for Git tasks + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 5ffc8c9c51dfa9bd0d691a88db670cdeb5f985c1 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +abstract class GitBaseTask extends Task +{ + /** + * Bath to git binary + * @var string + */ + private $gitPath = '/usr/bin/git'; + + /** + * @var VersionControl_Git + */ + private $gitClient = null; + + /** + * Current repository directory + * @var string + */ + private $repository; + + /** + * Initialize Task. + * Check and include necessary libraries. + */ + public function init() + { + @include_once 'VersionControl/Git.php'; + if (false == class_exists('VersionControl_Git')) { + throw new BuildException("The Git tasks depend on PEAR\'s " + . "VersionControl_Git package.", $this->getLocation()); + } + } + + /** + * Set repository directory + * + * @param string $repository Repo directory + * @return GitBaseTask + */ + public function setRepository($repository) + { + $this->repository = $repository; + return $this; + } + + /** + * Get repository directory + * + * @return string + */ + public function getRepository() + { + return $this->repository; + } + + /** + * Set path to git executable + * + * @param string $gitPath New path to git repository + * @return GitBaseTask + */ + public function setGitPath($gitPath) + { + $this->gitPath = $gitPath; + return $this; + } + + /** + * Get path to git executable + * + * @return string + */ + public function getGitPath() + { + return $this->gitPath; + } + + protected function getGitClient($reset = false, $repository = null) + { + $this->gitClient = ($reset === true) ? null : $this->gitClient; + $repository = (null === $repository) + ? $this->getRepository() + : $repository; + + if(null === $this->gitClient) { + try { + $this->gitClient = new VersionControl_Git($repository); + } catch (VersionControl_Git_Exception $e) { + // re-package + throw new BuildException( + 'You must specify readable directory as repository.'); + + } + } + $this->gitClient->setGitCommandPath($this->getGitPath()); + + return $this->gitClient; + } +} + + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitBranchTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitBranchTask.php new file mode 100644 index 00000000..54a0eb20 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitBranchTask.php @@ -0,0 +1,296 @@ +<?php +/* + * $Id: 88a8737d783614bcd5acb103738fafc23c509225 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-branch + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 88a8737d783614bcd5acb103738fafc23c509225 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitBranchTask extends GitBaseTask +{ + /** + * Branch name + * @var string + */ + private $branchname; + + /** + * New Branch name for git-branch -m | -M + * @var string + */ + private $newbranch; + + /** + * If not HEAD, specify starting point + * @var string + */ + private $startPoint; + + /** + * --set-upstream key to git-branch + * @var boolean + */ + private $setUpstream = false; + + /** + * --track key to git-branch + * @var boolean + */ + private $track = false; + + /** + * --no-track key to git-branch + * @var boolean + */ + private $noTrack = false; + + /** + * --force, -f key to git-branch + * @var boolean + */ + private $force = false; + + /** + * -d, -D, -m, -M options to git-branch + * Respective task options: + * delete, forceDelete, move, forceMove + * @var array + */ + private $extraOptions = array( + 'd' => false, + 'D' => false, + 'm' => false, + 'M' => false, + ); + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + if (null === $this->getBranchname()) { + throw new BuildException('"branchname" is required parameter'); + } + + // if we are moving branch, we need to know new name + if ($this->isMove() || $this->isForceMove()) { + if (null === $this->getNewbranch()) { + throw new BuildException('"newbranch" is required parameter'); + } + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('branch'); + $command + ->setOption('set-upstream', $this->isSetUpstream()) + ->setOption('no-track', $this->isNoTrack()) + ->setOption('force', $this->isForce()); + if ($this->isNoTrack() == false) { + $command->setOption('track', $this->getTrack()); + } + + // check extra options (delete, move) + foreach ($this->extraOptions as $option => $flag) { + if ($flag) { + $command->setOption($option, true); + } + } + + $command->addArgument($this->getBranchname()); + + if (null !== $this->getStartPoint()) { + $command->addArgument($this->getStartPoint()); + } + + if (null !== $this->getNewbranch()) { + $command->addArgument($this->getNewbranch()); + } + + $this->log('git-branch command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed.'); + } + + $this->log( + sprintf('git-branch: branch "%s" repository', $this->getRepository()), + Project::MSG_INFO); + $this->log('git-branch output: ' . trim($output), Project::MSG_INFO); + } + + public function setSetUpstream($flag) + { + $this->setUpstream = $flag; + } + + public function getSetUpstream() + { + return $this->setUpstream; + } + + public function isSetUpstream() + { + return $this->getSetUpstream(); + } + + public function setTrack($flag) + { + $this->track = $flag; + } + + public function getTrack() + { + return $this->track; + } + + public function isTrack() + { + return $this->getTrack(); + } + + public function setNoTrack($flag) + { + $this->noTrack = $flag; + } + + public function getNoTrack() + { + return $this->noTrack; + } + + public function isNoTrack() + { + return $this->getNoTrack(); + } + + public function setForce($flag) + { + $this->force = $flag; + } + + public function getForce() + { + return $this->force; + } + + public function isForce() + { + return $this->getForce(); + } + + public function setBranchname($branchname) + { + $this->branchname = $branchname; + } + + public function getBranchname() + { + return $this->branchname; + } + + public function setStartPoint($startPoint) + { + $this->startPoint = $startPoint; + } + + public function getStartPoint() + { + return $this->startPoint; + } + + public function setDelete($flag) + { + $this->extraOptions['d'] = $flag; + } + + public function getDelete() + { + return $this->extraOptions['d']; + } + + public function isDelete() + { + return $this->getDelete(); + } + + public function setForceDelete($flag) + { + $this->extraOptions['D'] = $flag; + } + + public function getForceDelete() + { + return $this->extraOptions['D']; + } + + public function setMove($flag) + { + $this->extraOptions['m'] = $flag; + } + + public function getMove() + { + return $this->extraOptions['m']; + } + + public function isMove() + { + return $this->getMove(); + } + + public function setForceMove($flag) + { + $this->extraOptions['M'] = $flag; + } + + public function getForceMove() + { + return $this->extraOptions['M']; + } + + public function isForceMove() + { + return $this->getForceMove(); + } + + public function setNewBranch($name) + { + $this->newbranch = $name; + } + + public function getNewBranch() + { + return $this->newbranch; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitCheckoutTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitCheckoutTask.php new file mode 100644 index 00000000..16a2bd9f --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitCheckoutTask.php @@ -0,0 +1,256 @@ +<?php +/* + * $Id: a1dcb809b44bfd34c3af154683dd2200c814e5f0 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-checkout + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: a1dcb809b44bfd34c3af154683dd2200c814e5f0 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitCheckoutTask extends GitBaseTask +{ + /** + * Branch name + * @var string + */ + private $branchname; + + /** + * If not HEAD, specify starting point + * @var string + */ + private $startPoint; + + /** + * --force, -f key to git-checkout + * @var boolean + */ + private $force = false; + + /** + * --quiet, -q key to git-checkout + * @var boolean + */ + private $quiet = false; + + /** + * When creating a new branch, set up "upstream" configuration. + * --track key to git-checkout + * @var boolean + */ + private $track = false; + + /** + * Do not set up "upstream" configuration + * --no-track key to git-checkout + * @var boolean + */ + private $noTrack = false; + + /** + * -b, -B, -m options to git-checkout + * Respective task options: + * create, forceCreate, merge + * @var array + */ + private $extraOptions = array( + 'b' => false, + 'B' => false, + 'm' => false, + ); + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + if (null === $this->getBranchname()) { + throw new BuildException('"branchname" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('checkout'); + $command + ->setOption('no-track', $this->isNoTrack()) + ->setOption('q', $this->isQuiet()) + ->setOption('force', $this->isForce()) + ->setOption('b', $this->isCreate()) + ->setOption('B', $this->isForceCreate()) + ->setOption('m', $this->isMerge()); + if ($this->isNoTrack()) { + $command->setOption('track', $this->isTrack()); + } + + $command->addArgument($this->getBranchname()); + + if (null !== $this->getStartPoint()) { + $command->addArgument($this->getStartPoint()); + } + + $this->log('git-checkout command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed.'); + } + + $this->log( + sprintf('git-checkout: checkout "%s" repository', $this->getRepository()), + Project::MSG_INFO); + $this->log('git-checkout output: ' . trim($output), Project::MSG_INFO); + } + + public function setBranchname($branchname) + { + $this->branchname = $branchname; + } + + public function getBranchname() + { + return $this->branchname; + } + + public function setStartPoint($startPoint) + { + $this->startPoint = $startPoint; + } + + public function getStartPoint() + { + return $this->startPoint; + } + + public function setForce($flag) + { + $this->force = $flag; + } + + public function getForce() + { + return $this->force; + } + + public function isForce() + { + return $this->getForce(); + } + + public function setQuiet($flag) + { + $this->quiet = $flag; + } + + public function getQuiet() + { + return $this->quiet; + } + + public function isQuiet() + { + return $this->getQuiet(); + } + + public function setTrack($flag) + { + $this->track = $flag; + } + + public function getTrack() + { + return $this->track; + } + + public function isTrack() + { + return $this->getTrack(); + } + + public function setNoTrack($flag) + { + $this->noTrack = $flag; + } + + public function getNoTrack() + { + return $this->noTrack; + } + + public function isNoTrack() + { + return $this->getNoTrack(); + } + + public function setCreate($flag) + { + $this->extraOptions['b'] = $flag; + } + + public function getCreate() + { + return $this->extraOptions['b']; + } + + public function isCreate() + { + return $this->getCreate(); + } + + // -B flag is not found in all versions of git + // --force is present everywhere + public function setForceCreate($flag) + { + $this->setForce($flag); + } + + public function getForceCreate() + { + return $this->extraOptions['B']; + } + + public function isForceCreate() + { + return $this->getForceCreate(); + } + + public function setMerge($flag) + { + $this->extraOptions['m'] = $flag; + } + + public function getMerge() + { + return $this->extraOptions['m']; + } + + public function isMerge() + { + return $this->getMerge(); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitCloneTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitCloneTask.php new file mode 100644 index 00000000..3d1eb76f --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitCloneTask.php @@ -0,0 +1,128 @@ +<?php +/* + * $Id: 0d9ce448c11e505885b9c5362f5c2d399e205f90 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-clone + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 0d9ce448c11e505885b9c5362f5c2d399e205f90 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitCloneTask extends GitBaseTask +{ + /** + * Whether --bare key should be set for git-init + * @var string + */ + private $isBare = false; + + /** + * Path to target directory + * @var string + */ + private $targetPath; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + if (null === $this->getTargetPath()) { + throw new BuildException('"targetPath" is required parameter'); + } + + $files = @scandir($this->getTargetPath()); + if (isset($files) && is_array($files) && (count($files) > 2)) { + throw new BuildException( + sprintf( + '"%s" target directory is not empty', + $this->getTargetPath()) + ); + } + + $client = $this->getGitClient(false, getcwd()); + + try { + $client->createClone( + $this->getRepository(), + $this->isBare(), + $this->getTargetPath()); + } catch (Exception $e) { + throw new BuildException('The remote end hung up unexpectedly'); + } + + $msg = 'git-clone: cloning ' + . ($this->isBare() ? '(bare) ' : '') + . '"' . $this->getRepository() .'" repository' + . ' to "' . $this->getTargetPath() .'" directory'; + $this->log($msg, Project::MSG_INFO); + } + + /** + * Get path to target direcotry repo + * + * @return string + */ + public function getTargetPath() + { + return $this->targetPath; + } + + /** + * Set path to source repo + * + * @param string $targetPath Path to repository used as source + * @return void + */ + public function setTargetPath($targetPath) + { + $this->targetPath = $targetPath; + } + + /** + * Alias @see getBare() + * + * @return string + */ + public function isBare() + { + return $this->getBare(); + } + + public function getBare() + { + return $this->isBare; + } + + public function setBare($flag) + { + $this->isBare = (bool)$flag; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitCommitTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitCommitTask.php new file mode 100644 index 00000000..71b26ab9 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitCommitTask.php @@ -0,0 +1,179 @@ +<?php +/* + * $Id: 355a6d3cf8e182652b4acf3af0a6cd3eaa58fd02 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-commit + * + * @package Phing.tasks.ext.git + * @author Jonathan Creasy <jonathan.creasy@gmail.com> + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitCommitTask extends GitBaseTask +{ + /** + * Path to target directory + * @var string + */ + private $targetPath; + + private $allFiles; + + private $message; + + private $files; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + if (null === $this->getTargetPath()) { + throw new BuildException('"targetPath" is required parameter'); + } + + if ($this->allFiles !== true && empty($this->files)) + { + throw new BuildException('"allFiles" cannot be false if no files are specified.'); + } + + $client = $this->getGitClient(false, $this->getTargetPath()); + + $options = Array(); + + if ($this->allFiles === true) + { + $options['all'] = true; + } + + $arguments = Array(); + if ($this->allFiles !== true && is_array($this->files)) + { + foreach($files as $file) + { + $arguments[] = $file; + } + } + + if (!empty($this->message)) + { + $arguments[] = $this->message; + } else { + $options['allow-empty-message'] = true; + } + + try { + $command = $git->Command('commit'); + $command->setArguments($arguments); + $command->setOptions($options); + $command->execute(); + } catch (Exception $e) { + throw new BuildException('The remote end hung up unexpectedly'); + } + + $msg = 'git-commit: Executed git commit '; + foreach ($options as $option=>$value) + { + + $msg .= ' --' . $options . '=' . $value; + } + + foreach ($arguments as $argument) + { + $msg .= ' ' . $argument; + } + + $this->log($msg, Project::MSG_INFO); + } + + /** + * Get path to target direcotry repo + * + * @return string + */ + public function getTargetPath() + { + return $this->targetPath; + } + + /** + * Set path to source repo + * + * @param string $targetPath Path to repository used as source + * @return void + */ + public function setTargetPath($targetPath) + { + $this->targetPath = $targetPath; + } + + /** + * Alias @see getAllFiles() + * + * @return string + */ + public function isallFiles() + { + return $this->getallFiles(); + } + + public function getallFiles() + { + return $this->allFiles; + } + + public function setallFiles($flag) + { + $this->allFiles = (bool)$flag; + } + + public function getMessage() + { + return $this->message; + } + + public function setMessage($message) + { + $this->message = $message; + } + + public function getFiles() + { + return $this->files; + } + + public function setFiles($files) + { + if (!$empty($files) && is_array($files)) + { + $this->setallfiles(false); + $this->Files = $files; + } else { + $this->Files = null; + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitFetchTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitFetchTask.php new file mode 100644 index 00000000..4b3e8a3d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitFetchTask.php @@ -0,0 +1,284 @@ +<?php +/* + * $Id: bcddbc1cd2e77003746b048568da8111b48da2fb $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-fetch + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: bcddbc1cd2e77003746b048568da8111b48da2fb $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitFetchTask extends GitBaseTask +{ + /** + * --force, -f key to git-fetch + * @var boolean + */ + private $force = false; + + /** + * --quiet, -q key to git-fetch + * @var boolean + */ + private $quiet = false; + + /** + * Fetch all remotes + * --all key to git-fetch + * @var boolean + */ + private $allRemotes = false; + + /** + * Keep downloaded pack + * --keep key to git-fetch + * @var boolean + */ + private $keepFiles = false; + + /** + * After fetching, remove any remote tracking branches which no longer + * exist on the remote. + * --prune key to git fetch + * @var boolean + */ + private $prune = false; + + /** + * Disable/enable automatic tag following + * --no-tags key to git-fetch + * @var boolean + */ + private $noTags = false; + + /** + * Fetch all tags (even not reachable from branch heads) + * --tags key to git-fetch + * @var boolean + */ + private $tags = false; + + /** + * <group> argument to git-fetch + * @var string + */ + private $group; + + /** + * <repository> argument to git-fetch + * @var string + */ + private $source = 'origin'; + + /** + * <refspec> argument to git-fetch + * @var string + */ + private $refspec; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('fetch'); + $command + ->setOption('tags', $this->isTags()) + ->setOption('no-tags', $this->isNoTags()) + ->setOption('prune', $this->isPrune()) + ->setOption('keep', $this->isKeepFiles()) + ->setOption('q', $this->isQuiet()) + ->setOption('force', $this->isForce()); + + // set operation target + if ($this->isAllRemotes()) { // --all + $command->setOption('all', true); + } elseif ($this->getGroup()) { // <group> + $command->addArgument($this->getGroup()); + } elseif ($this->getSource()) { // <repository> [<refspec>] + $command->addArgument($this->getSource()); + if ($this->getRefspec()) { + $command->addArgument($this->getRefspec()); + } + } else { + throw new BuildException('No remote repository specified'); + } + + $this->log('git-fetch command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed.'); + } + + $this->log( + sprintf('git-fetch: branch "%s" repository', $this->getRepository()), + Project::MSG_INFO); + $this->log('git-fetch output: ' . trim($output), Project::MSG_INFO); + } + + public function setForce($flag) + { + $this->force = $flag; + } + + public function getForce() + { + return $this->force; + } + + public function isForce() + { + return $this->getForce(); + } + + public function setQuiet($flag) + { + $this->quiet = $flag; + } + + public function getQuiet() + { + return $this->quiet; + } + + public function isQuiet() + { + return $this->getQuiet(); + } + + public function setAll($flag) + { + $this->allRemotes = $flag; + } + + public function getAll() + { + return $this->allRemotes; + } + + public function isAllRemotes() + { + return $this->getAll(); + } + + public function setKeep($flag) + { + $this->keepFiles = $flag; + } + + public function getKeep() + { + return $this->keepFiles; + } + + public function isKeepFiles() + { + return $this->getKeep(); + } + + public function setPrune($flag) + { + $this->prune = $flag; + } + + public function getPrune() + { + return $this->prune; + } + + public function isPrune() + { + return $this->getPrune(); + } + + public function setNoTags($flag) + { + $this->noTags = $flag; + } + + public function getNoTags() + { + return $this->noTags; + } + + public function isNoTags() + { + return $this->getNoTags(); + } + + public function setTags($flag) + { + $this->tags = $flag; + } + + public function getTags() + { + return $this->tags; + } + + public function isTags() + { + return $this->getTags(); + } + + public function setSource($source) + { + $this->source = $source; + } + + public function getSource() + { + return $this->source; + } + + public function setRefspec($spec) + { + $this->refspec = $spec; + } + + public function getRefspec() + { + return $this->refspec; + } + + public function setGroup($group) + { + $this->group = $group; + } + + public function getGroup() + { + return $this->group; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitGcTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitGcTask.php new file mode 100644 index 00000000..12de4119 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitGcTask.php @@ -0,0 +1,158 @@ +<?php +/* + * $Id: 13487520850c3a7ad71d85f02afbddfd408bfbba $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; +/** + * Wrapper around git-gc + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 13487520850c3a7ad71d85f02afbddfd408bfbba $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitGcTask extends GitBaseTask +{ + /** + * --aggressive key to git-gc + * @var boolean + */ + private $isAggressive = false; + + /** + * --auto key to git-gc + * @var boolean + */ + private $isAuto = false; + + /** + * --no-prune key to git-gc + * @var boolean + */ + private $noPrune = false; + + /** + * --prune=<date>option of git-gc + * @var string + */ + private $prune = '2.weeks.ago'; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('gc'); + $command + ->setOption('aggressive', $this->isAggressive()) + ->setOption('auto', $this->isAuto()) + ->setOption('no-prune', $this->isNoPrune()); + if ($this->isNoPrune() == false) { + $command->setOption('prune', $this->getPrune()); + } + + // suppress output + $command->setOption('q'); + + $this->log('git-gc command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed'); + } + + $this->log( + sprintf('git-gc: cleaning up "%s" repository', $this->getRepository()), + Project::MSG_INFO); + } + + /** + * @see getAggressive() + */ + public function isAggressive() + { + return $this->getAggressive(); + } + + public function getAggressive() + { + return $this->isAggressive; + } + + public function setAggressive($flag) + { + $this->isAggressive = (bool)$flag; + } + + /** + * @see getAuto() + */ + public function isAuto() + { + return $this->getAuto(); + } + + public function getAuto() + { + return $this->isAuto; + } + + public function setAuto($flag) + { + $this->isAuto = (bool)$flag; + } + + /** + * @see NoPrune() + */ + public function isNoPrune() + { + return $this->getNoPrune(); + } + + public function getNoPrune() + { + return $this->noPrune; + } + + public function setNoPrune($flag) + { + $this->noPrune = (bool)$flag; + } + + public function getPrune() + { + return $this->prune; + } + + public function setPrune($date) + { + $this->prune = $date; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitInitTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitInitTask.php new file mode 100644 index 00000000..b4654cae --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitInitTask.php @@ -0,0 +1,81 @@ +<?php +/* + * $Id: 5e66bb51f299c733e4410258f40dcf61f6e96e2f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/BuildException.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Repository initialization task + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 5e66bb51f299c733e4410258f40dcf61f6e96e2f $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitInitTask extends GitBaseTask +{ + + /** + * Whether --bare key should be set for git-init + * @var string + */ + private $isBare = false; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(); + $client->initRepository($this->isBare()); + + $msg = 'git-init: initializing ' + . ($this->isBare() ? '(bare) ' : '') + . '"' . $this->getRepository() .'" repository'; + $this->log($msg, Project::MSG_INFO); + } + + /** + * Alias @see getBare() + * + * @return string + */ + public function isBare() + { + return $this->getBare(); + } + + public function getBare() + { + return $this->isBare; + } + + public function setBare($flag) + { + $this->isBare = (bool)$flag; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitLogTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitLogTask.php new file mode 100644 index 00000000..c1d8058a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitLogTask.php @@ -0,0 +1,270 @@ +<?php +/* + * $Id: 27b94c44aa26823164ce02628de06ff8b44717f7 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-log + * + * @author Evan Kaufman <evan@digitalflophouse.com> + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 27b94c44aa26823164ce02628de06ff8b44717f7 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.5 + */ +class GitLogTask extends GitBaseTask +{ + /** + * Generate a diffstat. See --stat of git-log + * @var string|boolean + */ + private $stat = false; + + /** + * Names + status of changed files. See --name-status of git-log + * @var boolean + */ + private $nameStatus = false; + + /** + * Number of commits to show. See -<n>|-n|--max-count of git-log + * @var integer + */ + private $maxCount; + + /** + * Don't show commits with more than one parent. See --no-merges of git-log + * @var boolean + */ + private $noMerges = false; + + /** + * Commit format. See --format of git-log + * @var string + */ + private $format = 'medium'; + + /** + * Date format. See --date of git-log + * @var string + */ + private $date; + + /** + * <since> argument to git-log + * @var string + */ + private $sinceCommit; + + /** + * <until> argument to git-log + * @var string + */ + private $untilCommit = 'HEAD'; + + /** + * <path> arguments to git-log + * Accepts one or more paths delimited by PATH_SEPARATOR + * @var string + */ + private $paths; + + /** + * Property name to set with output value from git-log + * @var string + */ + private $outputProperty; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('log'); + $command + ->setOption('stat', $this->getStat()) + ->setOption('name-status', $this->isNameStatus()) + ->setOption('no-merges', $this->isNoMerges()) + ->setOption('format', $this->getFormat()); + + if (null !== $this->getMaxCount()) { + $command->setOption('max-count', $this->getMaxCount()); + } + + if (null !== $this->getDate()) { + $command->setOption('date', $this->getDate()); + } + + if (null !== $this->getSince()) { + $command->setOption('since', $this->getSince()); + } + $command->setOption('until', $this->getUntil()); + + $command->addDoubleDash(true); + if (null !== $this->getPaths()) { + $command->addDoubleDash(false); + $paths = explode(PATH_SEPARATOR, $this->getPaths()); + foreach ($paths as $path) { + $command->addArgument($path); + } + } + + $this->log('git-log command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed'); + } + + if (null !== $this->outputProperty) { + $this->project->setProperty($this->outputProperty, $output); + } + + $this->log( + sprintf('git-log: commit log for "%s" repository', $this->getRepository()), + Project::MSG_INFO); + $this->log('git-log output: ' . trim($output), Project::MSG_INFO); + } + + public function setStat($stat) + { + $this->stat = $stat; + } + + public function getStat() + { + return $this->stat; + } + + public function setNameStatus($flag) + { + $this->nameStatus = (boolean)$flag; + } + + public function getNameStatus() + { + return $this->nameStatus; + } + + public function isNameStatus() + { + return $this->getNameStatus(); + } + + public function setMaxCount($count) + { + $this->maxCount = (int)$count; + } + + public function getMaxCount() + { + return $this->maxCount; + } + + public function setNoMerges($flag) + { + $this->noMerges = (bool)$flag; + } + + public function getNoMerges() + { + return $this->noMerges; + } + + public function isNoMerges() + { + return $this->getNoMerges(); + } + + public function setFormat($format) + { + $this->format = $format; + } + + public function getFormat() + { + return $this->format; + } + + public function setDate($date) + { + $this->date = $date; + } + + public function getDate() + { + return $this->date; + } + + public function setSince($since) + { + $this->sinceCommit = $since; + } + + public function getSince() + { + return $this->sinceCommit; + } + + public function setAfter($after) + { + $this->setSince($after); + } + + public function setUntil($until) + { + $this->untilCommit = $until; + } + + public function getUntil() + { + return $this->untilCommit; + } + + public function setBefore($before) + { + $this->setUntil($before); + } + + public function setPaths($paths) + { + $this->paths = $paths; + } + + public function getPaths() + { + return $this->paths; + } + + public function setOutputProperty($prop) + { + $this->outputProperty = $prop; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitMergeTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitMergeTask.php new file mode 100644 index 00000000..7a3e17fb --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitMergeTask.php @@ -0,0 +1,258 @@ +<?php +/* + * $Id: 82fabd65e9247cb37fa3fe16c122d525db4fc697 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-merge + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 82fabd65e9247cb37fa3fe16c122d525db4fc697 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + * @link http://www.kernel.org/pub/software/scm/git/docs/git-merge.html + */ +class GitMergeTask extends GitBaseTask +{ + /** + * <commit> of git-merge + * @var string + */ + private $remote; + + /** + * Commit message + * @var string + */ + private $message; + + /** + * Merge strategy. See -s <strategy> of git-merge + * Available strategies are: octopus ours recursive resolve subtree + * @var string + */ + private $strategy; + + /** + * -X or --strategy-option of git-merge + * @var string + */ + private $strategyOption; + + /** + * --commit key of git-merge + * @var boolean + */ + private $commit = false; + + /** + * --no-commit key of git-merge + * @var boolean + */ + private $noCommit = false; + + /** + * --ff --no-ff keys to git-merge + * @var boolean + */ + private $fastForwardCommit = false; + + /** + * --quiet, -q key to git-merge + * @var boolean + */ + private $quiet = false; + + /** + * Valid merge strategies + * @var array + */ + private $validStrategies = array( + 'octopus', 'ours', 'recursive', 'resolve', 'subtree'); + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + $remotes = trim($this->getRemote()); + if (null === $remotes || '' === $remotes) { + throw new BuildException('"remote" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('merge'); + $command + ->setOption('commit', $this->isCommit()) + ->setOption('q', $this->isQuiet()); + + if ($this->getMessage()) { + $command->setOption('message', $this->getMessage()); + } + + if (!$this->isCommit()) { + $command->setOption('no-commit', $this->isNoCommit()); + } + + if ($this->isFastForwardCommit()) { + $command->setOption('no-ff', true); + } + + $strategy = $this->getStrategy(); + if ($strategy) { + // check if strategy is valid + if (false === in_array($strategy, $this->validStrategies)) { + throw new BuildException( + "Could not find merge strategy '" . $strategy . "'\n". + "Available strategies are: " . implode(', ', $this->validStrategies)); + } + $command->setOption('strategy', $strategy); + if ($this->getStrategyOption()) { + $command->setOption( + 'strategy-option', $this->getStrategyOption()); + } + } + + $remotes = explode(' ', $this->getRemote()); + foreach ($remotes as $remote) { + $command->addArgument($remote); + } + + $this->log('git-merge command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed.'); + } + + $this->log( + sprintf('git-merge: replaying "%s" commits', $this->getRemote()), + Project::MSG_INFO); + $this->log('git-merge output: ' . trim($output), Project::MSG_INFO); + + } + + public function setRemote($remote) + { + $this->remote = $remote; + } + + public function getRemote() + { + return $this->remote; + } + + public function setMessage($message) + { + $this->message = $message; + } + + public function getMessage() + { + return $this->message; + } + + public function setStrategy($strategy) + { + $this->strategy = $strategy; + } + + public function getStrategy() + { + return $this->strategy; + } + + public function setStrategyOption($strategyOption) + { + $this->strategyOption = $strategyOption; + } + + public function getStrategyOption() + { + return $this->strategyOption; + } + + public function setQuiet($flag) + { + $this->quiet = $flag; + } + + public function getQuiet() + { + return $this->quiet; + } + + public function isQuiet() + { + return $this->getQuiet(); + } + + public function setCommit($flag) + { + $this->commit = (boolean)$flag; + } + + public function getCommit() + { + return $this->commit; + } + + public function isCommit() + { + return $this->getCommit(); + } + + public function setNoCommit($flag) + { + $this->noCommit = (boolean)$flag; + } + + public function getNoCommit() + { + return $this->noCommit; + } + + public function isNoCommit() + { + return $this->getNoCommit(); + } + + public function setFastForwardCommit($flag) + { + $this->fastForwardCommit = $flag; + } + + public function getFastForwardCommit() + { + return $this->fastForwardCommit; + } + + public function isFastForwardCommit() + { + return $this->getFastForwardCommit(); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitPullTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitPullTask.php new file mode 100644 index 00000000..1f7cfcc1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitPullTask.php @@ -0,0 +1,373 @@ +<?php +/* + * $Id: f96a4faad59ab1b29abccd59d04269fe0c409084 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-pull + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: f96a4faad59ab1b29abccd59d04269fe0c409084 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + */ +class GitPullTask extends GitBaseTask +{ + /** + * <repository> argument to git-pull + * @var string + */ + private $source = 'origin'; + + /** + * <refspec> argument to git-pull + * @var string + */ + private $refspec; + + /** + * --rebase key to git-pull + * @var boolean + */ + private $rebase = false; + + /** + * --no-rebase key to git-pull + * Allow to override --rebase (if set to default true in configuration) + * @var boolean + */ + private $noRebase = false; + + /** + * Merge strategy. See -s <strategy> of git-pull + * @var string + */ + private $strategy; + + /** + * -X or --strategy-option of git-pull + * @var string + */ + private $strategyOption; + + /** + * Fetch all remotes + * --all key to git-pull + * @var boolean + */ + private $allRemotes = false; + + /** + * --append key to git-pull + * @var boolean + */ + private $append = false; + + /** + * Keep downloaded pack + * --keep key to git-pull + * @var boolean + */ + private $keepFiles = false; + + /** + * Disable/enable automatic tag following + * --no-tags key to git-pull + * @var boolean + */ + private $noTags = false; + + /** + * Fetch all tags (even not reachable from branch heads) + * --tags key to git-pull + * @var boolean + */ + private $tags = false; + + /** + * --quiet, -q key to git-pull + * @var boolean + */ + private $quiet = true; + + /** + * --force, -f key to git-pull + * @var boolean + */ + private $force = false; + + /** + * Valid merge strategies + * @var array + */ + private $validStrategies = array( + 'octopus', 'ours', 'recursive', 'resolve', 'subtree'); + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('pull'); + $command + ->setOption('rebase', $this->isRebase()); + + if (!$this->isRebase()) { + $command->setOption('no-rebase', $this->isNoRebase()); + } + + $strategy = $this->getStrategy(); + if ($strategy) { + // check if strategy is valid + if (false === in_array($strategy, $this->validStrategies)) { + throw new BuildException( + "Could not find merge strategy '" . $strategy . "'\n". + "Available strategies are: " . implode(', ', $this->validStrategies)); + } + $command->setOption('strategy', $strategy); + if ($this->getStrategyOption()) { + $command->setOption( + 'strategy-option', $this->getStrategyOption()); + } + } + + // order of arguments is important + $command + ->setOption('tags', $this->isTags()) + ->setOption('no-tags', $this->isNoTags()) + ->setOption('keep', $this->isKeepFiles()) + ->setOption('append', $this->isAppend()) + ->setOption('q', $this->isQuiet()) + ->setOption('force', $this->isForce()); + + // set operation target + if ($this->isAllRemotes()) { // --all + $command->setOption('all', true); + $this->log('git-pull: fetching from all remotes', Project::MSG_INFO); + } elseif ($this->getSource()) { // <repository> [<refspec>] + $command->addArgument($this->getSource()); + if ($this->getRefspec()) { + $command->addArgument($this->getRefspec()); + } + $this->log( + sprintf('git-pull: pulling from %s %s', + $this->getSource(), $this->getRefspec()), + Project::MSG_INFO); + } else { + throw new BuildException('No source repository specified'); + } + + $this->log('git-pull command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed.'); + } + + $this->log('git-pull: complete', Project::MSG_INFO); + $this->log('git-pull output: ' . trim($output), Project::MSG_INFO); + + } + + public function setStrategy($strategy) + { + $this->strategy = $strategy; + } + + public function getStrategy() + { + return $this->strategy; + } + + public function setStrategyOption($strategyOption) + { + $this->strategyOption = $strategyOption; + } + + public function getStrategyOption() + { + return $this->strategyOption; + } + + public function setSource($source) + { + $this->source = $source; + } + + public function getSource() + { + return $this->source; + } + + public function setRefspec($spec) + { + $this->refspec = $spec; + } + + public function getRefspec() + { + return $this->refspec; + } + + public function setAll($flag) + { + $this->allRemotes = $flag; + } + + public function getAll() + { + return $this->allRemotes; + } + + public function isAllRemotes() + { + return $this->getAll(); + } + + public function setAppend($flag) + { + $this->append = (boolean)$flag; + } + + public function getAppend() + { + return $this->append; + } + + public function isAppend() + { + return $this->getAppend(); + } + + public function setKeep($flag) + { + $this->keepFiles = $flag; + } + + public function getKeep() + { + return $this->keepFiles; + } + + public function isKeepFiles() + { + return $this->getKeep(); + } + + public function setNoTags($flag) + { + $this->noTags = $flag; + } + + public function getNoTags() + { + return $this->noTags; + } + + public function isNoTags() + { + return $this->getNoTags(); + } + + public function setTags($flag) + { + $this->tags = $flag; + } + + public function getTags() + { + return $this->tags; + } + + public function isTags() + { + return $this->getTags(); + } + + public function setQuiet($flag) + { + $this->quiet = $flag; + } + + public function getQuiet() + { + return $this->quiet; + } + + public function isQuiet() + { + return $this->getQuiet(); + } + + public function setRebase($flag) + { + $this->rebase = (boolean)$flag; + } + + public function getRebase() + { + return $this->rebase; + } + + public function isRebase() + { + return $this->getRebase(); + } + + public function setNoRebase($flag) + { + $this->noRebase = (boolean)$flag; + } + + public function getNoRebase() + { + return $this->noRebase; + } + + public function isNoRebase() + { + return $this->getNoRebase(); + } + + public function setForce($flag) + { + $this->force = $flag; + } + + public function getForce() + { + return $this->force; + } + + public function isForce() + { + return $this->getForce(); + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitPushTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitPushTask.php new file mode 100644 index 00000000..996fa57f --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitPushTask.php @@ -0,0 +1,255 @@ +<?php +/* + * $Id: a01e7e9f6cc92e419e82b4e99e4a45de6a61eba8 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper aroung git-push + * + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: a01e7e9f6cc92e419e82b4e99e4a45de6a61eba8 $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.3 + * @link http://www.kernel.org/pub/software/scm/git/docs/git-push.html + */ +class GitPushTask extends GitBaseTask +{ + /** + * Instead of naming each ref to push, specifies that all refs + * --all key to git-push + * @var boolean + */ + private $allRemotes = false; + + /** + * Mirror to remote repository + * --mirror key to git-push + * @var boolean + */ + private $mirror = false; + + /** + * Same as prefixing repos with colon + * --delete argument to git-push + * @var string + */ + private $delete = false; + + /** + * Push all refs under refs/tags + * --tags key to git-fetch + * @var boolean + */ + private $tags = false; + + /** + * <repository> argument to git-push + * @var string + */ + private $destination = 'origin'; + + /** + * <refspec> argument to git-push + * @var string + */ + private $refspec; + + /** + * --force, -f key to git-push + * @var boolean + */ + private $force = false; + + /** + * --quiet, -q key to git-push + * @var boolean + */ + private $quiet = true; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('push'); + $command + ->setOption('tags', $this->isTags()) + ->setOption('mirror', $this->isMirror()) + ->setOption('delete', $this->isDelete()) + ->setOption('q', $this->isQuiet()) + ->setOption('force', $this->isForce()); + + // set operation target + if ($this->isAllRemotes()) { // --all + $command->setOption('all', true); + $this->log('git-push: push to all refs', Project::MSG_INFO); + } elseif ($this->isMirror()) { // <repository> [<refspec>] + $command->setOption('mirror', true); + $this->log('git-push: mirror all refs', Project::MSG_INFO); + } elseif ($this->getDestination()) { // <repository> [<refspec>] + $command->addArgument($this->getDestination()); + if ($this->getRefspec()) { + $command->addArgument($this->getRefspec()); + } + $this->log( + sprintf('git-push: pushing to %s %s', + $this->getDestination(), $this->getRefspec()), + Project::MSG_INFO); + } else { + throw new BuildException('At least one destination must be provided'); + } + + $this->log('git-push command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + throw new BuildException('Task execution failed.'); + } + + $this->log('git-push: complete', Project::MSG_INFO); + if ($this->isDelete()) { + $this->log('git-push: branch delete requested', Project::MSG_INFO); + } + $this->log('git-push output: ' . trim($output), Project::MSG_INFO); + } + + public function setAll($flag) + { + $this->allRemotes = $flag; + } + + public function getAll() + { + return $this->allRemotes; + } + + public function isAllRemotes() + { + return $this->getAll(); + } + + public function setMirror($flag) + { + $this->mirror = (boolean)$flag; + } + + public function getMirror() + { + return $this->mirror; + } + + public function isMirror() + { + return $this->getMirror(); + } + + public function setDelete($flag) + { + $this->delete = (boolean)$flag; + } + + public function getDelete() + { + return $this->delete; + } + + public function isDelete() + { + return $this->getDelete(); + } + + public function setTags($flag) + { + $this->tags = $flag; + } + + public function getTags() + { + return $this->tags; + } + + public function isTags() + { + return $this->getTags(); + } + + public function setDestination($destination) + { + $this->destination = $destination; + } + + public function getDestination() + { + return $this->destination; + } + + public function setRefspec($spec) + { + $this->refspec = $spec; + } + + public function getRefspec() + { + return $this->refspec; + } + + public function setForce($flag) + { + $this->force = $flag; + } + + public function getForce() + { + return $this->force; + } + + public function isForce() + { + return $this->getForce(); + } + + public function setQuiet($flag) + { + $this->quiet = $flag; + } + + public function getQuiet() + { + return $this->quiet; + } + + public function isQuiet() + { + return $this->getQuiet(); + } + + + + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/git/GitTagTask.php b/buildscripts/phing/classes/phing/tasks/ext/git/GitTagTask.php new file mode 100644 index 00000000..864e71ba --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/git/GitTagTask.php @@ -0,0 +1,406 @@ +<?php +/* + * $Id: 127d4af12e159083935466773d1af788e46acd4e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/git/GitBaseTask.php'; + +/** + * Wrapper around git-tag + * + * @author Evan Kaufman <evan@digitalflophouse.com> + * @author Victor Farazdagi <simple.square@gmail.com> + * @version $Id: 127d4af12e159083935466773d1af788e46acd4e $ + * @package phing.tasks.ext.git + * @see VersionControl_Git + * @since 2.4.5 + */ +class GitTagTask extends GitBaseTask +{ + /** + * Make unsigned, annotated tag object. See -a of git-tag + * @var boolean + */ + private $annotate = false; + + /** + * Make GPG-signed tag. See -s of git-tag + * @var boolean + */ + private $sign = false; + + /** + * Make GPG-signed tag, using given key. See -u of git-tag + * @var string + */ + private $keySign; + + /** + * Replace existing tag with given name. See -f of git-tag + * @var boolean + */ + private $replace = false; + + /** + * Delete existing tags with given names. See -d of git-tag + * @var boolean + */ + private $delete = false; + + /** + * Verify gpg signature of given tag names. See -v of git-tag + * @var boolean + */ + private $verify = false; + + /** + * List tags with names matching given pattern. See -l of git-tag + * @var boolean + */ + private $list = false; + + /** + * <num> specifies how many lines from the annotation, if any, are printed + * when using -l. See -n of git-tag + * @var int + */ + private $num; + + /** + * Only list tags containing specified commit. See --contains of git-tag + * @var string + */ + private $contains; + + /** + * Use given tag message. See -m of git-tag + * @var string + */ + private $message; + + /** + * Take tag message from given file. See -F of git-tag + * @var string + */ + private $file; + + /** + * <tagname> argument to git-tag + * @var string + */ + private $name; + + /** + * <commit> argument to git-tag + * @var string + */ + private $commit; + + /** + * <object> argument to git-tag + * @var string + */ + private $object; + + /** + * <pattern> argument to git-tag + * @var string + */ + private $pattern; + + /** + * Property name to set with output value from git-tag + * @var string + */ + private $outputProperty; + + /** + * The main entry point for the task + */ + public function main() + { + if (null === $this->getRepository()) { + throw new BuildException('"repository" is required parameter'); + } + + $client = $this->getGitClient(false, $this->getRepository()); + $command = $client->getCommand('tag'); + $command + ->setOption('a', $this->isAnnotate()) + ->setOption('s', $this->isSign()) + ->setOption('f', $this->isReplace()) + ->setOption('d', $this->isDelete()) + ->setOption('v', $this->isVerify()) + ->setOption('l', $this->isList()); + + if (null !== $this->getKeySign()) { + $command->setOption('u', $this->getKeySign()); + } + + if (null !== $this->getMessage()) { + $command->setOption('m', $this->getMessage()); + } + + if (null !== $this->getFile()) { + $command->setOption('F', $this->getFile()); + } + + // Use 'name' arg, if relevant + if (null != $this->getName() && false == $this->isList()) { + $command->addArgument($this->getName()); + } + + if (null !== $this->getKeySign() || $this->isAnnotate() || $this->isSign()) { + // Require a tag message or file + if (null === $this->getMessage() && null === $this->getFile()) { + throw new BuildException('"message" or "file" required to make a tag'); + } + } + + // Use 'commit' or 'object' args, if relevant + if (null !== $this->getCommit()) { + $command->addArgument($this->getCommit()); + } else if (null !== $this->getObject()) { + $command->addArgument($this->getObject()); + } + + // Customize list (-l) options + if ($this->isList()) { + if (null !== $this->getContains()) { + $command->setOption('contains', $this->getContains()); + } + if (null !== $this->getPattern()) { + $command->addArgument($this->getPattern()); + } + if (null != $this->getNum()) { + $command->setOption('n', $this->getNum()); + } + } + + $this->log('git-tag command: ' . $command->createCommandString(), Project::MSG_INFO); + + try { + $output = $command->execute(); + } catch (Exception $e) { + $this->log($e->getMessage(), Project::MSG_ERR); + throw new BuildException('Task execution failed. ' . $e->getMessage()); + } + + if (null !== $this->outputProperty) { + $this->project->setProperty($this->outputProperty, $output); + } + + $this->log( + sprintf('git-tag: tags for "%s" repository', $this->getRepository()), + Project::MSG_INFO); + $this->log('git-tag output: ' . trim($output), Project::MSG_INFO); + } + + public function setAnnotate($flag) + { + $this->annotate = (bool)$flag; + } + + public function getAnnotate() + { + return $this->annotate; + } + + public function isAnnotate() + { + return $this->getAnnotate(); + } + + public function setSign($flag) + { + $this->sign = (bool)$flag; + } + + public function getSign() + { + return $this->sign; + } + + public function isSign() + { + return $this->getSign(); + } + + public function setKeySign($keyId) + { + $this->keySign = $keyId; + } + + public function getKeySign() + { + return $this->keySign; + } + + public function setReplace($flag) + { + $this->replace = (bool)$flag; + } + + public function getReplace() + { + return $this->replace; + } + + public function isReplace() + { + return $this->getReplace(); + } + + public function setForce($flag) + { + return $this->setReplace($flag); + } + + public function setDelete($flag) + { + $this->delete = (bool)$flag; + } + + public function getDelete() + { + return $this->delete; + } + + public function isDelete() + { + return $this->getDelete(); + } + + public function setVerify($flag) + { + $this->verify = (bool)$flag; + } + + public function getVerify() + { + return $this->verify; + } + + public function isVerify() + { + return $this->getVerify(); + } + + public function setList($flag) + { + $this->list = (bool)$flag; + } + + public function getList() + { + return $this->list; + } + + public function isList() + { + return $this->getList(); + } + + public function setNum($num) + { + $this->num = (int)$num; + } + + public function getNum() + { + return $this->num; + } + + public function setContains($commit) + { + $this->contains = $commit; + } + + public function getContains() + { + return $this->contains; + } + + public function setMessage($msg) + { + $this->message = $msg; + } + + public function getMessage() + { + return $this->message; + } + + public function setFile($file) + { + $this->file = $file; + } + + public function getFile() + { + return $this->file; + } + + public function setName($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + + public function setCommit($commit) + { + $this->commit = $commit; + } + + public function getCommit() + { + return $this->commit; + } + + public function setObject($object) + { + $this->object = $object; + } + + public function getObject() + { + return $this->object; + } + + public function setPattern($pattern) + { + $this->pattern = $pattern; + } + + public function getPattern() + { + return $this->pattern; + } + + public function setOutputProperty($prop) + { + $this->outputProperty = $prop; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php index 76780fa6..38ec99d4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php @@ -1,6 +1,6 @@ <?php /** - * $Id: IoncubeComment.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: dbbc1b4830ba43116d5b5e5d20c749598eaf62b7 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,23 +22,22 @@ /** * Wrapper for comments for ionCube tasks * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: IoncubeComment.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: dbbc1b4830ba43116d5b5e5d20c749598eaf62b7 $ * @package phing.tasks.ext.ioncube * @since 2.2.0 */ class IoncubeComment { - private $value = ""; - - public function getValue() - { - return $this->value; - } - - public function addText($txt) - { - $this->value = trim($txt); - } + private $value = ""; + + public function getValue() + { + return $this->value; + } + + public function addText($txt) + { + $this->value = trim($txt); + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php index 9eecd5a0..5a31f355 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: IoncubeEncoderTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: a6ce870b3d14be7f365468e3a272e5ac16128e93 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,312 +25,618 @@ require_once 'phing/tasks/ext/ioncube/IoncubeComment.php'; /** * Invokes the ionCube Encoder (PHP4 or PHP5) * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: IoncubeEncoderTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @author Domenico Sgarbossa <sbraaaa@yahoo.it> + * @version $Id: a6ce870b3d14be7f365468e3a272e5ac16128e93 $ * @package phing.tasks.ext.ioncube * @since 2.2.0 */ class IoncubeEncoderTask extends Task { - private $phpVersion = "5"; - private $ioncubePath = "/usr/local/ioncube"; - private $encoderName = "ioncube_encoder"; - - private $fromDir = ""; - private $toDir = ""; - - private $encrypt = ""; - - private $targetOption = ""; - private $binary = false; - private $optimize = ""; - private $withoutRuntimeLoaderSupport = false; - - private $licensePath = ""; - private $passPhrase = ""; - - private $comments = array(); - - /** - * 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); - + private $ionSwitches = array(); + + private $ionOptions = array(); + + private $ionOptionsXS = array(); + + private $comments = array(); + + private $encoderName = 'ioncube_encoder'; + + private $fromDir = ''; + + private $ioncubePath = '/usr/local/ioncube'; + + private $phpVersion = '5'; + + private $targetOption = ''; + + private $toDir = ''; + + private $showCommandLine = false; + + /** + * Sets whether to show command line before it is executed + */ + function setShowCommandLine($value) + { + $this->showCommandLine = $value; + } + + /** + * Adds a comment to be used in encoded files + */ + function addComment(IoncubeComment $comment) + { + $this->comments[] = $comment; + } + + /** + * Sets the allowed server + */ + function setAllowedServer($value) + { + $this->ionOptionsXS['allowed-server'] = $value; + } + + /** + * Returns the allowed server setting + */ + function getAllowedServer() + { + return $this->ionOptionsXS['allowed-server']; + } + + /** + * Sets the binary option + */ + function setBinary($value) + { + $this->ionSwitches['binary'] = $value; + } + + /** + * Returns the binary option + */ + function getBinary() + { + return $this->ionSwitches['binary']; + } + + /** + * Sets files or folders to copy (separated by space) + */ + function setCopy($value) + { + $this->ionOptionsXS['copy'] = $value; + } + + /** + * Returns the copy setting + */ + function getCopy() + { + return $this->ionOptionsXS['copy']; + } + + /** + * Sets additional file patterns, files or directories to encode, + * or to reverse the effect of copy (separated by space) + */ + function setEncode($value) + { + $this->ionOptionsXS['encode'] = $value; + } + + /** + * Returns the encode setting + */ + function getEncode() + { + return $this->ionOptionsXS['encode']; + } + + /** + * Sets regexps of additional files to encrypt (separated by space) + */ + function setEncrypt($value) + { + $this->ionOptionsXS['encrypt'] = $value; + } + + /** + * Returns regexps of additional files to encrypt (separated by space) + */ + function getEncrypt() + { + return $this->ionOptionsXS['encrypt']; + } + + /** + * Sets a period after which the files expire + */ + function setExpirein($value) + { + $this->ionOptions['expire-in'] = $value; + } + + /** + * Returns the expireIn setting + */ + function getExpirein() + { + return $this->ionOptions['expire-in']; + } + + /** + * Sets a YYYY-MM-DD date to expire the files + */ + function setExpireon($value) + { + $this->ionOptions['expire-on'] = $value; + } + + /** + * Returns the expireOn setting + */ + function getExpireon() + { + return $this->ionOptions['expire-on']; + } + + /** + * Sets the source directory + */ + function setFromDir($value) + { + $this->fromDir = $value; + } + + /** + * Returns the source directory + */ + function getFromDir() + { + return $this->fromDir; + } + + /** + * Set files and directories to ignore entirely and exclude from the target directory + * (separated by space). + */ + function setIgnore($value) + { + $this->ionOptionsXS['ignore'] = $value; + } + + /** + * Returns the ignore setting + */ + function getIgnore() + { + return $this->ionOptionsXS['ignore']; + } + + /** + * Sets the path to the ionCube encoder + */ + function setIoncubePath($value) + { + $this->ioncubePath = $value; + } + + /** + * Returns the path to the ionCube encoder + */ + function getIoncubePath() + { + return $this->ioncubePath; + } + + /** + * Set files and directories not to be ignored (separated by space). + */ + function setKeep($value) + { + $this->ionOptionsXS['keep'] = $value; + } + + /** + * Returns the ignore setting + */ + function getKeep() + { + return $this->ionOptionsXS['keep']; + } + + /** + * Sets the path to the license file to use + */ + function setLicensePath($value) + { + $this->ionOptions['with-license'] = $value; + } + + /** + * Returns the path to the license file to use + */ + function getLicensePath() + { + return $this->ionOptions['with-license']; + } + + /** + * Sets the no-doc-comments option + */ + function setNoDocComments($value) + { + $this->ionSwitches['no-doc-comment'] = $value; + } + + /** + * Returns the no-doc-comments option + */ + function getNoDocComments() + { + return $this->ionSwitches['no-doc-comment']; + } + + /** + * Sets the obfuscate option + */ + function setObfuscate($value) + { + $this->ionOptionsXS['obfuscate'] = $value; + } + + /** + * Returns the optimize option + */ + function getObfuscate() + { + return $this->ionOptionsXS['obfuscate']; + } + + /** + * Sets the obfuscation key (required if using the obfuscate option) + */ + function setObfuscationKey($value) + { + $this->ionOptions['obfuscation-key'] = $value; + } + + /** + * Returns the optimize option + */ + function getObfuscationKey() + { + return $this->ionOptions['obfuscation-key']; + } + + /** + * Sets the optimize option + */ + function setOptimize($value) + { + $this->ionOptions['optimize'] = $value; + } + + /** + * Returns the optimize option + */ + function getOptimize() + { + return $this->ionOptions['optimize']; + } + + /** + * Sets the passphrase to use when encoding files + */ + function setPassPhrase($value) + { + $this->ionOptions['passphrase'] = $value; + } + + /** + * Returns the passphrase to use when encoding files + */ + function getPassPhrase() + { + return $this->ionOptions['passphrase']; + } + + /** + * Sets the version of PHP to use (defaults to 5) + */ + function setPhpVersion($value) + { + $this->phpVersion = $value; + } + + /** + * Returns the version of PHP to use (defaults to 5) + */ + function getPhpVersion() + { + return $this->phpVersion; + } + + /** + * Sets the target directory + */ + function setToDir($value) + { + $this->toDir = $value; + } + + /** + * Returns the target directory + */ + function getToDir() + { + return $this->toDir; + } + + /** + * Sets the without-runtime-loader-support option + */ + function setWithoutRuntimeLoaderSupport($value) + { + $this->ionSwitches['without-runtime-loader-support'] = $value; + } + + /** + * Returns the without-runtime-loader-support option + */ + function getWithoutRuntimeLoaderSupport() + { + return $this->ionSwitches['without-runtime-loader-support']; + } + + /** + * Sets the no-short-open-tags option + */ + function setNoShortOpenTags($value) + { + $this->ionSwitches['no-short-open-tags'] = $value; + } + + /** + * Returns the no-short-open-tags option + */ + function getNoShortOpenTags() + { + return $this->ionSwitches['no-short-open-tags']; + } + + /** + * Sets the ignore-deprecated-warnings option + */ + function setIgnoreDeprecatedWarnings($value) + { + $this->ionSwitches['ignore-deprecated-warnings'] = $value; + } + + /** + * Returns the ignore-deprecated-warnings option + */ + function getIgnoreDeprecatedWarnings() + { + return $this->ionSwitches['ignore-deprecated-warnings']; + } + + /** + * Sets the ignore-strict-warnings option + */ + function setIgnoreStrictWarnings($value) + { + $this->ionSwitches['ignore-strict-warnings'] = $value; + } + + /** + * Returns the ignore-strict-warnings option + */ + function getIgnoreStrictWarnings() + { + return $this->ionSwitches['ignore-strict-warnings']; + } + + /** + * Sets the allow-encoding-into-source option + */ + function setAllowEncodingIntoSource($value) + { + $this->ionSwitches['allow-encoding-into-source'] = $value; + } + + /** + * Returns the allow-encoding-into-source option + */ + function getAllowEncodingIntoSource() + { + return $this->ionSwitches['allow-encoding-into-source']; + } + + /** + * Sets the message-if-no-loader option + */ + function setMessageIfNoLoader($value) + { + $this->ionOptions['message-if-no-loader'] = $value; + } + + /** + * Returns the message-if-no-loader option + */ + function getMessageIfNoLoader() + { + return $this->ionOptions['message-if-no-loader']; + } + + /** + * Sets the action-if-no-loader option + */ + function setActionIfNoLoader($value) + { + $this->ionOptions['action-if-no-loader'] = $value; + } + + /** + * Returns the action-if-no-loader option + */ + function getActionIfNoLoader() + { + return $this->ionOptions['action-if-no-loader']; + } + + /** + * Sets the option to use when encoding target directory already exists (defaults to none) + */ + function setTargetOption($targetOption) + { + $this->targetOption = $targetOption; + } + + /** + * Returns he option to use when encoding target directory already exists (defaults to none) + */ + function getTargetOption() + { + return $this->targetOption; + } + + /** + * Sets the callback-file option + */ + function setCallbackFile($value) + { + $this->ionOptions['callback-file'] = $value; + } + + /** + * Returns the callback-file option + */ + function getCallbackFile() + { + return $this->ionOptions['callback-file']; + } + + /** + * Sets the obfuscation-exclusions-file option + */ + function setObfuscationExclusionFile($value) + { + $this->ionOptions['obfuscation-exclusion-file'] = $value; + } + + /** + * Returns the obfuscation-exclusions-file option + */ + function getObfuscationExclusionFile() + { + return $this->ionOptions['obfuscation-exclusion-file']; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $arguments = $this->constructArguments(); + + $encoder = new PhingFile($this->ioncubePath, $this->encoderName . ($this->phpVersion == 5 ? '5' : '')); + + $this->log("Running ionCube Encoder..."); + + if ($this->showCommandLine) + { + $this->log("Command line: ".$encoder->__toString() . ' ' . $arguments); + } + + exec($encoder->__toString() . ' ' . $arguments . " 2>&1", $output, $return); + if ($return != 0) { - throw new BuildException("Could not execute ionCube Encoder: " . implode(' ', $output)); + throw new BuildException("Could not execute ionCube Encoder: " . implode(' ', $output)); } - } - - /** - * Constructs an argument string for the ionCube encoder - */ - private function constructArguments() - { - $arguments = ""; - - if ($this->binary) - { - $arguments.= "--binary "; - } - - if (!empty($this->optimize)) - { - $arguments.= "--optimize " . $this->optimize . " "; - } - - if ($this->withoutRuntimeLoaderSupport) - { - $arguments.= "--without-runtime-loader-support "; - } - - if (!empty($this->targetOption)) - { - switch ($this->targetOption) - { - case "replace": - case "merge": - case "update": - case "rename": - { - $arguments.= "--" . $this->targetOption . "-target "; - } break; - - default: - { - throw new BuildException("Unknown target option '" . $this->targetOption . "'"); - } break; - } - } - - if (!empty($this->encrypt)) - { - foreach (explode(" ", $this->encrypt) as $encrypt) - { - $arguments.= "--encrypt '$encrypt' "; - } - } - - if (!empty($this->licensePath)) - { - $arguments.= "--with-license '" . $this->licensePath . "' "; - } - - 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; - } + } + + /** + * Constructs an argument string for the ionCube encoder + */ + private function constructArguments() + { + $arguments = ''; + + foreach ($this->ionSwitches as $name => $value) + { + if ($value) + { + $arguments.= "--$name "; + } + } + + foreach ($this->ionOptions as $name => $value) + { + /** + * action-if-no-loader value is a php source snippet so it is + * better to handle it this way to prevent quote problems! + */ + if ($name == 'action-if-no-loader') + { + $arguments.= "--$name \"$value\" "; + } + else + { + $arguments.= "--$name '$value' "; + } + } + + foreach ($this->ionOptionsXS as $name => $value) + { + foreach (explode(' ', $value) as $arg) + { + $arguments.= "--$name '$arg' "; + } + } + + foreach ($this->comments as $comment) + { + $arguments.= "--add-comment '" . $comment->getValue() . "' "; + } + + if (!empty($this->targetOption)) + { + switch ($this->targetOption) + { + case "replace": + case "merge": + case "update": + case "rename": + { + $arguments.= "--" . $this->targetOption . "-target "; + } break; + + default: + { + throw new BuildException("Unknown target option '" . $this->targetOption . "'"); + } break; + } + } + + if ($this->fromDir != '') + { + $arguments .= $this->fromDir . ' '; + } + + if ($this->toDir != '') + { + $arguments .= "-o " . $this->toDir . ' '; + } + + return $arguments; + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php index 70abd544..6e7ab68a 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: IoncubeLicenseTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 555e4853cd742e4ef733e3df4051c49cda527b73 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,120 +25,184 @@ require_once 'phing/tasks/ext/ioncube/IoncubeComment.php'; /** * Invokes the ionCube "make_license" program * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: IoncubeLicenseTask.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 555e4853cd742e4ef733e3df4051c49cda527b73 $ * @package phing.tasks.ext.ioncube * @since 2.2.0 */ class IoncubeLicenseTask extends Task { - private $ioncubePath = "/usr/local/ioncube"; - - private $licensePath = ""; - private $passPhrase = ""; - - private $comments = array(); - - /** - * Sets the path to the ionCube encoder - */ - function setIoncubePath($ioncubePath) - { - $this->ioncubePath = $ioncubePath; - } + private $ioncubePath = "/usr/local/ioncube"; + + private $licensePath = ""; + private $passPhrase = ""; + private $allowedServer = ""; + private $expireOn = ""; + private $expireIn = ""; + private $comments = array(); - /** - * Returns the path to the ionCube encoder - */ - function getIoncubePath() - { - return $this->ioncubePath; - } + /** + * Sets the path to the ionCube encoder + */ + function setIoncubePath($ioncubePath) + { + $this->ioncubePath = $ioncubePath; + } - /** - * Sets the path to the license file to use - */ - function setLicensePath($licensePath) - { - $this->licensePath = $licensePath; - } + /** + * Returns the path to the ionCube encoder + */ + function getIoncubePath() + { + return $this->ioncubePath; + } - /** - * Returns the path to the license file to use - */ - function getLicensePath() - { - return $this->licensePath; - } + /** + * Sets the path to the license file to use + */ + function setLicensePath($licensePath) + { + $this->licensePath = $licensePath; + } - /** - * Sets the passphrase to use when encoding files - */ - function setPassPhrase($passPhrase) - { - $this->passPhrase = $passPhrase; - } + /** + * Returns the path to the license file to use + */ + function getLicensePath() + { + return $this->licensePath; + } - /** - * Returns the passphrase to use when encoding files - */ - function getPassPhrase() - { - return $this->passPhrase; - } + /** + * Sets the passphrase to use when encoding files + */ + function setPassPhrase($passPhrase) + { + $this->passPhrase = $passPhrase; + } - /** - * Adds a comment to be used in encoded files - */ - function addComment(IoncubeComment $comment) - { - $this->comments[] = $comment; - } + /** + * Returns the passphrase to use when encoding files + */ + function getPassPhrase() + { + return $this->passPhrase; + } - /** - * 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); - + /** + * Adds a comment to be used in encoded files + */ + function addComment(IoncubeComment $comment) + { + $this->comments[] = $comment; + } + + /** + * Sets the --allowed-server option to use when generating the license + */ + function setAllowedServer($allowedServer) + { + $this->allowedServer = $allowedServer; + } + + /** + * Returns the --allowed-server option + */ + function getAllowedServer() + { + return $this->allowedServer; + } + + /** + * Sets the --expire-on option to use when generating the license + */ + function setExpireOn($expireOn) + { + $this->expireOn = $expireOn; + } + + /** + * Returns the --expire-on option + */ + function getExpireOn() + { + return $this->expireOn; + } + + /** + * Sets the --expire-in option to use when generating the license + */ + function setExpireIn($expireIn) + { + $this->expireIn = $expireIn; + } + + /** + * Returns the --expire-in option + */ + function getExpireIn() + { + return $this->expireIn; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $arguments = $this->constructArguments(); + + $makelicense = new PhingFile($this->ioncubePath, 'make_license'); + + $this->log("Running ionCube make_license..."); + + exec($makelicense->__toString() . " " . $arguments . " 2>&1", $output, $return); + if ($return != 0) { - throw new BuildException("Could not execute ionCube make_license: " . implode(' ', $output)); + throw new BuildException("Could not execute ionCube make_license: " . implode(' ', $output)); } - } + } + + /** + * Constructs an argument string for the ionCube make_license + */ + private function constructArguments() + { + $arguments = ""; + + if (!empty($this->passPhrase)) + { + $arguments.= "--passphrase '" . $this->passPhrase . "' "; + } + + foreach ($this->comments as $comment) + { + $arguments.= "--header-line '" . $comment->getValue() . "' "; + } + + if (!empty($this->licensePath)) + { + $arguments.= "--o '" . $this->licensePath . "' "; + } - /** - * Constructs an argument string for the ionCube make_license - */ - private function constructArguments() + if (!empty($this->allowedServer)) { - $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; + $arguments.= "--allowed-server {" . $this->allowedServer . "} "; } + + if (!empty($this->expireOn)) + { + $arguments.= "--expire-on " . $this->expireOn . " "; + } + + if (!empty($this->expireIn)) + { + $arguments.= "--expire-in " . $this->expireIn . " "; + } + + return $arguments; + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMin.php b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMin.php new file mode 100644 index 00000000..44766fc1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMin.php @@ -0,0 +1,292 @@ +<?php
+/**
+ * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
+ *
+ * This is pretty much a direct port of jsmin.c to PHP with just a few
+ * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
+ * outputs to stdout, this library accepts a string as input and returns another
+ * string as output.
+ *
+ * PHP 5 or higher is required.
+ *
+ * Permission is hereby granted to use this version of the library under the
+ * same terms as jsmin.c, which has the following license:
+ *
+ * --
+ * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * The Software shall be used for Good, not Evil.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * --
+ *
+ * @package JSMin
+ * @author Ryan Grove <ryan@wonko.com>
+ * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
+ * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
+ * @license http://opensource.org/licenses/mit-license.php MIT License
+ * @version 1.1.1 (2008-03-02)
+ * @link http://code.google.com/p/jsmin-php/
+ */
+
+class JSMin {
+ const ORD_LF = 10;
+ const ORD_SPACE = 32;
+
+ protected $a = '';
+ protected $b = '';
+ protected $input = '';
+ protected $inputIndex = 0;
+ protected $inputLength = 0;
+ protected $lookAhead = null;
+ protected $output = '';
+
+ // -- Public Static Methods --------------------------------------------------
+
+ public static function minify($js) {
+ $jsmin = new JSMin($js);
+ return $jsmin->min();
+ }
+
+ // -- Public Instance Methods ------------------------------------------------
+
+ public function __construct($input) {
+ $this->input = str_replace("\r\n", "\n", $input);
+ $this->inputLength = strlen($this->input);
+ }
+
+ // -- Protected Instance Methods ---------------------------------------------
+
+ protected function action($d) {
+ switch($d) {
+ case 1:
+ $this->output .= $this->a;
+
+ case 2:
+ $this->a = $this->b;
+
+ if ($this->a === "'" || $this->a === '"') {
+ for (;;) {
+ $this->output .= $this->a;
+ $this->a = $this->get();
+
+ if ($this->a === $this->b) {
+ break;
+ }
+
+ if (ord($this->a) <= self::ORD_LF) {
+ throw new JSMinException('Unterminated string literal.');
+ }
+
+ if ($this->a === '\\') {
+ $this->output .= $this->a;
+ $this->a = $this->get();
+ }
+ }
+ }
+
+ case 3:
+ $this->b = $this->next();
+
+ if ($this->b === '/' && (
+ $this->a === '(' || $this->a === ',' || $this->a === '=' ||
+ $this->a === ':' || $this->a === '[' || $this->a === '!' ||
+ $this->a === '&' || $this->a === '|' || $this->a === '?')) {
+
+ $this->output .= $this->a . $this->b;
+
+ for (;;) {
+ $this->a = $this->get();
+
+ if ($this->a === '/') {
+ break;
+ } elseif ($this->a === '\\') {
+ $this->output .= $this->a;
+ $this->a = $this->get();
+ } elseif (ord($this->a) <= self::ORD_LF) {
+ throw new JSMinException('Unterminated regular expression '.
+ 'literal.');
+ }
+
+ $this->output .= $this->a;
+ }
+
+ $this->b = $this->next();
+ }
+ }
+ }
+
+ protected function get() {
+ $c = $this->lookAhead;
+ $this->lookAhead = null;
+
+ if ($c === null) {
+ if ($this->inputIndex < $this->inputLength) {
+ $c = $this->input[$this->inputIndex];
+ $this->inputIndex += 1;
+ } else {
+ $c = null;
+ }
+ }
+
+ if ($c === "\r") {
+ return "\n";
+ }
+
+ if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
+ return $c;
+ }
+
+ return ' ';
+ }
+
+ protected function isAlphaNum($c) {
+ return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
+ }
+
+ protected function min() {
+ $this->a = "\n";
+ $this->action(3);
+
+ while ($this->a !== null) {
+ switch ($this->a) {
+ case ' ':
+ if ($this->isAlphaNum($this->b)) {
+ $this->action(1);
+ } else {
+ $this->action(2);
+ }
+ break;
+
+ case "\n":
+ switch ($this->b) {
+ case '{':
+ case '[':
+ case '(':
+ case '+':
+ case '-':
+ $this->action(1);
+ break;
+
+ case ' ':
+ $this->action(3);
+ break;
+
+ default:
+ if ($this->isAlphaNum($this->b)) {
+ $this->action(1);
+ }
+ else {
+ $this->action(2);
+ }
+ }
+ break;
+
+ default:
+ switch ($this->b) {
+ case ' ':
+ if ($this->isAlphaNum($this->a)) {
+ $this->action(1);
+ break;
+ }
+
+ $this->action(3);
+ break;
+
+ case "\n":
+ switch ($this->a) {
+ case '}':
+ case ']':
+ case ')':
+ case '+':
+ case '-':
+ case '"':
+ case "'":
+ $this->action(1);
+ break;
+
+ default:
+ if ($this->isAlphaNum($this->a)) {
+ $this->action(1);
+ }
+ else {
+ $this->action(3);
+ }
+ }
+ break;
+
+ default:
+ $this->action(1);
+ break;
+ }
+ }
+ }
+
+ return $this->output;
+ }
+
+ protected function next() {
+ $c = $this->get();
+
+ if ($c === '/') {
+ switch($this->peek()) {
+ case '/':
+ for (;;) {
+ $c = $this->get();
+
+ if (ord($c) <= self::ORD_LF) {
+ return $c;
+ }
+ }
+
+ case '*':
+ $this->get();
+
+ for (;;) {
+ switch($this->get()) {
+ case '*':
+ if ($this->peek() === '/') {
+ $this->get();
+ return ' ';
+ }
+ break;
+
+ case null:
+ throw new JSMinException('Unterminated comment.');
+ }
+ }
+
+ default:
+ return $c;
+ }
+ }
+
+ return $c;
+ }
+
+ protected function peek() {
+ $this->lookAhead = $this->get();
+ return $this->lookAhead;
+ }
+}
+
+/**
+ * @package JSMin
+ */
+class JSMinException extends Exception {}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMinTask.php b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMinTask.php new file mode 100644 index 00000000..26202942 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/jsmin/JsMinTask.php @@ -0,0 +1,145 @@ +<?php
+/*
+ * $Id: 4a9a75fcd969cfc4e26a7f2c78836389e8be7864 $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/tasks/ext/jsmin/JsMin.php';
+
+/**
+ * Task to minify javascript files.
+ *
+ * Requires JSMin which can be found at http://code.google.com/p/jsmin-php/ but
+ * is bundled with Phing so no additional install of JsMin is required.
+ *
+ * @author Frank Kleine <mikey@stubbles.net>
+ * @version $Id: 4a9a75fcd969cfc4e26a7f2c78836389e8be7864 $
+ * @package phing.tasks.ext
+ * @since 2.3.0
+ */
+class JsMinTask extends Task
+{
+ /**
+ * the source files
+ *
+ * @var FileSet
+ */
+ protected $filesets = array();
+ /**
+ * Whether the build should fail, if
+ * errors occured
+ *
+ * @var boolean
+ */
+ protected $failonerror = false;
+
+ /**
+ * Define if the target should use or not a suffix -min
+ *
+ * @var boolean
+ */
+ protected $suffix = '-min';
+
+ /**
+ * directory to put minified javascript files into
+ *
+ * @var string
+ */
+ protected $targetDir;
+
+ /**
+ * Nested creator, adds a set of files (nested fileset attribute).
+ */
+ public function createFileSet()
+ {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num - 1];
+ }
+
+ /**
+ * Whether the build should fail, if an error occured.
+ *
+ * @param boolean $value
+ */
+ public function setFailonerror($value)
+ {
+ $this->failonerror = $value;
+ }
+
+ /**
+ * Define if the task should or not use a suffix (-min is the default)
+ *
+ * @param string $value
+ */
+ public function setSuffix($value)
+ {
+ $this->suffix = $value;
+ }
+
+ /**
+ * sets the directory where minified javascript files should be put inot
+ *
+ * @param string $targetDir
+ */
+ public function setTargetDir($targetDir)
+ {
+ $this->targetDir = $targetDir;
+ }
+
+ /**
+ * The init method: Do init steps.
+ */
+ public function init()
+ {
+ return true;
+ }
+
+ /**
+ * The main entry point method.
+ */
+ public function main()
+ {
+ foreach ($this->filesets as $fs) {
+ try {
+ $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles();
+ $fullPath = realpath($fs->getDir($this->project));
+ foreach ($files as $file) {
+ $this->log('Minifying file ' . $file);
+ try {
+ $target = $this->targetDir . '/' . str_replace($fullPath, '', str_replace('.js', $this->suffix . '.js', $file));
+ if (file_exists(dirname($target)) === false) {
+ mkdir(dirname($target), 0700, true);
+ }
+
+ file_put_contents($target, JSMin::minify(file_get_contents($fullPath . '/' . $file)));
+ } catch (JSMinException $jsme) {
+ $this->log("Could not minify file $file: " . $jsme->getMessage(), Project::MSG_ERR);
+ }
+ }
+ } catch (BuildException $be) {
+ // directory doesn't exist or is not readable
+ if ($this->failonerror) {
+ throw $be;
+ } else {
+ $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
+ }
+ }
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php new file mode 100755 index 00000000..fbda3ecc --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php @@ -0,0 +1,184 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/system/ExecTask.php'; + +/** + * Abstract Liquibase task. Base class for all Liquibase Phing tasks. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +abstract class AbstractLiquibaseTask extends Task +{ + protected $jar; + protected $changeLogFile; + protected $username; + protected $password; + protected $url; + protected $classpathref; + + + /** + * Sets the absolute path to liquibase jar. + * + * @param string the absolute path to the liquibase jar. + */ + public function setJar($jar) + { + $this->jar = $jar; + } + + + /** + * Sets the absolute path to the changelog file to use. + * + * @param string the absolute path to the changelog file + */ + public function setChangeLogFile($changelogFile) + { + $this->changeLogFile = $changelogFile; + } + + + /** + * Sets the username to connect to the database. + * + * @param string the username + */ + public function setUsername($username) + { + $this->username = $username; + } + + + /** + * Sets the password to connect to the database. + * + * @param string the password + */ + public function setPassword($password) + { + $this->password = $password; + } + + + /** + * Sets the url to connect to the database in jdbc style, e.g. + * <code> + * jdbc:postgresql://psqlhost/mydatabase + * </code> + * + * @param string jdbc connection string + */ + public function setUrl($url) + { + $this->url = $url; + } + + + /** + * Sets the Java classpathref. + * + * @param string A reference to the classpath that contains the database + * driver, liquibase.jar, and the changelog.xml file + */ + public function setclasspathref($classpathref) + { + $this->classpathref = $classpathref; + } + + + /** + * Ensure that correct parameters were passed in. + * + * @return void + */ + protected function checkParams() + { + if((null === $this->jar) or !file_exists($this->jar)) + { + throw new BuildException( + sprintf( + 'Specify the name of the LiquiBase.jar. "%s" does not exist!', + $this->jar + ) + ); + } + + if((null === $this->changeLogFile) or !file_exists($this->changeLogFile)) + { + throw new BuildException( + sprintf( + 'Specify the name of the Changelog file. "%s" does not exist!', + $this->changeLogFile + ) + ); + } + + if(null === $this->classpathref) + { + throw new BuildException('Please provide a classpath!'); + } + + if(null === $this->username) + { + throw new BuildException('Please provide a username for database acccess!'); + } + + if(null === $this->password) + { + throw new BuildException('Please provide a password for database acccess!'); + } + + if(null === $this->url) + { + throw new BuildException('Please provide a url for database acccess!'); + } + } + + + /** + * Executes the given command and returns the output. + * + * @param string the command to execute + * @param string additional parameters + * @return string the output of the executed command + */ + protected function execute($lbcommand, $lbparams = '') + { + $command = sprintf( + 'java -jar %s --changeLogFile=%s --url=%s --username=%s --password=%s --classpath=%s %s %s', + escapeshellarg($this->jar), + escapeshellarg($this->changeLogFile), + escapeshellarg($this->url), + escapeshellarg($this->username), + escapeshellarg($this->password), + escapeshellarg($this->classpathref), + escapeshellarg($lbcommand), + $lbparams + ); + + passthru($command); + + return; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php new file mode 100755 index 00000000..77fb97d2 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php @@ -0,0 +1,39 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to create a changelog file. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseChangeLogTask extends AbstractLiquibaseTask +{ + /** + * @see Task::main() + */ + public function main() + { + $this->checkParams(); + $this->execute('generateChangeLog'); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php new file mode 100755 index 00000000..e79fae92 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php @@ -0,0 +1,86 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to create a javadoc-like documentation based on current database and + * changelog. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseDbDocTask extends AbstractLiquibaseTask +{ + protected $outputDir; + + + /** + * Sets the output directory where the documentation gets generated to. + * + * @param string the output directory + */ + public function setOutputDir($outputDir) + { + $this->outputDir = $outputDir; + } + + + /** + * @see AbstractTask::checkParams() + */ + protected function checkParams() + { + parent::checkParams(); + + if((null === $this->outputDir) or !is_dir($this->outputDir)) + { + if(!mkdir($this->outputDir, 0777, true)) + { + throw new BuildException( + sprintf( + 'The directory "%s" does not exist and could not be created!', + $this->outputDir + ) + ); + } + } + + if(!is_writable($this->outputDir)) + { + throw new BuildException( + sprintf( + 'The directory "%s" is not writable!', + $this->outputDir + ) + ); + } + } + + + /** + * @see Task::main() + */ + public function main() + { + $this->checkParams(); + $this->execute('dbdoc', escapeshellarg($this->outputDir)); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php new file mode 100755 index 00000000..847f1401 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php @@ -0,0 +1,137 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to create the diff between two databases. Will output the changes needed + * to convert the reference database to the database. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseDiffTask extends AbstractLiquibaseTask +{ + protected $referenceUsername; + protected $referencePassword; + protected $referenceUrl; + + + /** + * Sets the username to connect to the reference database. + * + * @param string the username + */ + public function setReferenceUsername($username) + { + $this->referenceUsername = $username; + } + + + /** + * Sets the password to connect to the refernce database. + * + * @param string the password + */ + public function setReferencePassword($password) + { + $this->referencePassword = $password; + } + + + /** + * Sets the url to connect to the reference database in jdbc style, e.g. + * <code> + * jdbc:postgresql://psqlhost/myrefdatabase + * </code> + * + * @param string jdbc connection string + */ + public function setReferenceUrl($url) + { + $this->referenceUrl = $url; + } + + + /** + * @see AbstractTask::checkParams() + */ + protected function checkParams() + { + parent::checkParams(); + + if(null === $this->referenceUsername) + { + throw new BuildException('Please provide a username for the reference database acccess!'); + } + + if(null === $this->referencePassword) + { + throw new BuildException('Please provide a password for the reference database acccess!'); + } + + if(null === $this->referenceUrl) + { + throw new BuildException('Please provide a url for the reference database acccess!'); + } + } + + + /** + * @see Task::main() + */ + public function main() + { + $this->checkParams(); + + $refparams = sprintf( + '--referenceUsername=%s --referencePassword=%s --referenceUrl=%s', + escapeshellarg($this->referenceUsername), + escapeshellarg($this->referencePassword), + escapeshellarg($this->referenceUrl) + ); + + // save main changelog file + $changelogFile = $this->changeLogFile; + + // set the name of the new generated changelog file + $this->setChangeLogFile(dirname($changelogFile).'/diffs/'.date('YmdHis').'.xml'); + if(!is_dir(dirname($changelogFile).'/diffs/')) + { + mkdir(dirname($changelogFile).'/diffs/', 0777, true); + } + $this->execute('diffChangeLog', $refparams); + + $xmlFile = new DOMDocument(); + $xmlFile->load($changelogFile); + + // create the new node + $rootNode = $xmlFile->getElementsByTagName('databaseChangeLog')->item(0); + $includeNode = $rootNode->appendChild($xmlFile->createElement('include')); + + // set the attributes for the new node + $includeNode->setAttribute('file', str_replace(dirname($changelogFile).'/', '', $this->changeLogFile)); + $includeNode->setAttribute('relativeToChangelogFile', 'true'); + file_put_contents($changelogFile, $xmlFile->saveXML()); + + $this->setChangeLogFile($changelogFile); + $this->execute('markNextChangeSetRan'); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php new file mode 100755 index 00000000..ec5584e6 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php @@ -0,0 +1,72 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Rollbacks the database changes. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseRollbackTask extends AbstractLiquibaseTask +{ + protected $rollbackTag; + + + /** + * Sets the name of the tag to roll back to. + * + * @param string the name to roll back to + */ + public function setRollbackTag($rollbackTag) + { + $this->rollbackTag = $rollbackTag; + } + + + /** + * @see AbstractTask::checkParams() + */ + protected function checkParams() + { + parent::checkParams(); + + if(null === $this->rollbackTag) + { + throw new BuildException( + sprintf( + 'Please specify the tag to rollback to!', + $this->rollbackTag + ) + ); + } + } + + + /** + * @see Task::main() + */ + public function main() + { + $this->checkParams(); + $this->execute('rollback', escapeshellarg($this->rollbackTag)); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseTagTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseTagTask.php new file mode 100755 index 00000000..07b0e72e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseTagTask.php @@ -0,0 +1,75 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to tag the current database state. In case you tag the database multiple + * times without applying a new changelog before, the tags will overwrite each + * other! + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseTagTask extends AbstractLiquibaseTask +{ + protected $tag; + + + /** + * Sets the name of tag which is used to mark the database state for + * possible future rollback. + * + * @param string the name to tag the database with + */ + public function setTag($tag) + { + $this->tag = $tag; + } + + + /** + * @see AbstractTask::checkParams() + */ + protected function checkParams() + { + parent::checkParams(); + + if(null === $this->tag) + { + throw new BuildException( + sprintf( + 'Please specify the tag!', + $this->tag + ) + ); + } + } + + + /** + * @see Task::main() + */ + public function main() + { + $this->checkParams(); + $this->execute('tag', escapeshellarg($this->tag)); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.php b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.php new file mode 100755 index 00000000..35162e4d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.php @@ -0,0 +1,39 @@ +<?php + +/** + * Copyright (c) 2007-2011 bitExpert AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +require_once 'phing/tasks/ext/liquibase/AbstractLiquibaseTask.php'; + +/** + * Task to update the database to latest version of the changelog file. + * + * @author Stephan Hochdoerfer <S.Hochdoerfer@bitExpert.de> + * @version $Id$ + * @since 2.4.10 + * @package phing.tasks.ext.liquibase + */ +class LiquibaseUpdateTask extends AbstractLiquibaseTask +{ + /** + * @see Task::main() + */ + public function main() + { + $this->checkParams(); + $this->execute('update'); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php new file mode 100644 index 00000000..53286f46 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php @@ -0,0 +1,109 @@ +<?php +/** + * $Id: f3a492fa25b203d3263e3463c1ab522c61bd0a9c $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; + +/** + * Analyzer element for the PhpDependTask + * + * @package phing.tasks.ext.pdepend + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: f3a492fa25b203d3263e3463c1ab522c61bd0a9c $ + * @since 2.4.1 + */ +class PhpDependAnalyzerElement +{ + /** + * The type of the analyzer + * + * @var string + */ + protected $_type = ''; + + /** + * The value(s) for the analyzer option + * + * @var array + */ + protected $_value = array(); + + /** + * Sets the analyzer type + * + * @param string $type Type of the analyzer + * + * @return void + */ + public function setType($type) + { + $this->_type = $type; + + switch ($this->_type) { + case 'coderank-mode': + break; + + default: + throw new BuildException( + "Analyzer '" . $this->_type . "' not implemented" + ); + } + } + + /** + * Get the analyzer type + * + * @return string + */ + public function getType() + { + return $this->_type; + } + + /** + * Sets the value for the analyzer + * + * @param string $value Value for the analyzer + * + * @return void + */ + public function setValue($value) + { + $this->_value = array(); + + $token = ' ,;'; + $values = strtok($value, $token); + + while ($values !== false) { + $this->_value[] = $values; + $values = strtok($token); + } + } + + /** + * Get the analyzer value + * + * @return string + */ + public function getValue() + { + return $this->_value; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php new file mode 100644 index 00000000..619f7377 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php @@ -0,0 +1,105 @@ +<?php +/** + * $Id: 6aa728f12c6a9b89fb93cfd39908918937a6d5f9 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; + +/** + * Logger element for the PhpDependTask. + * + * @package phing.tasks.ext.pdepend + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 6aa728f12c6a9b89fb93cfd39908918937a6d5f9 $ + * @since 2.4.1 + */ +class PhpDependLoggerElement +{ + /** + * The type of the logger. + * + * @var string + */ + protected $_type = ''; + + /** + * Output file for logger. + * + * @var PhingFile + */ + protected $_outfile = null; + + /** + * Sets the logger type. + * + * @param string $type Type of the logger + * + * @return void + */ + public function setType($type) + { + $this->_type = $type; + + switch ($this->_type) { + case 'jdepend-chart': + case 'jdepend-xml': + case 'overview-pyramid': + case 'phpunit-xml': + case 'summary-xml': + break; + + default: + throw new BuildException( + "Logger '" . $this->_type . "' not implemented" + ); + } + } + + /** + * Get the logger type + * + * @return string + */ + public function getType() + { + return $this->_type; + } + + /** + * Sets the output file for the logger results. + * + * @param PhingFile $outfile The output file + * + * @return void + */ + public function setOutfile(PhingFile $outfile) + { + $this->_outfile = $outfile; + } + + /** + * Get the output file. + * + * @return PhingFile + */ + public function getOutfile() + { + return $this->_outfile; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependTask.php b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependTask.php new file mode 100644 index 00000000..c42575b7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdepend/PhpDependTask.php @@ -0,0 +1,506 @@ +<?php +/** + * $Id: 572bbfe2e542b864211a85de9990f5cbfe31a4cd $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * Runs the PHP_Depend software analyzer and metric tool. + * Performs static code analysis on a given source base. + * + * @package phing.tasks.ext.pdepend + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 572bbfe2e542b864211a85de9990f5cbfe31a4cd $ + * @since 2.4.1 + */ +class PhpDependTask extends Task +{ + /** + * A php source code filename or directory + * + * @var PhingFile + */ + protected $_file = null; + + /** + * All fileset objects assigned to this task + * + * @var array<FileSet> + */ + protected $_filesets = array(); + + /** + * List of allowed file extensions. Default file extensions are <b>php</b> + * and <p>php5</b>. + * + * @var array<string> + */ + protected $_allowedFileExtensions = array('php', 'php5'); + + /** + * List of exclude directories. Default exclude dirs are <b>.git</b>, + * <b>.svn</b> and <b>CVS</b>. + * + * @var array<string> + */ + protected $_excludeDirectories = array('.git', '.svn', 'CVS'); + + /** + * List of exclude packages + * + * @var array<string> + */ + protected $_excludePackages = array(); + + /** + * Should the parse ignore doc comment annotations? + * + * @var boolean + */ + protected $_withoutAnnotations = false; + + /** + * Should PHP_Depend treat <b>+global</b> as a regular project package? + * + * @var boolean + */ + protected $_supportBadDocumentation = false; + + /** + * Flag for enable/disable debugging + * + * @var boolean + */ + protected $_debug = false; + + /** + * PHP_Depend configuration file + * + * @var PhingFile + */ + protected $_configFile = null; + + /** + * Logger elements + * + * @var array<PhpDependLoggerElement> + */ + protected $_loggers = array(); + + /** + * Analyzer elements + * + * @var array<PhpDependAnalyzerElement> + */ + protected $_analyzers = array(); + + /** + * Holds the PHP_Depend runner instance + * + * @var PHP_Depend_TextUI_Runner + */ + protected $_runner = null; + + /** + * Flag that determines whether to halt on error + * + * @var boolean + */ + protected $_haltonerror = false; + + /** + * Load the necessary environment for running PHP_Depend + * + * @return void + * @throws BuildException + */ + public function init() + { + /** + * Determine PHP_Depend installation + */ + @include_once 'PHP/Depend/TextUI/Runner.php'; + + if (! class_exists('PHP_Depend_TextUI_Runner')) { + throw new BuildException( + 'PhpDependTask depends on PHP_Depend being installed ' + . 'and on include_path', + $this->getLocation() + ); + } + + /** + * Other dependencies that should only be loaded + * when class is actually used + */ + require_once 'phing/tasks/ext/pdepend/PhpDependLoggerElement.php'; + require_once 'phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php'; + require_once 'PHP/Depend/Autoload.php'; + } + + /** + * Set the input source file or directory + * + * @param PhingFile $file The input source file or directory + * + * @return void + */ + public function setFile(PhingFile $file) + { + $this->_file = $file; + } + + /** + * Nested creator, adds a set of files (nested fileset attribute) + * + * @return FileSet The created fileset object + */ + public function createFileSet() + { + $num = array_push($this->_filesets, new FileSet()); + return $this->_filesets[$num-1]; + } + + /** + * Sets a list of filename extensions for valid php source code files + * + * @param string $fileExtensions List of valid file extensions + * + * @return void + */ + public function setAllowedFileExtensions($fileExtensions) + { + $this->_allowedFileExtensions = array(); + + $token = ' ,;'; + $ext = strtok($fileExtensions, $token); + + while ($ext !== false) { + $this->_allowedFileExtensions[] = $ext; + $ext = strtok($token); + } + } + + /** + * Sets a list of exclude directories + * + * @param string $excludeDirectories List of exclude directories + * + * @return void + */ + public function setExcludeDirectories($excludeDirectories) + { + $this->_excludeDirectories = array(); + + $token = ' ,;'; + $pattern = strtok($excludeDirectories, $token); + + while ($pattern !== false) { + $this->_excludeDirectories[] = $pattern; + $pattern = strtok($token); + } + } + + /** + * Sets a list of exclude packages + * + * @param string $excludePackages Exclude packages + * + * @return void + */ + public function setExcludePackages($excludePackages) + { + $this->_excludePackages = array(); + + $token = ' ,;'; + $pattern = strtok($excludePackages, $token); + + while ($pattern !== false) { + $this->_excludePackages[] = $pattern; + $pattern = strtok($token); + } + } + + /** + * Should the parser ignore doc comment annotations? + * + * @param boolean $withoutAnnotations + * + * @return void + */ + public function setWithoutAnnotations($withoutAnnotations) + { + $this->_withoutAnnotations = StringHelper::booleanValue( + $withoutAnnotations + ); + } + + /** + * Should PHP_Depend support projects with a bad documentation. If this + * option is set to <b>true</b>, PHP_Depend will treat the default package + * <b>+global</b> as a regular project package. + * + * @param boolean $supportBadDocumentation + * + * @return void + */ + public function setSupportBadDocumentation($supportBadDocumentation) + { + $this->_supportBadDocumentation = StringHelper::booleanValue( + $supportBadDocumentation + ); + } + + /** + * Set debugging On/Off + * + * @param boolean $debug + * + * @return void + */ + public function setDebug($debug) + { + $this->_debug = StringHelper::booleanValue($debug); + } + + /** + * Set halt on error + * + * @param boolean $haltonerror + * + * @return void + */ + public function setHaltonerror($haltonerror) + { + $this->_haltonerror = StringHelper::booleanValue($haltonerror); + } + + /** + * Set the configuration file + * + * @param PhingFile $configFile The configuration file + * + * @return void + */ + public function setConfigFile(PhingFile $configFile) + { + $this->_configFile = $configFile; + } + + /** + * Create object for nested logger element + * + * @return PhpDependLoggerElement + */ + public function createLogger() + { + $num = array_push($this->_loggers, new PhpDependLoggerElement()); + return $this->_loggers[$num-1]; + } + + /** + * Create object for nested analyzer element + * + * @return PhpDependAnalyzerElement + */ + public function createAnalyzer() + { + $num = array_push($this->_analyzers, new PhpDependAnalyzerElement()); + return $this->_analyzers[$num-1]; + } + + /** + * Executes PHP_Depend_TextUI_Runner against PhingFile or a FileSet + * + * @return void + * @throws BuildException + */ + public function main() + { + $autoload = new PHP_Depend_Autoload(); + $autoload->register(); + + if (!isset($this->_file) and count($this->_filesets) == 0) { + throw new BuildException( + "Missing either a nested fileset or attribute 'file' set" + ); + } + + if (count($this->_loggers) == 0) { + throw new BuildException("Missing nested 'logger' element"); + } + + $this->validateLoggers(); + $this->validateAnalyzers(); + + $filesToParse = array(); + + if ($this->_file instanceof PhingFile) { + $filesToParse[] = $this->_file->__toString(); + } else { + // append any files in filesets + foreach ($this->_filesets as $fs) { + $files = $fs->getDirectoryScanner($this->project) + ->getIncludedFiles(); + + foreach ($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $filesToParse[] = $f->getAbsolutePath(); + } + } + } + + $this->_runner = new PHP_Depend_TextUI_Runner(); + $this->_runner->addProcessListener(new PHP_Depend_TextUI_ResultPrinter()); + + $configurationFactory = new PHP_Depend_Util_Configuration_Factory(); + $configuration = $configurationFactory->createDefault(); + $this->_runner->setConfiguration($configuration); + + $this->_runner->setSourceArguments($filesToParse); + + foreach ($this->_loggers as $logger) { + // Register logger + $this->_runner->addLogger( + $logger->getType(), + $logger->getOutfile()->__toString() + ); + } + + foreach ($this->_analyzers as $analyzer) { + // Register additional analyzer + $this->_runner->addOption( + $analyzer->getType(), + $analyzer->getValue() + ); + } + + // Disable annotation parsing + if ($this->_withoutAnnotations) { + $this->_runner->setWithoutAnnotations(); + } + + // Enable bad documentation support + if ($this->_supportBadDocumentation) { + $this->_runner->setSupportBadDocumentation(); + } + + // Check for suffix + if (count($this->_allowedFileExtensions) > 0) { + $this->_runner->setFileExtensions($this->_allowedFileExtensions); + } + + // Check for ignore directories + if (count($this->_excludeDirectories) > 0) { + $this->_runner->setExcludeDirectories($this->_excludeDirectories); + } + + // Check for exclude packages + if (count($this->_excludePackages) > 0) { + $this->_runner->setExcludePackages($this->_excludePackages); + } + + // Check for configuration option + if ($this->_configFile instanceof PhingFile) { + if (file_exists($this->_configFile->__toString()) === false) { + throw new BuildException( + 'The configuration file "' + . $this->_configFile->__toString() . '" doesn\'t exist.' + ); + } + + // Load configuration file + $config = new PHP_Depend_Util_Configuration( + $this->_configFile->__toString(), + null, + true + ); + + // Store in config registry + PHP_Depend_Util_ConfigurationInstance::set($config); + } + + if ($this->_debug) { + require_once 'PHP/Depend/Util/Log.php'; + // Enable debug logging + PHP_Depend_Util_Log::setSeverity(PHP_Depend_Util_Log::DEBUG); + } + + $this->_runner->run(); + + if ($this->_runner->hasParseErrors() === true) { + $this->log('Following errors occurred:'); + + foreach ($this->_runner->getParseErrors() as $error) { + $this->log($error); + } + + if ($this->_haltonerror === true) { + throw new BuildException('Errors occurred during parse process'); + } + } + } + + /** + * Validates the available loggers + * + * @return void + * @throws BuildException + */ + protected function validateLoggers() + { + foreach ($this->_loggers as $logger) { + if ($logger->getType() === '') { + throw new BuildException( + "Logger missing required 'type' attribute" + ); + } + + if ($logger->getOutfile() === null) { + throw new BuildException( + "Logger requires 'outfile' attribute" + ); + } + } + } + + /** + * Validates the available analyzers + * + * @return void + * @throws BuildException + */ + protected function validateAnalyzers() + { + foreach ($this->_analyzers as $analyzer) { + if ($analyzer->getType() === '') { + throw new BuildException( + "Analyzer missing required 'type' attribute" + ); + } + + if (count($analyzer->getValue()) === 0) { + throw new BuildException( + "Analyzer missing required 'value' attribute" + ); + } + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php new file mode 100755 index 00000000..41f296f7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php @@ -0,0 +1,151 @@ +<?php + +/** + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + * + * @version SVN: $Id: dacfd46938db28930888f57a6924be642ec1b3d7 $ + * @package phing.tasks.ext.pdo + */ + +require_once 'phing/tasks/ext/pdo/PDOQuerySplitter.php'; + +/** + * Splits SQL source into queries using simple regular expressions + * + * Extracted from PDOSQLExecTask::runStatements() + * + * @author Hans Lellelid <hans@xmpl.org> + * @author Alexey Borzov <avb@php.net> + * @package phing.tasks.ext.pdo + * @version $Id$ + */ +class DefaultPDOQuerySplitter extends PDOQuerySplitter +{ + /** + * Delimiter type, one of PDOSQLExecTask::DELIM_ROW or PDOSQLExecTask::DELIM_NORMAL + * @var string + */ + private $delimiterType; + + /** + * Leftover SQL from previous line + * @var string + */ + private $sqlBacklog = ''; + + /** + * Constructor, sets the parent task, reader with SQL source and delimiter type + * + * @param PDOSQLExecTask $parent + * @param Reader $reader + * @param string $delimiterType + */ + public function __construct(PDOSQLExecTask $parent, Reader $reader, $delimiterType = PDOSQLExecTask::DELIM_NORMAL) + { + parent::__construct($parent, $reader); + $this->delimiterType = $delimiterType; + } + + /** + * Returns next query from SQL source, null if no more queries left + * + * In case of "row" delimiter type this searches for strings containing only + * delimiters. In case of "normal" delimiter type, this uses simple regular + * expression logic to search for delimiters. + * + * @return string|null + */ + public function nextQuery() + { + $sql = ""; + $hasQuery = false; + + while (($line = $this->sqlReader->readLine()) !== null) { + $delimiter = $this->parent->getDelimiter(); + $project = $this->parent->getOwningTarget()->getProject(); + $line = ProjectConfigurator::replaceProperties( + $project, trim($line), $project->getProperties() + ); + + if (($line != $delimiter) && ( + StringHelper::startsWith("//", $line) || + StringHelper::startsWith("--", $line) || + StringHelper::startsWith("#", $line))) { + continue; + } + + if (strlen($line) > 4 + && strtoupper(substr($line,0, 4)) == "REM ") { + continue; + } + + // MySQL supports defining new delimiters + if (preg_match('/DELIMITER [\'"]?([^\'" $]+)[\'"]?/i', $line, $matches)) { + $this->parent->setDelimiter($matches[1]); + continue; + } + + if ($this->sqlBacklog !== "") { + $sql = $this->sqlBacklog; + $this->sqlBacklog = ""; + } + + $sql .= " " . $line . "\n"; + + // SQL defines "--" as a comment to EOL + // and in Oracle it may contain a hint + // so we cannot just remove it, instead we must end it + if (strpos($line, "--") !== false) { + $sql .= "\n"; + } + + // DELIM_ROW doesn't need this (as far as i can tell) + if ($this->delimiterType == PDOSQLExecTask::DELIM_NORMAL) { + + $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter) . ")#"; + + $sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE); + $this->sqlBacklog = ""; + foreach ($sqlParts as $sqlPart) { + // we always want to append, even if it's a delim (which will be stripped off later) + $this->sqlBacklog .= $sqlPart; + + // we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query + if ($sqlPart === $delimiter) { + $sql = $this->sqlBacklog; + $this->sqlBacklog = ""; + $hasQuery = true; + } + } + } + + if ($hasQuery || ($this->delimiterType == PDOSQLExecTask::DELIM_ROW && $line == $delimiter)) { + // this assumes there is always a delimter on the end of the SQL statement. + $sql = StringHelper::substring($sql, 0, strlen($sql) - strlen($delimiter) + - ($this->delimiterType == PDOSQLExecTask::DELIM_ROW ? 2 : 1)); + return $sql; + } + } + + // Catch any statements not followed by ; + if ($sql !== "") { + return $sql; + } + + return null; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOQuerySplitter.php index df17d2d4..60a9d436 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOQuerySplitter.php @@ -1,7 +1,6 @@ <?php + /** - * $Id: SummaryPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -17,42 +16,48 @@ * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information please see * <http://phing.info>. + * + * @version $Id: e84ada3cdb7a04da60158c7a352fbb06f17f2ca7 $ + * @package phing.tasks.ext.pdo */ - -require_once 'PHPUnit2/Framework/Test.php'; - -require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php'; /** - * Prints short summary output of the test to Phing's logging system. + * Base class for classes that split SQL source into separate queries * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SummaryPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class SummaryPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter + * @author Alexey Borzov <avb@php.net> + * @package phing.tasks.ext.pdo + * @version $Id$ + */ +abstract class PDOQuerySplitter { - function endTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - parent::endTestSuite($suite); - - $sb = "Tests run: " . $this->getRunCount(); - $sb.= ", Failures: " . $this->getFailureCount(); - $sb.= ", Errors: " . $this->getErrorCount(); - $sb.= ", Time elapsed: " . $this->getElapsedTime(); - $sb.= " sec\n"; - - if ($this->out != NULL) - { - $this->out->write($sb); - $this->out->close(); - } - } - - function getExtension() - { - return NULL; - } + /** + * Task that uses the splitter + * @var PDOSQLExecTask + */ + protected $parent; + + /** + * Reader with SQL source + * @var BufferedReader + */ + protected $sqlReader; + + /** + * Constructor, sets the parent task and reader with SQL source + * + * @param PDOSQLExecTask $parent + * @param Reader $reader + */ + public function __construct(PDOSQLExecTask $parent, Reader $reader) + { + $this->parent = $parent; + $this->sqlReader = new BufferedReader($reader); + } + + /** + * Returns next query from SQL source, null if no more queries left + * + * @return string|null + */ + abstract public function nextQuery(); } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOResultFormatter.php new file mode 100644 index 00000000..82a90ca4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOResultFormatter.php @@ -0,0 +1,84 @@ +<?php +/** + * $Id: a3237522d22494bbfaf0521ebb8f091d448f3614 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; + +/** + * Abstract + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +abstract class PDOResultFormatter +{ + /** + * Output writer. + * + * @var Writer + */ + protected $out; + + /** + * Sets the output writer. + * + * @param Writer $out + */ + public function setOutput(Writer $out) { + $this->out = $out; + } + + /** + * Gets the output writer. + * + * @return Writer + */ + public function getOutput() { + return $this->out; + } + + /** + * Gets the preferred output filename for this formatter. + * @return string + */ + abstract public function getPreferredOutfile(); + + /** + * Perform any initialization. + */ + public function initialize() { + + } + + /** + * Processes a specific row from PDO result set. + * + * @param array $row Row of PDO result set. + */ + abstract public function processRow($row); + + /** + * Perform any final tasks and Close the writer. + */ + public function close() { + $this->out->close(); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php new file mode 100644 index 00000000..bc657604 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php @@ -0,0 +1,313 @@ +<?php +/** + * $Id: a3ca52c2b277a8cbc0d2802b75f2bea18701b636 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/tasks/ext/pdo/PlainPDOResultFormatter.php'; +require_once 'phing/tasks/ext/pdo/XMLPDOResultFormatter.php'; +require_once 'phing/util/LogWriter.php'; + +/** + * A class to represent the nested <formatter> element for PDO SQL results. + * + * This class is inspired by the similarly-named class in the PHPUnit tasks. + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +class PDOSQLExecFormatterElement +{ + /** + * @var PDOResultFormatter + */ + private $formatter; + + /** + * The type of the formatter (used for built-in formatter classes). + * @var string + */ + private $type = ""; + + /** + * Whether to use file (or write output to phing log). + * @var boolean + */ + private $useFile = true; + + /** + * Output file for formatter. + * @var PhingFile + */ + private $outfile; + + /** + * Print header columns. + * @var boolean + */ + private $showheaders = true; + + /** + * Whether to format XML output. + * @var boolean + */ + private $formatoutput = true; + + /** + * Encoding for XML output. + * @var string + */ + private $encoding; + + /** + * Column delimiter. + * Defaults to ',' + * @var string + */ + private $coldelimiter = ","; + + /** + * Row delimiter. + * Defaults to PHP_EOL. + * @var string + */ + private $rowdelimiter = PHP_EOL; + + /** + * Append to an existing file or overwrite it? + * @var boolean + */ + private $append = false; + + /** + * Parameters for a custom formatter. + * @var array Parameter[] + */ + private $formatterParams = array(); + + /** + * @var PDOSQLExecTask + */ + private $parentTask; + + /** + * Construct a new PDOSQLExecFormatterElement with parent task. + * @param PDOSQLExecTask $parentTask + */ + public function __construct(PDOSQLExecTask $parentTask) + { + $this->parentTask = $parentTask; + } + + /** + * Supports nested <param> element (for custom formatter classes). + * @return Parameter + */ + public function createParam() { + $num = array_push($this->parameters, new Parameter()); + return $this->parameters[$num-1]; + } + + /** + * Gets a configured output writer. + * @return Writer + */ + private function getOutputWriter() + { + if ($this->useFile) { + $of = $this->getOutfile(); + if (!$of) { + $of = new PhingFile($this->formatter->getPreferredOutfile()); + } + return new FileWriter($of, $this->append); + } else { + return $this->getDefaultOutput(); + } + } + + /** + * Configures wrapped formatter class with any attributes on this element. + */ + public function prepare() { + + if (!$this->formatter) { + throw new BuildException("No formatter specified (use type or classname attribute)", $this->getLocation()); + } + + $out = $this->getOutputWriter(); + + $this->parentTask->log("Setting output writer to: " . get_class($out), Project::MSG_VERBOSE); + $this->formatter->setOutput($out); + + if ($this->formatter instanceof PlainPDOResultFormatter) { + // set any options that apply to the plain formatter + $this->formatter->setShowheaders($this->showheaders); + $this->formatter->setRowdelim($this->rowdelimiter); + $this->formatter->setColdelim($this->coldelimiter); + } elseif ($this->formatter instanceof XMLPDOResultFormatter) { + // set any options that apply to the xml formatter + $this->formatter->setEncoding($this->encoding); + $this->formatter->setFormatOutput($this->formatoutput); + } + + foreach($this->formatterParams as $param) { + $param = new Parameter(); + $method = 'set' . $param->getName(); + if (!method_exists($this->formatter, $param->getName())) { + throw new BuildException("Formatter " . get_class($this->formatter) . " does not have a $method method.", $this->getLocation()); + } + call_user_func(array($this->formatter, $method), $param->getValue()); + } + } + + /** + * Sets the formatter type. + * @param string $type + */ + function setType($type) { + $this->type = $type; + if ($this->type == "xml") { + $this->formatter = new XMLPDOResultFormatter(); + } elseif ($this->type == "plain") { + $this->formatter = new PlainPDOResultFormatter(); + } else { + throw new BuildException("Formatter '" . $this->type . "' not implemented"); + } + } + + /** + * Set classname for a custom formatter (must extend PDOResultFormatter). + * @param string $className + */ + function setClassName($className) { + $classNameNoDot = Phing::import($className); + $this->formatter = new $classNameNoDot(); + } + + /** + * Set whether to write formatter results to file. + * @param boolean $useFile + */ + function setUseFile($useFile) { + $this->useFile = (boolean) $useFile; + } + + /** + * Return whether to write formatter results to file. + * @return boolean + */ + function getUseFile() { + return $this->useFile; + } + + /** + * Sets the output file for the formatter results. + * @param PhingFile $outFile + */ + function setOutfile(PhingFile $outfile) { + $this->outfile = $outfile; + } + + /** + * Get the output file. + * @return PhingFile + */ + function getOutfile() { + return $this->outfile; + /* + } else { + return new PhingFile($this->formatter->getPreferredOutfile()); + }*/ + } + + /** + * whether output should be appended to or overwrite + * an existing file. Defaults to false. + * @param boolean $append + */ + public function setAppend($append) { + $this->append = (boolean) $append; + } + + /** + * Whether output should be appended to file. + * @return boolean + */ + public function getAppend() { + return $this->append; + } + + /** + * Print headers for result sets from the + * statements; optional, default true. + * @param boolean $showheaders + */ + public function setShowheaders($showheaders) { + $this->showheaders = (boolean) $showheaders; + } + + /** + * Sets the column delimiter. + * @param string $v + */ + public function setColdelim($v) { + $this->coldelimiter = $v; + } + + /** + * Sets the row delimiter. + * @param string $v + */ + public function setRowdelim($v) { + $this->rowdelimiter = $v; + } + + /** + * Set the DOM document encoding. + * @param string $v + */ + public function setEncoding($v) { + $this->encoding = $v; + } + + /** + * @param boolean $v + */ + public function setFormatOutput($v) { + $this->formatOutput = (boolean) $v; + } + + /** + * Gets a default output writer for this task. + * @return Writer + */ + private function getDefaultOutput() + { + return new LogWriter($this->parentTask); + } + + /** + * Gets the formatter that has been configured based on this element. + * @return PDOResultFormatter + */ + function getFormatter() { + return $this->formatter; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecTask.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecTask.php new file mode 100755 index 00000000..3837d7ff --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOSQLExecTask.php @@ -0,0 +1,606 @@ +<?php +/* + * $Id: 8b5a8e4f80b46f8a797b058dbb9a240a1185c12b $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/pdo/PDOTask.php'; +include_once 'phing/system/io/StringReader.php'; +include_once 'phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php'; + +/** + * Executes a series of SQL statements on a database using PDO. + * + * <p>Statements can + * either be read in from a text file using the <i>src</i> attribute or from + * between the enclosing SQL tags.</p> + * + * <p>Multiple statements can be provided, separated by semicolons (or the + * defined <i>delimiter</i>). Individual lines within the statements can be + * commented using either --, // or REM at the start of the line.</p> + * + * <p>The <i>autocommit</i> attribute specifies whether auto-commit should be + * turned on or off whilst executing the statements. If auto-commit is turned + * on each statement will be executed and committed. If it is turned off the + * statements will all be executed as one transaction.</p> + * + * <p>The <i>onerror</i> attribute specifies how to proceed when an error occurs + * during the execution of one of the statements. + * The possible values are: <b>continue</b> execution, only show the error; + * <b>stop</b> execution and commit transaction; + * and <b>abort</b> execution and transaction and fail task.</p> + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Jeff Martin <jeff@custommonkey.org> (Ant) + * @author Michael McCallum <gholam@xtra.co.nz> (Ant) + * @author Tim Stephenson <tim.stephenson@sybase.com> (Ant) + * @package phing.tasks.ext.pdo + * @version $Id: 8b5a8e4f80b46f8a797b058dbb9a240a1185c12b $ + */ +class PDOSQLExecTask extends PDOTask { + + /** + * Count of how many statements were executed successfully. + * @var int + */ + private $goodSql = 0; + + /** + * Count of total number of SQL statements. + * @var int + */ + private $totalSql = 0; + + const DELIM_ROW = "row"; + const DELIM_NORMAL = "normal"; + + /** + * Database connection + * @var PDO + */ + private $conn = null; + + /** + * Files to load + * @var array FileSet[] + */ + private $filesets = array(); + + /** + * Files to load + * @var array FileList[] + */ + private $filelists = array(); + + /** + * Formatter elements. + * @var array PDOSQLExecFormatterElement[] + */ + private $formatters = array(); + + /** + * SQL statement + * @var PDOStatement + */ + private $statement; + + /** + * SQL input file + * @var PhingFile + */ + private $srcFile; + + /** + * SQL input command + * @var string + */ + private $sqlCommand = ""; + + /** + * SQL transactions to perform + */ + private $transactions = array(); + + /** + * SQL Statement delimiter (for parsing files) + * @var string + */ + private $delimiter = ";"; + + /** + * The delimiter type indicating whether the delimiter will + * only be recognized on a line by itself + */ + private $delimiterType = "normal"; // can't use constant just defined + + /** + * Action to perform if an error is found + **/ + private $onError = "abort"; + + /** + * Encoding to use when reading SQL statements from a file + */ + private $encoding = null; + + /** + * Fetch mode for PDO select queries. + * @var int + */ + private $fetchMode; + + /** + * Set the name of the SQL file to be run. + * Required unless statements are enclosed in the build file + */ + public function setSrc(PhingFile $srcFile) { + $this->srcFile = $srcFile; + } + + /** + * Set an inline SQL command to execute. + * NB: Properties are not expanded in this text. + */ + public function addText($sql) { + $this->sqlCommand .= $sql; + } + + /** + * Adds a set of files (nested fileset attribute). + */ + public function addFileset(FileSet $set) { + $this->filesets[] = $set; + } + + /** + * Adds a set of files (nested filelist attribute). + */ + public function addFilelist(FileList $list) { + $this->filelists[] = $list; + } + + /** + * Creates a new PDOSQLExecFormatterElement for <formatter> element. + * @return PDOSQLExecFormatterElement + */ + public function createFormatter() + { + $fe = new PDOSQLExecFormatterElement($this); + $this->formatters[] = $fe; + return $fe; + } + + /** + * Add a SQL transaction to execute + */ + public function createTransaction() { + $t = new PDOSQLExecTransaction($this); + $this->transactions[] = $t; + return $t; + } + + /** + * Set the file encoding to use on the SQL files read in + * + * @param encoding the encoding to use on the files + */ + public function setEncoding($encoding) { + $this->encoding = $encoding; + } + + /** + * Set the statement delimiter. + * + * <p>For example, set this to "go" and delimitertype to "ROW" for + * Sybase ASE or MS SQL Server.</p> + * + * @param delimiter + */ + public function setDelimiter($delimiter) + { + $this->delimiter = $delimiter; + } + + /** + * Get the statement delimiter. + * + * @return string + */ + public function getDelimiter() + { + return $this->delimiter; + } + + /** + * Set the Delimiter type for this sql task. The delimiter type takes two + * values - normal and row. Normal means that any occurence of the delimiter + * terminate the SQL command whereas with row, only a line containing just + * the delimiter is recognized as the end of the command. + * + * @param string $delimiterType + */ + public function setDelimiterType($delimiterType) + { + $this->delimiterType = $delimiterType; + } + + /** + * Action to perform when statement fails: continue, stop, or abort + * optional; default "abort" + */ + public function setOnerror($action) { + $this->onError = $action; + } + + /** + * Sets the fetch mode to use for the PDO resultset. + * @param mixed $mode The PDO fetchmode integer or constant name. + */ + public function setFetchmode($mode) { + if (is_numeric($mode)) { + $this->fetchMode = (int) $mode; + } else { + if (defined($mode)) { + $this->fetchMode = constant($mode); + } else { + throw new BuildException("Invalid PDO fetch mode specified: " . $mode, $this->getLocation()); + } + } + } + + /** + * Gets a default output writer for this task. + * @return Writer + */ + private function getDefaultOutput() + { + return new LogWriter($this); + } + + /** + * Load the sql file and then execute it + * @throws BuildException + */ + public function main() { + + // Set a default fetchmode if none was specified + // (We're doing that here to prevent errors loading the class is PDO is not available.) + if ($this->fetchMode === null) { + $this->fetchMode = PDO::FETCH_ASSOC; + } + + // Initialize the formatters here. This ensures that any parameters passed to the formatter + // element get passed along to the actual formatter object + foreach($this->formatters as $fe) { + $fe->prepare(); + } + + $savedTransaction = array(); + for($i=0,$size=count($this->transactions); $i < $size; $i++) { + $savedTransaction[] = clone $this->transactions[$i]; + } + + $savedSqlCommand = $this->sqlCommand; + + $this->sqlCommand = trim($this->sqlCommand); + + try { + if ($this->srcFile === null && $this->sqlCommand === "" + && empty($this->filesets) && empty($this->filelists) + && count($this->transactions) === 0) { + throw new BuildException("Source file or fileset/filelist, " + . "transactions or sql statement " + . "must be set!", $this->location); + } + + if ($this->srcFile !== null && !$this->srcFile->exists()) { + throw new BuildException("Source file does not exist!", $this->location); + } + + // deal with the filesets + foreach($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($this->project); + $srcDir = $fs->getDir($this->project); + $srcFiles = $ds->getIncludedFiles(); + // Make a transaction for each file + foreach($srcFiles as $srcFile) { + $t = $this->createTransaction(); + $t->setSrc(new PhingFile($srcDir, $srcFile)); + } + } + + // process filelists + foreach($this->filelists as $fl) { + $srcDir = $fl->getDir($this->project); + $srcFiles = $fl->getFiles($this->project); + // Make a transaction for each file + foreach($srcFiles as $srcFile) { + $t = $this->createTransaction(); + $t->setSrc(new PhingFile($srcDir, $srcFile)); + } + } + + // Make a transaction group for the outer command + $t = $this->createTransaction(); + if ($this->srcFile) $t->setSrc($this->srcFile); + $t->addText($this->sqlCommand); + $this->conn = $this->getConnection(); + + try { + + $this->statement = null; + + // Initialize the formatters. + $this->initFormatters(); + + try { + + // Process all transactions + for ($i=0,$size=count($this->transactions); $i < $size; $i++) { + if (!$this->isAutocommit()) { + $this->log("Beginning transaction", Project::MSG_VERBOSE); + $this->conn->beginTransaction(); + } + $this->transactions[$i]->runTransaction(); + if (!$this->isAutocommit()) { + $this->log("Commiting transaction", Project::MSG_VERBOSE); + $this->conn->commit(); + } + } + } catch (Exception $e) { + $this->closeConnection(); + throw $e; + } + } catch (IOException $e) { + if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") { + try { + $this->conn->rollback(); + } catch (PDOException $ex) {} + } + $this->closeConnection(); + throw new BuildException($e->getMessage(), $this->location); + } catch (PDOException $e){ + if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") { + try { + $this->conn->rollback(); + } catch (PDOException $ex) {} + } + $this->closeConnection(); + throw new BuildException($e->getMessage(), $this->location); + } + + // Close the formatters. + $this->closeFormatters(); + + $this->log($this->goodSql . " of " . $this->totalSql . + " SQL statements executed successfully"); + + } catch (Exception $e) { + $this->transactions = $savedTransaction; + $this->sqlCommand = $savedSqlCommand; + $this->closeConnection(); + throw $e; + } + // finally { + $this->transactions = $savedTransaction; + $this->sqlCommand = $savedSqlCommand; + $this->closeConnection(); + } + + + /** + * read in lines and execute them + * @throws PDOException, IOException + */ + public function runStatements(Reader $reader) { + + if (self::DELIM_NORMAL == $this->delimiterType && 0 === strpos($this->getUrl(), 'pgsql:')) { + require_once 'phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php'; + $splitter = new PgsqlPDOQuerySplitter($this, $reader); + } else { + require_once 'phing/tasks/ext/pdo/DefaultPDOQuerySplitter.php'; + $splitter = new DefaultPDOQuerySplitter($this, $reader, $this->delimiterType); + } + + try { + while (null !== ($query = $splitter->nextQuery())) { + $this->log("SQL: " . $query, Project::MSG_VERBOSE); + $this->execSQL($query); + } + + } catch (PDOException $e) { + throw $e; + } + } + + /** + * Whether the passed-in SQL statement is a SELECT statement. + * This does a pretty simple match, checking to see if statement starts with + * 'select' (but not 'select into'). + * + * @param string $sql + * @return boolean Whether specified SQL looks like a SELECT query. + */ + protected function isSelectSql($sql) + { + $sql = trim($sql); + return (stripos($sql, 'select') === 0 && stripos($sql, 'select into ') !== 0); + } + + /** + * Exec the sql statement. + * @throws PDOException + */ + protected function execSQL($sql) { + + // Check and ignore empty statements + if (trim($sql) == "") { + return; + } + + try { + $this->totalSql++; + + $this->statement = $this->conn->prepare($sql); + $this->statement->execute(); + $this->log($this->statement->rowCount() . " rows affected", Project::MSG_VERBOSE); + + // only call processResults() for statements that return actual data (such as 'select') + if ($this->statement->columnCount() > 0) + { + $this->processResults(); + } + + $this->statement->closeCursor(); + $this->statement = null; + + $this->goodSql++; + + } catch (PDOException $e) { + $this->log("Failed to execute: " . $sql, Project::MSG_ERR); + if ($this->onError != "continue") { + throw new BuildException("Failed to execute SQL", $e); + } + $this->log($e->getMessage(), Project::MSG_ERR); + } + } + + /** + * Returns configured PDOResultFormatter objects (which were created from PDOSQLExecFormatterElement objects). + * @return array PDOResultFormatter[] + */ + protected function getConfiguredFormatters() + { + $formatters = array(); + foreach ($this->formatters as $fe) { + $formatters[] = $fe->getFormatter(); + } + return $formatters; + } + + /** + * Initialize the formatters. + */ + protected function initFormatters() { + $formatters = $this->getConfiguredFormatters(); + foreach ($formatters as $formatter) { + $formatter->initialize(); + } + + } + + /** + * Run cleanup and close formatters. + */ + protected function closeFormatters() { + $formatters = $this->getConfiguredFormatters(); + foreach ($formatters as $formatter) { + $formatter->close(); + } + } + + /** + * Passes results from query to any formatters. + * @throws PDOException + */ + protected function processResults() { + + try { + + $this->log("Processing new result set.", Project::MSG_VERBOSE); + + $formatters = $this->getConfiguredFormatters(); + + while ($row = $this->statement->fetch($this->fetchMode)) { + foreach ($formatters as $formatter) { + $formatter->processRow($row); + } + } + + } catch (Exception $x) { + $this->log("Error processing reults: " . $x->getMessage(), Project::MSG_ERR); + foreach ($formatters as $formatter) { + $formatter->close(); + } + throw $x; + } + + } + + /** + * Closes current connection + */ + protected function closeConnection() + { + if ($this->conn) { + unset($this->conn); + } + } +} + +/** + * "Inner" class that contains the definition of a new transaction element. + * Transactions allow several files or blocks of statements + * to be executed using the same JDBC connection and commit + * operation in between. + * + * @package phing.tasks.ext.pdo + */ +class PDOSQLExecTransaction { + + private $tSrcFile = null; + private $tSqlCommand = ""; + private $parent; + + function __construct($parent) + { + // Parent is required so that we can log things ... + $this->parent = $parent; + } + + public function setSrc(PhingFile $src) + { + $this->tSrcFile = $src; + } + + public function addText($sql) + { + $this->tSqlCommand .= $sql; + } + + /** + * @throws IOException, PDOException + */ + public function runTransaction() + { + if (!empty($this->tSqlCommand)) { + $this->parent->log("Executing commands", Project::MSG_INFO); + $this->parent->runStatements(new StringReader($this->tSqlCommand)); + } + + if ($this->tSrcFile !== null) { + $this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(), + Project::MSG_INFO); + $reader = new FileReader($this->tSrcFile); + $this->parent->runStatements($reader); + $reader->close(); + } + } +} + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOTask.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOTask.php new file mode 100755 index 00000000..93feaa6d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PDOTask.php @@ -0,0 +1,215 @@ +<?php + +/* + * $Id: de478f3e51714db7d9163b6bbc3fa64de27549cb $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +include_once 'phing/types/Reference.php'; + +/** + * Handles PDO configuration needed by SQL type tasks. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Nick Chalko <nick@chalko.com> (Ant) + * @author Jeff Martin <jeff@custommonkey.org> (Ant) + * @author Michael McCallum <gholam@xtra.co.nz> (Ant) + * @author Tim Stephenson <tim.stephenson@sybase.com> (Ant) + * @version $Id$ + * @package phing.tasks.system + */ +abstract class PDOTask extends Task { + + private $caching = true; + + /** + * Autocommit flag. Default value is false + */ + private $autocommit = false; + + /** + * DB url. + */ + private $url; + + /** + * User name. + */ + private $userId; + + /** + * Password + */ + private $password; + + /** + * RDBMS Product needed for this SQL. + **/ + private $rdbms; + + /** + * Initialize CreoleTask. + * This method includes any necessary Creole libraries and triggers + * appropriate error if they cannot be found. This is not done in header + * because we may want this class to be loaded w/o triggering an error. + */ + function init() { + if (!class_exists('PDO')) { + throw new Exception("PDOTask depends on PDO feature being included in PHP."); + } + } + + /** + * Caching loaders / driver. This is to avoid + * getting an OutOfMemoryError when calling this task + * multiple times in a row; default: true + * @param $enable + */ + public function setCaching($enable) { + $this->caching = $enable; + } + + /** + * Sets the database connection URL; required. + * @param url The url to set + */ + public function setUrl($url) { + $this->url = $url; + } + + /** + * Sets the password; required. + * @param password The password to set + */ + public function setPassword($password) { + $this->password = $password; + } + + /** + * Auto commit flag for database connection; + * optional, default false. + * @param autocommit The autocommit to set + */ + public function setAutocommit($autocommit) { + $this->autocommit = $autocommit; + } + + /** + * Sets the version string, execute task only if + * rdbms version match; optional. + * @param version The version to set + */ + public function setVersion($version) { + $this->version = $version; + } + + protected function getLoaderMap() { + return self::$loaderMap; + } + + + /** + * Creates a new Connection as using the driver, url, userid and password specified. + * The calling method is responsible for closing the connection. + * @return Connection the newly created connection. + * @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load. + */ + protected function getConnection() { + + if ($this->url === null) { + throw new BuildException("Url attribute must be set!", $this->location); + } + + try { + + $this->log("Connecting to " . $this->getUrl(), Project::MSG_VERBOSE); + + $user = null; + $pass = null; + + if ($this->userId) { + $user = $this->getUserId(); + } + + if ($this->password) { + $pass = $this->getPassword(); + } + + $conn = new PDO($this->getUrl(), $user, $pass); + $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + try { + $conn->setAttribute(PDO::ATTR_AUTOCOMMIT, $this->autocommit); + } catch (PDOException $pe) { + $this->log("Unable to enable auto-commit for this database: " . $pe->getMessage(), Project::MSG_VERBOSE); + } + + return $conn; + + } catch (SQLException $e) { + throw new BuildException($e->getMessage(), $this->location); + } + + } + + public function isCaching($value) { + $this->caching = $value; + } + + /** + * Gets the autocommit. + * @return Returns a boolean + */ + public function isAutocommit() { + return $this->autocommit; + } + + /** + * Gets the url. + * @return Returns a String + */ + public function getUrl() { + return $this->url; + } + + /** + * Gets the userId. + * @return Returns a String + */ + public function getUserId() { + return $this->userId; + } + + /** + * Set the user name for the connection; required. + * @param userId The userId to set + */ + public function setUserid($userId) { + $this->userId = $userId; + } + + /** + * Gets the password. + * @return Returns a String + */ + public function getPassword() { + return $this->password; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php new file mode 100755 index 00000000..b99ac624 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php @@ -0,0 +1,291 @@ +<?php + +/** + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + * + * @version SVN: $Id: 0e3570c0e594f4396d833d77e841294855b297d9 $ + * @package phing.tasks.ext.pdo + */ + +require_once 'phing/tasks/ext/pdo/PDOQuerySplitter.php'; + +/** + * Splits PostgreSQL's dialect of SQL into separate queries + * + * Unlike DefaultPDOQuerySplitter this uses a lexer instead of regular + * expressions. This allows handling complex constructs like C-style comments + * (including nested ones) and dollar-quoted strings. + * + * @author Alexey Borzov <avb@php.net> + * @package phing.tasks.ext.pdo + * @version $Id: 0e3570c0e594f4396d833d77e841294855b297d9 $ + * @link http://www.phing.info/trac/ticket/499 + * @link http://www.postgresql.org/docs/current/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING + */ +class PgsqlPDOQuerySplitter extends PDOQuerySplitter +{ + /**#@+ + * Lexer states + */ + const STATE_NORMAL = 0; + const STATE_SINGLE_QUOTED = 1; + const STATE_DOUBLE_QUOTED = 2; + const STATE_DOLLAR_QUOTED = 3; + const STATE_COMMENT_LINEEND = 4; + const STATE_COMMENT_MULTILINE = 5; + const STATE_BACKSLASH = 6; + /**#@-*/ + + /** + * Nesting depth of current multiline comment + * @var int + */ + protected $commentDepth = 0; + + /** + * Current dollar-quoting "tag" + * @var string + */ + protected $quotingTag = ''; + + /** + * Current lexer state, one of STATE_* constants + * @var int + */ + protected $state = self::STATE_NORMAL; + + /** + * Whether a backslash was just encountered in quoted string + * @var bool + */ + protected $escape = false; + + /** + * Current source line being examined + * @var string + */ + protected $line = ''; + + /** + * Position in current source line + * @var int + */ + protected $inputIndex; + + /** + * Gets next symbol from the input, false if at end + * + * @return string|bool + */ + public function getc() + { + if (!strlen($this->line) || $this->inputIndex >= strlen($this->line)) { + if (null === ($line = $this->sqlReader->readLine())) { + return false; + } + $project = $this->parent->getOwningTarget()->getProject(); + $this->line = ProjectConfigurator::replaceProperties( + $project, $line, $project->getProperties() + ) . "\n"; + $this->inputIndex = 0; + } + return $this->line[$this->inputIndex++]; + } + + /** + * Bactracks one symbol on the input + * + * NB: we don't need ungetc() at the start of the line, so this case is + * not handled. + */ + public function ungetc() + { + $this->inputIndex--; + } + + /** + * Checks whether symbols after $ are a valid dollar-quoting tag + * + * @return string|bool Dollar-quoting "tag" if it is present, false otherwise + */ + protected function checkDollarQuote() + { + $ch = $this->getc(); + if ('$' == $ch) { + // empty tag + return ''; + + } elseif (!ctype_alpha($ch) && '_' != $ch) { + // not a delimiter + $this->ungetc(); + return false; + + } else { + $tag = $ch; + while (false !== ($ch = $this->getc())) { + if ('$' == $ch) { + return $tag; + + } elseif (ctype_alnum($ch) || '_' == $ch) { + $tag .= $ch; + + } else { + for ($i = 0; $i < strlen($tag); $i++) { + $this->ungetc(); + } + return false; + } + } + } + } + + public function nextQuery() + { + $sql = ''; + $delimiter = $this->parent->getDelimiter(); + $openParens = 0; + + while (false !== ($ch = $this->getc())) { + switch ($this->state) { + case self::STATE_NORMAL: + switch ($ch) { + case '-': + if ('-' == $this->getc()) { + $this->state = self::STATE_COMMENT_LINEEND; + } else { + $this->ungetc(); + } + break; + case '"': + $this->state = self::STATE_DOUBLE_QUOTED; + break; + case "'": + $this->state = self::STATE_SINGLE_QUOTED; + break; + case '/': + if ('*' == $this->getc()) { + $this->state = self::STATE_COMMENT_MULTILINE; + $this->commentDepth = 1; + } else { + $this->ungetc(); + } + break; + case '$': + if (false !== ($tag = $this->checkDollarQuote())) { + $this->state = self::STATE_DOLLAR_QUOTED; + $this->quotingTag = $tag; + $sql .= '$' . $tag . '$'; + continue 3; + } + break; + case '(': + $openParens++; + break; + case ')': + $openParens--; + break; + // technically we can use e.g. psql's \g command as delimiter + case $delimiter[0]: + // special case to allow "create rule" statements + // http://www.postgresql.org/docs/current/interactive/sql-createrule.html + if (';' == $delimiter && 0 < $openParens) { + break; + } + $hasQuery = true; + for ($i = 1; $i < strlen($delimiter); $i++) { + if ($delimiter[$i] != $this->getc()) { + $hasQuery = false; + } + } + if ($hasQuery) { + return $sql; + } else { + for ($j = 1; $j < $i; $j++) { + $this->ungetc(); + } + } + } + break; + + case self::STATE_COMMENT_LINEEND: + if ("\n" == $ch) { + $this->state = self::STATE_NORMAL; + } + break; + + case self::STATE_COMMENT_MULTILINE: + switch ($ch) { + case '/': + if ('*' != $this->getc()) { + $this->ungetc(); + } else { + $this->commentDepth++; + } + break; + + case '*': + if ('/' != $this->getc()) { + $this->ungetc(); + } else { + $this->commentDepth--; + if (0 == $this->commentDepth) { + $this->state = self::STATE_NORMAL; + continue 3; + } + } + } + + case self::STATE_SINGLE_QUOTED: + case self::STATE_DOUBLE_QUOTED: + if ($this->escape) { + $this->escape = false; + break; + } + $quote = $this->state == self::STATE_SINGLE_QUOTED ? "'" : '"'; + switch ($ch) { + case '\\': + $this->escape = true; + break; + case $quote: + if ($quote == $this->getc()) { + $sql .= $quote; + } else { + $this->ungetc(); + $this->state = self::STATE_NORMAL; + } + } + + case self::STATE_DOLLAR_QUOTED: + if ('$' == $ch && false !== ($tag = $this->checkDollarQuote())) { + if ($tag == $this->quotingTag) { + $this->state = self::STATE_NORMAL; + } + $sql .= '$' . $tag . '$'; + continue 2; + } + } + + if ($this->state != self::STATE_COMMENT_LINEEND && $this->state != self::STATE_COMMENT_MULTILINE) { + $sql .= $ch; + } + } + if ('' !== $sql) { + return $sql; + } + return null; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php new file mode 100644 index 00000000..3aad8ec8 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php @@ -0,0 +1,130 @@ +<?php +/** + * $Id: 0b899576769e68651a8847db8db8941aa4d784a2 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/tasks/ext/pdo/PDOResultFormatter.php'; + +/** + * Plain text formatter for PDO results. + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +class PlainPDOResultFormatter extends PDOResultFormatter +{ + /** + * Have column headers been printed? + * @var boolean + */ + private $colsprinted = false; + + /** + * Whether to show headers. + * @var boolean + */ + private $showheaders = true; + + /** + * Column delimiter. + * Defaults to ',' + * @var string + */ + private $coldelimiter = ","; + + /** + * Row delimiter. + * Defaults to PHP_EOL. + * @var string + */ + private $rowdelimiter = PHP_EOL; + + /** + * Set the showheaders attribute. + * @param boolean $v + */ + public function setShowheaders($v) { + $this->showheaders = StringHelper::booleanValue($v); + } + + /** + * Sets the column delimiter. + * @param string $v + */ + public function setColdelim($v) { + $this->coldelimiter = $v; + } + + /** + * Sets the row delimiter. + * @param string $v + */ + public function setRowdelim($v) { + $this->rowdelimiter = $v; + } + + /** + * Processes a specific row from PDO result set. + * + * @param array $row Row of PDO result set. + */ + public function processRow($row) { + + if (!$this->colsprinted && $this->showheaders) { + $first = true; + foreach($row as $fieldName => $ignore) { + if ($first) $first = false; else $line .= ","; + $line .= $fieldName; + } + + $this->out->write($line); + $this->out->write(PHP_EOL); + + $line = ""; + $colsprinted = true; + } // if show headers + + $first = true; + foreach($row as $columnValue) { + + if ($columnValue != null) { + $columnValue = trim($columnValue); + } + + if ($first) { + $first = false; + } else { + $line .= $this->coldelimiter; + } + $line .= $columnValue; + } + + $this->out->write($line); + $this->out->write($this->rowdelimiter); + + } + + public function getPreferredOutfile() + { + return new PhingFile('results.txt'); + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php new file mode 100644 index 00000000..435ae6e7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php @@ -0,0 +1,141 @@ +<?php +/** + * $Id: e5c24c7ac3cd665f7877d66f64218be584429581 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/tasks/ext/pdo/PDOResultFormatter.php'; + +/** + * XML formatter for PDO results. + * + * This class reprsents the output of a query using a simple XML schema. + * + * <results> + * <row> + * <col name="id">value</col> + * <col name="name">value2</col> + * </row> + * <row> + * <col name="id">value</col> + * <col name="name">value2</col> + * </row> + * </results> + * + * The actual names of the colums will depend on the fetchmode that was used + * with PDO. + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.tasks.ext.pdo + * @since 2.3.0 + */ +class XMLPDOResultFormatter extends PDOResultFormatter { + + /** + * The XML document being created. + * @var DOMDocument + */ + private $doc; + + /** + * @var DOMElement + */ + private $rootNode; + + /** + * XML document encoding + * + * @var string + */ + private $encoding; + + /** + * @var boolean + */ + private $formatOutput = true; + + /** + * Set the DOM document encoding. + * @param string $v + */ + public function setEncoding($v) { + $this->encoding = $v; + } + + /** + * @param boolean $v + */ + public function setFormatOutput($v) { + $this->formatOutput = (boolean) $v; + } + + public function initialize() { + $this->doc = new DOMDocument("1.0", $this->encoding); + $this->rootNode = $this->doc->createElement('results'); + $this->doc->appendChild($this->rootNode); + $this->doc->formatOutput = $this->formatOutput; + } + + /** + * Processes a specific row from PDO result set. + * + * @param array $row Row of PDO result set. + */ + public function processRow($row) { + + $rowNode = $this->doc->createElement('row'); + $this->rootNode->appendChild($rowNode); + + foreach($row as $columnName => $columnValue) { + + $colNode = $this->doc->createElement('column'); + $colNode->setAttribute('name', $columnName); + + if ($columnValue != null) { + $columnValue = trim($columnValue); + $colNode->nodeValue = $columnValue; + } + $rowNode->appendChild($colNode); + } + + } + + /** + * Gets a preferred filename for an output file. + * + * If no filename is specified, this is where the results will be placed + * (unless usefile=false). + * + * @return string + */ + public function getPreferredOutfile() + { + return new PhingFile('results.xml'); + } + + /** + * Write XML to file and free the DOM objects. + */ + public function close() { + $this->out->write($this->doc->saveXML()); + $this->rootNode = null; + $this->doc = null; + parent::close(); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php b/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php index 12bd4e55..23a0e4c6 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php +++ b/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php @@ -1,6 +1,6 @@ <?php /* - * $Id: Fileset.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 7016dea93483cc99ad17a638e30f5ff57c37c78b $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -30,17 +30,11 @@ include_once 'phing/system/io/PhingFile.php'; * @author Greg Beaver * @author Hans Lellelid <hans@xmpl.org> * @package phing.tasks.ext.pearpackage - * @version $Revision: 1.7 $ + * @version $Id$ */ class PEAR_PackageFileManager_Fileset { /** - * @access private - * @var PEAR_PackageFileManager - */ - private $parent; - - /** * Curent Phing Project. * @var Project */ @@ -60,9 +54,12 @@ class PEAR_PackageFileManager_Fileset { * @param PEAR_PackageFileManager * @param array */ - function __construct($parent, $options) + function __construct($options) { - $this->parent = $parent; + if (!is_array($options)) { + $options = $options->getOptions(); + } + $this->project = $options['phing_project']; $this->filesets = $options['phing_filesets']; } @@ -109,7 +106,7 @@ class PEAR_PackageFileManager_Fileset { $path = '/'; // for array index } - $parts = explode('.', basename($file)); + $parts = explode('.', basename($file)); $ext = array_pop($parts); if (strlen($ext) == strlen($file)) { $ext = ''; @@ -228,4 +225,4 @@ class PEAR_PackageFileManager_Fileset { return strnatcasecmp($a,$b); } } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadata.php b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadata.php new file mode 100644 index 00000000..1f7a263c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadata.php @@ -0,0 +1,55 @@ +<?php +/* + * $Id: fae81ee47ae75fc98d7848a22da93bfd4afb7a1b $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phar/PharMetadataElement.php'; + +/** + * @package phing.tasks.ext.phar + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + */ +class PharMetadata +{ + /** + * @var array + */ + protected $elements = array(); + /** + * @return PharMetadataElement + */ + public function createElement() + { + return ($this->elements[] = new PharMetadataElement()); + } + /** + * @return array + */ + public function toArray() + { + $metadata = array(); + + foreach ($this->elements as $element) { + $metadata[$element->getName()] = $element->toArray(); + } + + return $metadata; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadataElement.php b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadataElement.php new file mode 100644 index 00000000..c40f68f1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phar/PharMetadataElement.php @@ -0,0 +1,80 @@ +<?php +/* + * $Id: 4c70deae6a6f273d55f504077a3941ad926ad325 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phar/PharMetadata.php'; + +/** + * @package phing.tasks.ext.phar + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + */ +class PharMetadataElement + extends PharMetadata +{ + /** + * @var string + */ + private $name; + /** + * @var string + */ + private $value; + /** + * @param string $value + */ + public function setValue($value) + { + $this->value = $value; + } + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + /** + * @return string + */ + public function getName() + { + return $this->name; + } + /** + * Return array of + * + * @return string|array + */ + public function getValue() + { + /* + * Elements first! + */ + return (empty($this->elements) ? $this->value : $this->elements); + } + /** + * @return string|array + */ + public function toArray() + { + return (empty($this->elements) ? $this->value : parent::toArray()); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phar/PharPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/phar/PharPackageTask.php new file mode 100644 index 00000000..76a4215a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phar/PharPackageTask.php @@ -0,0 +1,362 @@ +<?php +/* + * $Id: 0396ab9c461e7d7655f12c9ed3a613fe6e69f973 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/system/MatchingTask.php'; +require_once 'phing/types/IterableFileSet.php'; +require_once 'phing/tasks/ext/phar/PharMetadata.php'; + +/** + * Package task for {@link http://ru.php.net/manual/en/book.phar.php Phar technology}. + * + * @package phing.tasks.ext + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + */ +class PharPackageTask + extends MatchingTask +{ + /** + * @var PhingFile + */ + private $destinationFile; + /** + * @var int + */ + private $compression = Phar::NONE; + /** + * Base directory, from where local package paths will be calculated. + * + * @var PhingFile + */ + private $baseDirectory; + /** + * @var PhingFile + */ + private $cliStubFile; + /** + * @var PhingFile + */ + private $webStubFile; + /** + * @var string + */ + private $stubPath; + /** + * Private key the Phar will be signed with. + * + * @var PhingFile + */ + private $key; + /** + * Password for the private key. + * + * @var string + */ + private $keyPassword = ''; + /** + * @var int + */ + private $signatureAlgorithm = Phar::SHA1; + /** + * @var array + */ + private $filesets = array(); + /** + * @var PharMetadata + */ + private $metadata = null; + /** + * @var string + */ + private $alias; + /** + * @return PharMetadata + */ + public function createMetadata() + { + return ($this->metadata = new PharMetadata()); + } + /** + * @return FileSet + */ + public function createFileSet() + { + $this->fileset = new IterableFileSet(); + $this->filesets[] = $this->fileset; + return $this->fileset; + } + /** + * @param string $algorithm + */ + public function setSignature($algorithm) + { + /* + * If we don't support passed algprithm, leave old one. + */ + switch ($algorithm) { + case 'md5': + $this->signatureAlgorithm = Phar::MD5; + break; + case 'sha1': + $this->signatureAlgorithm = Phar::SHA1; + break; + case 'sha256': + $this->signatureAlgorithm = Phar::SHA256; + break; + case 'sha512': + $this->signatureAlgorithm = Phar::SHA512; + break; + case 'openssl': + $this->signatureAlgorithm = Phar::OPENSSL; + break; + default: + break; + } + } + /** + * @param string $compression + */ + public function setCompression($compression) + { + /* + * If we don't support passed compression, leave old one. + */ + switch ($compression) { + case 'gzip': + $this->compression = Phar::GZ; + break; + case 'bzip2': + $this->compression = Phar::BZ2; + break; + default: + break; + } + } + /** + * @param PhingFile $destinationFile + */ + public function setDestFile(PhingFile $destinationFile) + { + $this->destinationFile = $destinationFile; + } + /** + * @param PhingFile $baseDirectory + */ + public function setBaseDir(PhingFile $baseDirectory) + { + $this->baseDirectory = $baseDirectory; + } + /** + * @param PhingFile $stubFile + */ + public function setCliStub(PhingFile $stubFile) + { + $this->cliStubFile = $stubFile; + } + /** + * @param PhingFile $stubFile + */ + public function setWebStub(PhingFile $stubFile) + { + $this->webStubFile = $stubFile; + } + /** + * @param string $stubPath + */ + public function setStub($stubPath) + { + $this->stubPath = $stubPath; + } + /** + * @param $alias + */ + public function setAlias($alias) + { + $this->alias = $alias; + } + /** + * Sets the private key to use to sign the Phar with. + * + * @param PhingFile $key Private key to sign the Phar with. + */ + public function setKey(PhingFile $key) + { + $this->key = $key; + } + /** + * Password for the private key. + * + * @param string $keyPassword + */ + public function setKeyPassword($keyPassword) + { + $this->keyPassword = $keyPassword; + } + /** + * @throws BuildException + */ + public function main() + { + $this->checkPreconditions(); + + try { + $this->log( + 'Building package: '.$this->destinationFile->__toString(), + Project::MSG_INFO + ); + + /* + * Delete old package, if exists. + */ + if ($this->destinationFile->exists()) { + /* + * TODO Check operation for errors... + */ + $this->destinationFile->delete(); + } + + $phar = $this->buildPhar(); + $phar->startBuffering(); + + $baseDirectory = realpath($this->baseDirectory->getPath()); + + foreach ($this->filesets as $fileset) { + $this->log( + 'Adding specified files in ' . $fileset->getDir($this->project) . ' to package', + Project::MSG_VERBOSE + ); + + $phar->buildFromIterator($fileset, $baseDirectory); + } + + $phar->stopBuffering(); + + /* + * File compression, if needed. + */ + if (Phar::NONE != $this->compression) { + $phar->compressFiles($this->compression); + } + } catch (Exception $e) { + throw new BuildException( + 'Problem creating package: '.$e->getMessage(), + $e, + $this->getLocation() + ); + } + } + /** + * @throws BuildException + */ + private function checkPreconditions() + { + if (is_null($this->destinationFile)) { + throw new BuildException("destfile attribute must be set!", $this->getLocation()); + } + + if ($this->destinationFile->exists() && $this->destinationFile->isDirectory()) { + throw new BuildException("destfile is a directory!", $this->getLocation()); + } + + if (!$this->destinationFile->canWrite()) { + throw new BuildException("Can not write to the specified destfile!", $this->getLocation()); + } + if (!is_null($this->baseDirectory)) { + if (!$this->baseDirectory->exists()) { + throw new BuildException("basedir '" . (string) $this->baseDirectory . "' does not exist!", $this->getLocation()); + } + } + if ($this->signatureAlgorithm == Phar::OPENSSL) { + + if (!extension_loaded('openssl')) { + throw new BuildException("PHP OpenSSL extension is required for OpenSSL signing of Phars!", $this->getLocation()); + } + + if (is_null($this->key)) { + throw new BuildException("key attribute must be set for OpenSSL signing!", $this->getLocation()); + } + + if (!$this->key->exists()) { + throw new BuildException("key '" . (string) $this->key . "' does not exist!", $this->getLocation()); + } + + if (!$this->key->canRead()) { + throw new BuildException("key '" . (string) $this->key . "' cannot be read!", $this->getLocation()); + } + } + } + /** + * Build and configure Phar object. + * + * @return Phar + */ + private function buildPhar() + { + $phar = new Phar($this->destinationFile); + + if ($this->signatureAlgorithm == Phar::OPENSSL) { + + // Load up the contents of the key + $keyContents = file_get_contents($this->key); + + // Setup an OpenSSL resource using the private key and tell the Phar + // to sign it using that key. + $private = openssl_pkey_get_private($keyContents, $this->keyPassword); + $phar->setSignatureAlgorithm(Phar::OPENSSL, $private); + + // Get the details so we can get the public key and write that out + // alongside the phar. + $details = openssl_pkey_get_details($private); + file_put_contents($this->destinationFile . '.pubkey', $details['key']); + + } else { + $phar->setSignatureAlgorithm($this->signatureAlgorithm); + } + + if (isset($this->stubPath)) { + $phar->setStub(file_get_contents($this->stubPath)); + } else { + if (!empty($this->cliStubFile)) { + $cliStubFile = $this->cliStubFile->getPathWithoutBase($this->baseDirectory); + } else { + $cliStubFile = null; + } + + if (!empty($this->webStubFile)) { + $webStubFile = $this->webStubFile->getPathWithoutBase($this->baseDirectory); + } else { + $webStubFile = null; + } + + $phar->setDefaultStub($cliStubFile, $webStubFile); + } + + if ($metadata = $this->metadata->toArray()) { + $phar->setMetadata($metadata); + } + + if(!empty($this->alias)){ + $phar->setAlias($this->alias); + } + + return $phar; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageTask.php new file mode 100644 index 00000000..80da93fa --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageTask.php @@ -0,0 +1,248 @@ +<?php +/** + * $Id: 5029881915d6a9e95320ba6e7f463f38af66cd93 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/phk/PhkPackageWebAccess.php'; + +/** + * See {@link http://phk.tekwire.net/} for more information about PHK. + * + * @author Alexey Shockov <alexey@shockov.com> + * @package phing.tasks.ext.phk + */ +class PhkPackageTask extends Task +{ + /** + * @var string + */ + private $outputFile; + /** + * @var string + */ + private $inputDirectory; + /** + * @var string + */ + private $phkCreatorPath; + /** + * @var PhkPackageWebAccess + */ + private $webAccess; + /** + * @var array + */ + private $modifiers = array(); + /** + * @var array + */ + private $options = array(); + /** + * @return PhkPackageWebAccess + */ + public function createWebAccess() + { + return ($this->webAccess = new PhkPackageWebAccess()); + } + /** + * @param string $crcCheck + */ + public function setCrcCheck($crcCheck) + { + $this->options['crc_check'] = ('true' == $crcCheck ? true : false); + } + /** + * @param string $webRunScript + */ + public function setWebRunScript($webRunScript) + { + $this->options['web_run_script'] = $webRunScript; + } + /** + * @param string $cliRunScript + */ + public function setCliRunScript($cliRunScript) + { + $this->options['cli_run_script'] = $cliRunScript; + } + /** + * @param string $libRunScript + */ + public function setLibRunScript($libRunScript) + { + $this->options['lib_run_script'] = $libRunScript; + } + /** + * @param string $name + */ + public function setName($name) + { + $this->options['name'] = $name; + } + /** + * @param string $webMainRedirect + */ + public function setWebMainRedirect($webMainRedirect) + { + $this->options['web_main_redirect'] = ('true' == $webMainRedirect ? true : false); + } + /** + * @param string $pluginClass + */ + public function setPluginClass($pluginClass) + { + $this->options['plugin_class'] = $pluginClass; + } + /** + * @param string $version + */ + public function setVersion($version) + { + $this->options['version'] = $version; + } + /** + * @param string $summary + */ + public function setSummary($summary) + { + $this->options['summary'] = $summary; + } + /** + * @param string $inputDirectory + */ + public function setInputDirectory($inputDirectory) + { + $this->inputDirectory = $inputDirectory; + } + /** + * @param string $outputFile + */ + public function setOutputFile($outputFile) + { + $this->outputFile = $outputFile; + } + /** + * May be none, gzip or bzip2. + * + * @param string $compress + */ + public function setCompress($compress) + { + $this->modifiers['compress'] = $compress; + } + /** + * True or false. + * + * @param srting $strip + */ + public function setStrip($strip) + { + $this->modifiers['strip'] = $strip; + } + /** + * Path to PHK_Creator.phk file. + * + * @param srting $path + */ + public function setPhkCreatorPath($path) + { + $this->phkCreatorPath = $path; + } + /** + * + */ + public function init() + { + + } + /** + * Main method... + */ + public function main() + { + /* + * Check for empty first - speed ;) + */ + if (!is_file($this->phkCreatorPath)) { + throw new BuildException('You must specify the "phkcreatorpath" attribute for PHK task.'); + } + if (empty($this->inputDirectory)) { + throw new BuildException('You must specify the "inputdirectory" attribute for PHK task.'); + } + if (empty($this->outputFile)) { + throw new BuildException('You must specify the "outputfile" attribute for PHK task.'); + } + + require_once $this->phkCreatorPath; + + $mountPoint = PHK_Mgr::mount($this->outputFile, PHK::F_CREATOR); + $phkManager = PHK_Mgr::instance($mountPoint); + + /* + * Add files. + */ + $phkManager->ftree()->merge_file_tree('/', $this->inputDirectory, $this->modifiers); + + /* + * Add web_access to options, if present. + */ + if (!is_null($this->webAccess)) { + $webAccessPaths = $this->webAccess->getPaths(); + if (!empty($webAccessPaths)) { + $this->options['web_access'] = $webAccessPaths; + } + } + + $phkManager->set_options($this->options); + + /* + * Intercept output (in PHP we can't intercept stream). + */ + ob_start(); + /* + * Create file... + */ + $phkManager->dump(); + /* + * Print with Phing log... + */ + $output = trim(ob_get_clean()); + $output = explode("\n", $output); + foreach ($output as $line) { + /* + * Delete all '--- *' lines. Bluh! + */ + /* + * TODO Change preg_math to more faster alternative. + */ + if (preg_match('/^---/', $line)) { + continue; + } + + $this->log($line); + } + + /* + * Set rights for generated file... Don't use umask() - see + * notes in official documentation for this function. + */ + chmod($this->outputFile, 0644); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccess.php b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccess.php new file mode 100644 index 00000000..9634d899 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccess.php @@ -0,0 +1,57 @@ +<?php +/** + * $Id: b6ea3e7df3c43498e8c6e105bedfd0b6e99e055a $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phk/PhkPackageWebAccessPath.php'; + +/** + * @author Alexey Shockov <alexey@shockov.com> + * @package phing.tasks.ext.phk + */ +class PhkPackageWebAccess +{ + /** + * @var array + */ + private $paths = array(); + /** + * @return PhkPackageWebAccessPath + */ + public function createPath() + { + return ($this->paths[] = new PhkPackageWebAccessPath()); + } + /** + * @return array + */ + public function getPaths() + { + /* + * Get real paths... + */ + $paths = array(); + + foreach ($this->paths as $path) { + $paths[] = $path->getPath(); + } + + return $paths; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccessPath.php b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccessPath.php new file mode 100644 index 00000000..730a8929 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phk/PhkPackageWebAccessPath.php @@ -0,0 +1,46 @@ +<?php +/** + * $Id: 755aeaf34726af2eb30c989914faad8d7aebd126 $ + * + * 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>. + */ + +/** + * @author Alexey Shockov <alexey@shockov.com> + * @package phing.tasks.ext.phk + */ +class PhkPackageWebAccessPath +{ + /** + * @var string + */ + private $path; + /** + * @param string $path + */ + public function addText($path) + { + $this->path = trim($path); + } + /** + * @return string + */ + public function getPath() + { + return $this->path; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php new file mode 100644 index 00000000..e650ca72 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php @@ -0,0 +1,177 @@ +<?php +/** + * $Id: dece05e79e883b4d5e95f2215e36ce4f2f72ed2e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; + +/** + * A wrapper for the implementations of PHPCPDResultFormatter. + * + * @package phing.tasks.ext.phpcpd + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: dece05e79e883b4d5e95f2215e36ce4f2f72ed2e $ + */ +class PHPCPDFormatterElement +{ + /** + * The report result formatter. + * + * @var PHPCPDResultFormatter + */ + protected $_formatter = null; + + /** + * The type of the formatter. + * + * @var string + */ + protected $_type = ''; + + /** + * Whether to use file (or write output to phing log). + * + * @var boolean + */ + protected $_useFile = true; + + /** + * Output file for formatter. + * + * @var PhingFile + */ + protected $_outfile = null; + + /** + * The parent task + * + * @var PHPCPDTask + */ + private $_parentTask; + + /** + * Construct a new PHPCPDFormatterElement with parent task. + * @param PHPCPDTask $parentTask + */ + public function __construct(PHPCPDTask $parentTask) + { + $this->_parentTask = $parentTask; + } + + /** + * Sets the formatter type. + * + * @param string $type Type of the formatter + * + * @return void + */ + public function setType($type) + { + $this->_type = $type; + + switch ($this->_type) { + case 'pmd': + if ($this->_useFile === false) { + throw new BuildException( + "Formatter '" . $this->_type + . "' can only print the result to an file" + ); + } + + include_once 'phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php'; + $this->_formatter = new PMDPHPCPDResultFormatter(); + break; + + case 'default': + include_once 'phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php'; + $this->_formatter = new DefaultPHPCPDResultFormatter(); + break; + + default: + throw new BuildException( + "Formatter '" . $this->_type . "' not implemented" + ); + } + } + + /** + * Get the formatter type + * + * @return string + */ + public function getType() + { + return $this->_type; + } + + /** + * Set whether to write formatter results to file or not. + * + * @param boolean $useFile True or false. + * + * @return void + */ + public function setUseFile($useFile) + { + $this->_useFile = StringHelper::booleanValue($useFile); + } + + /** + * Return whether to write formatter results to file or not. + * + * @return boolean + */ + public function getUseFile() + { + return $this->_useFile; + } + + /** + * Sets the output file for the formatter results. + * + * @param PhingFile $outfile The output file + * + * @return void + */ + public function setOutfile(PhingFile $outfile) + { + $this->_outfile = $outfile; + } + + /** + * Get the output file. + * + * @return PhingFile + */ + public function getOutfile() + { + return $this->_outfile; + } + + /** + * Returns the report formatter. + * + * @throws BuildException When the specified renderer does not exist. + * @return PHPCPDResultFormatter + */ + public function getFormatter() + { + return $this->_formatter; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php new file mode 100644 index 00000000..31f76154 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php @@ -0,0 +1,312 @@ +<?php +/** + * $Id: 8fbff39b2ca68e97afd59d5dc6d5a37c3678624e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * Runs PHP Copy & Paste Detector. Checking PHP files for duplicated code. + * Refactored original PhpCpdTask provided by + * Timo Haberkern <timo.haberkern@fantastic-bits.de> + * + * @package phing.tasks.ext.phpcpd + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 8fbff39b2ca68e97afd59d5dc6d5a37c3678624e $ + */ +class PHPCPDTask extends Task +{ + /** + * A php source code filename or directory + * + * @var PhingFile + */ + protected $_file = null; + + /** + * All fileset objects assigned to this task + * + * @var array<FileSet> + */ + protected $_filesets = array(); + + /** + * Minimum number of identical lines. + * + * @var integer + */ + protected $_minLines = 5; + + /** + * Minimum number of identical tokens. + * + * @var integer + */ + protected $_minTokens = 70; + + /** + * List of valid file extensions for analyzed files. + * + * @var array + */ + protected $_allowedFileExtensions = array('php'); + + /** + * List of exclude directory patterns. + * + * @var array + */ + protected $_ignorePatterns = array('.git', '.svn', 'CVS', '.bzr', '.hg'); + + /** + * The format for the report + * + * @var string + */ + protected $_format = 'default'; + + /** + * Formatter elements. + * + * @var array<PHPCPDFormatterElement> + */ + protected $_formatters = array(); + + /** + * Load the necessary environment for running PHPCPD. + * + * @throws BuildException - if the phpcpd classes can't be loaded. + */ + public function init() + { + /** + * Determine PHPCPD installation + */ + @include_once 'PHPCPD/Autoload.php'; + + if (! class_exists('PHPCPD_TextUI_Command')) { + throw new BuildException( + 'PHPCPDTask depends on PHPCPD being installed ' + . 'and on include_path.', + $this->getLocation() + ); + } + + // Other dependencies that should only be loaded + // when class is actually used + require_once 'phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php'; + } + + /** + * Set the input source file or directory. + * + * @param PhingFile $file The input source file or directory. + * + * @return void + */ + public function setFile(PhingFile $file) + { + $this->_file = $file; + } + + /** + * Nested creator, adds a set of files (nested fileset attribute). + * + * @param FileSet $fs List of files to scan + * + * @return void + */ + public function addFileSet(FileSet $fs) + { + $this->_filesets[] = $fs; + } + + /** + * Sets the minimum number of identical lines (default: 5). + * + * @param integer $minLines Minimum number of identical lines + * + * @return void + */ + public function setMinLines($minLines) + { + $this->_minLines = $minLines; + } + + /** + * Sets the minimum number of identical tokens (default: 70). + * + * @param integer $minTokens Minimum number of identical tokens + */ + public function setMinTokens($minTokens) + { + $this->_minTokens = $minTokens; + } + + /** + * Sets a list of filename extensions for valid php source code files. + * + * @param string $fileExtensions List of valid file extensions. + * + * @return void + */ + public function setAllowedFileExtensions($fileExtensions) + { + $this->_allowedFileExtensions = array(); + + $token = ' ,;'; + $ext = strtok($fileExtensions, $token); + + while ($ext !== false) { + $this->_allowedFileExtensions[] = $ext; + $ext = strtok($token); + } + } + + /** + * Sets a list of ignore patterns that is used to exclude directories from + * the source analysis. + * + * @param string $ignorePatterns List of ignore patterns. + * + * @return void + */ + public function setIgnorePatterns($ignorePatterns) + { + $this->_ignorePatterns = array(); + + $token = ' ,;'; + $pattern = strtok($ignorePatterns, $token); + + while ($pattern !== false) { + $this->_ignorePatterns[] = $pattern; + $pattern = strtok($token); + } + } + + /** + * Sets the output format + * + * @param string $format Format of the report + */ + public function setFormat($format) + { + $this->_format = $format; + } + + /** + * Create object for nested formatter element. + * + * @return PHPCPDFormatterElement + */ + public function createFormatter() + { + $num = array_push( + $this->_formatters, + new PHPCPDFormatterElement($this) + ); + return $this->_formatters[$num-1]; + } + + /** + * Executes PHPCPD against PhingFile or a FileSet + * + * @return void + */ + public function main() + { + if (!isset($this->_file) and count($this->_filesets) == 0) { + throw new BuildException( + "Missing either a nested fileset or attribute 'file' set" + ); + } + + if (count($this->_formatters) == 0) { + // turn legacy format attribute into formatter + $fmt = new PHPCPDFormatterElement($this); + $fmt->setType($this->_format); + $fmt->setUseFile(false); + $this->_formatters[] = $fmt; + } + + $this->validateFormatters(); + + $filesToParse = array(); + + if ($this->_file instanceof PhingFile) { + $filesToParse[] = $this->_file->getPath(); + } else { + // append any files in filesets + foreach ($this->_filesets as $fs) { + $files = $fs->getDirectoryScanner($this->project) + ->getIncludedFiles(); + + foreach ($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $filesToParse[] = $f->getAbsolutePath(); + } + } + } + + $this->log('Processing files...'); + + $detector = new PHPCPD_Detector(new PHPCPD_Detector_Strategy_Default()); + $clones = $detector->copyPasteDetection( + $filesToParse, + $this->_minLines, + $this->_minTokens + ); + + $this->log('Finished copy/paste detection'); + + foreach ($this->_formatters as $fe) { + $formatter = $fe->getFormatter(); + $formatter->processClones( + $clones, + $this->project, + $fe->getUseFile(), + $fe->getOutfile() + ); + } + } + + /** + * Validates the available formatters + * + * @throws BuildException + * @return void + */ + protected function validateFormatters() + { + foreach ($this->_formatters as $fe) { + if ($fe->getType() == '') { + throw new BuildException( + "Formatter missing required 'type' attribute." + ); + } + + if ($fe->getUsefile() && $fe->getOutfile() === null) { + throw new BuildException( + "Formatter requires 'outfile' attribute " + . "when 'useFile' is true." + ); + } + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php new file mode 100644 index 00000000..b84da547 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php @@ -0,0 +1,58 @@ +<?php +/** + * $Id: a4825de14746285d97af9d435215ec8400406fa7 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PHPCPD/TextUI/ResultPrinter.php'; +require_once 'phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php'; + +/** + * Prints plain text output of phpcpd run + * + * @package phing.tasks.ext.phpcpd.formatter + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: a4825de14746285d97af9d435215ec8400406fa7 $ + */ +class DefaultPHPCPDResultFormatter extends PHPCPDResultFormatter +{ + + /** + * Processes a list of clones. + * + * @param PHPCPD_CloneMap $clones + * @param Project $project + * @param boolean $useFile + * @param PhingFile|null $outfile + */ + public function processClones(PHPCPD_CloneMap $clones, Project $project, $useFile = false, $outFile = null) + { + $logger = new PHPCPD_TextUI_ResultPrinter(); + // default format goes to logs, no buffering + ob_start(); + $logger->printResult($clones, $project->getBaseDir(), true); + $output = ob_get_contents(); + ob_end_clean(); + + if (!$useFile || empty($outFile)) { + echo $output; + } else { + file_put_contents($outFile->getPath(), $output); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php new file mode 100644 index 00000000..0cdab194 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php @@ -0,0 +1,40 @@ +<?php +/** + * $Id: 478d7a823945aa4706befb0059b2fab28743fb07 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * This abstract class describes classes that format the results of a PHPCPD run. + * + * @package phing.tasks.ext.phpcpd.formatter + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 478d7a823945aa4706befb0059b2fab28743fb07 $ + */ +abstract class PHPCPDResultFormatter +{ + /** + * Processes a list of clones. + * + * @param PHPCPD_CloneMap $clones + * @param Project $project + * @param boolean $useFile + * @param PhingFile|null $outfile + */ + abstract public function processClones(PHPCPD_CloneMap $clones, Project $project, $useFile = false, $outFile = null); +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php new file mode 100644 index 00000000..33c24407 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php @@ -0,0 +1,51 @@ +<?php +/** + * $Id: a336822b8c54702ba2b0590e5a812c779e5c221b $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PHPCPD/Log/XML/PMD.php'; +require_once 'phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.php'; + +/** + * Prints PMD-XML output of phpcpd run + * + * @package phing.tasks.ext.phpcpd.formatter + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: a336822b8c54702ba2b0590e5a812c779e5c221b $ + */ +class PMDPHPCPDResultFormatter extends PHPCPDResultFormatter +{ + /** + * Processes a list of clones. + * + * @param PHPCPD_CloneMap $clones + * @param Project $project + * @param boolean $useFile + * @param PhingFile|null $outfile + */ + public function processClones(PHPCPD_CloneMap $clones, Project $project, $useFile = false, $outFile = null) + { + if (!$useFile || empty($outFile)) { + throw new BuildException("Output filename required for this formatter"); + } + + $logger = new PHPCPD_Log_XML_PMD($outFile); + $logger->processClones($clones); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php deleted file mode 100644 index 2fefc4e5..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - - /** - * $Id: PHPDocumentorTask.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - - require_once 'phing/Task.php'; - - /** - * Task to run phpDocumentor. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPDocumentorTask.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpdoc - */ - class PHPDocumentorTask extends Task - { - /** - * The name of the executable for phpDocumentor - */ - const PHPDOC = 'phpdoc'; - - private $title = "Default Title"; - - private $destdir = "."; - - private $sourcepath = NULL; - - private $output = ""; - - private $linksource = false; - - private $parseprivate = false; - - /** - * Set the title for the generated documentation - */ - function setTitle($title) - { - $this->title = $title; - } - - /** - * Set the destination directory for the generated documentation - */ - function setDestdir($destdir) - { - $this->destdir = $destdir; - } - - /** - * Set the source path - */ - function setSourcepath(Path $sourcepath) - { - if ($this->sourcepath === NULL) - { - $this->sourcepath = $sourcepath; - } - else - { - $this->sourcepath->append($sourcepath); - } - } - - /** - * Set the output type - */ - function setOutput($output) - { - $this->output = $output; - } - - /** - * Should sources be linked in the generated documentation - */ - function setLinksource($linksource) - { - $this->linksource = $linksource; - } - - /** - * Should private members/classes be documented - */ - function setParseprivate($parseprivate) - { - $this->parseprivate = $parseprivate; - } - - /** - * Main entrypoint of the task - */ - function main() - { - $arguments = $this->constructArguments(); - - exec(self::PHPDOC . " " . $arguments, $output, $retval); - } - - /** - * Constructs an argument string for phpDocumentor - */ - private function constructArguments() - { - $arguments = "-q "; - - if ($this->title) - { - $arguments.= "-ti \"" . $this->title . "\" "; - } - - if ($this->destdir) - { - $arguments.= "-t " . $this->destdir . " "; - } - - if ($this->sourcepath !== NULL) - { - $arguments.= "-d " . $this->sourcepath->__toString() . " "; - } - - if ($this->output) - { - $arguments.= "-o " . $this->output . " "; - } - - if ($this->linksource) - { - $arguments.= "-s "; - } - - if ($this->parseprivate) - { - $arguments.= "-pp "; - } - - return $arguments; - } - }; - -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php new file mode 100644 index 00000000..462b1d99 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php @@ -0,0 +1,98 @@ +<?php +/** + * $Id: 73c919ab2044bf6582f52bd7ccb0184019d52f53 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PhpDocumentor/phpDocumentor/Errors.inc'; + +/** + * Phing subclass of the ErrorTracker class provided with PhpDocumentor to work around limitations in PhpDocumentor API. + * + * This class is necessary because PhpDocumentor does directly output errors and + * warnings occured during testing for undocumented elements to stdout. + * This class is injected globally to force PhpDocumentor to use phing's logging + * mechanism. + * + * Obviously this is far from ideal, but there's also no solution given the inflexibility of the + * PhpDocumentor design. + * + * @author Timo A. Hummel <privat@timohummel.com> @author felicitus + * @version $Id: 73c919ab2044bf6582f52bd7ccb0184019d52f53 $ + * @package phing.tasks.ext.phpdoc + */ +class PhingPhpDocumentorErrorTracker extends ErrorTracker { + + /* + * @var object Reference to the task we're called with + */ + private $task; + + /** + * Outputs a warning. This is an almost 1:1 copy from PhpDocumentor, + * we're just processing the warning text and send it to phing's logger. + * + * @param $num integer Number of parameters + * @return nothing + */ + function addWarning ($num) { + $a = array('', '', '', ''); + if (func_num_args()>1) { + for ($i=1;$i<func_num_args();$i++) { + $a[$i - 1] = func_get_arg($i); + } + } + + $message = sprintf($GLOBALS['phpDocumentor_warning_descrip'][$num], $a[0], $a[1], $a[2], $a[3]); + $this->task->log($message, Project::MSG_WARN); + + } + + /** + * Outputs an error. This is an almost 1:1 copy from PhpDocumentor, + * we're just processing the error text and send it to phing's logger. + * + * @param $num integer Number of parameters + * @return nothing + */ + + function addError ($num) { + $a = array('', '', '', ''); + if (func_num_args()>1) { + for ($i=1;$i<func_num_args();$i++) { + $a[$i - 1] = func_get_arg($i); + } + } + + $message = sprintf($GLOBALS['phpDocumentor_error_descrip'][$num], $a[0], $a[1], $a[2], $a[3]); + $this->task->log($message, Project::MSG_ERR); + + } + + /** + * Sets the task we're working with. This is necessary since we need to be + * able to call the method "log". + * + * @param object $task The task we're working with + * @return nothing + */ + public function setTask ($task) { + $this->task = $task; + } + +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php new file mode 100644 index 00000000..62662b0b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php @@ -0,0 +1,230 @@ +<?php +/** + * $Id: cde99d501839daf8c9dd9df61ee6cce7caad6b3e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PhpDocumentor/phpDocumentor/Setup.inc.php'; + +/** + * Phing subclass of the phpDocumentor_setup class provided with PhpDocumentor to work around limitations in PhpDocumentor API. + * + * This class is necessary because phpDocumentor_setup does not expose a complete API for setting configuration options. Because + * this class must directly modify some "private" GLOBAL(!) configuration variables, it is liable to break if the PhpDocumentor + * internal implementation changes. Obviously this is far from ideal, but there's also no solution given the inflexibility of the + * PhpDocumentor design. + * + * @author Hans Lellelid <hans@xmpl.org>@author hans + * @version $Id: cde99d501839daf8c9dd9df61ee6cce7caad6b3e $ + * @package phing.tasks.ext.phpdoc + */ +class PhingPhpDocumentorSetup extends phpDocumentor_setup { + + /** + * Constructs a new PhingPhpDocumentorSetup. + * + * @param string $configDir Directory in which to look for configuration files. + * @param object $task The task we're working with, so we can pass it on to the ErrorTracker + */ + public function __construct($configdir = null, $task) { + global $_phpDocumentor_cvsphpfile_exts, $_phpDocumentor_setting, $_phpDocumentor_phpfile_exts; + + $this->setup = new Io(); + $this->render = new phpDocumentor_IntermediateParser("Default Title"); + + $GLOBALS['_phpDocumentor_install_dir'] = $configdir; + $this->parseIni(); + + // These redundant-looking lines seem to actually make a difference. + // See: http://phing.info/trac/ticket/150 + $_phpDocumentor_phpfile_exts = $GLOBALS['_phpDocumentor_phpfile_exts']; + $_phpDocumentor_cvsphpfile_exts = $GLOBALS['_phpDocumentor_cvsphpfile_exts']; + + if (tokenizer_ext) { + $this->parse = new phpDocumentorTParser(); + } else { + $this->parse = new Parser(); + } + + $this->setMemoryLimit(); + + include_once 'phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php'; + + // Inject our own error tracker to PhpDocumentor + $GLOBALS['phpDocumentor_errors'] = new PhingPhpDocumentorErrorTracker; + $GLOBALS['phpDocumentor_errors']->setTask($task); + + } + + /** + * Set whether to generate sourcecode for each file parsed. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param bool $b + */ + public function setGenerateSourcecode($b) { + global $_phpDocumentor_setting; + $_phpDocumentor_setting['sourcecode'] = (boolean) $b; + } + + /** + * Set an array of README/INSTALL/CHANGELOG file paths. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param array $files Absolute paths to files. + */ + public function setRicFiles($files) { + global $_phpDocumentor_RIC_files; + $_phpDocumentor_RIC_files = $files; + } + + /** + * Set comma-separated list of tags to ignore. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param string $tags + */ + public function setIgnoreTags($tags) { + global $_phpDocumentor_setting; + $ignoretags = explode(',', $tags); + $ignoretags = array_map('trim', $ignoretags); + $tags = array(); + foreach($ignoretags as $tag) { + if (!in_array($tag,array('@global', '@access', '@package', '@ignore', '@name', '@param', '@return', '@staticvar', '@var'))) + $tags[] = $tag; + } + $_phpDocumentor_setting['ignoretags'] = $tags; + } + + /** + * Set whether to parse dirs as PEAR repos. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param bool $b + */ + public function setPear($b) { + global $_phpDocumentor_setting; + $_phpDocumentor_setting['pear'] = (boolean) $b; + } + + /** + * Set fullpath to directory to look in for examples. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param string $dir + */ + public function setExamplesDir($dir) { + global $_phpDocumentor_setting; + $_phpDocumentor_setting['examplesdir'] = $dir; + } + + /** + * Sets the default package name. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param string $name + */ + public function setDefaultPackageName($name) { + $GLOBALS['phpDocumentor_DefaultPackageName'] = trim($name); + } + + /** + * Sets the default category name. + * + * This method exists as a hack because there is no API exposed for this in PhpDocumentor. + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + * @param string $name + */ + public function setDefaultCategoryName($name) { + $GLOBALS['phpDocumentor_DefaultCategoryName'] = trim($name); + } + + /** + * Enables quiet mode. + * + * This method exists as a hack because the API exposed for this method in PhpDocumentor + * doesn't work correctly. + * + * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this + * is subject to break if PhpDocumentor internals changes. + * + */ + public function setQuietMode() { + global $_phpDocumentor_setting; + $_phpDocumentor_setting['quiet'] = true; + parent::setQuietMode(); + } + + /** + * Control whether or not warnings will be shown for undocumented elements. + * Useful for identifying classes and methods that haven't yet been + * documented. + * + * @param bool $bEnable + */ + public function setUndocumentedelements($bEnable) { + $this->render->setUndocumentedElementWarningsMode($bEnable); + } + + /** + * custom tags, will be recognized and put in tags[] instead of + * unknowntags[] + * + * This method exists as a hack because the API exposed for this method in + * PhpDocumentor doesn't work correctly. + * + * Note that because we are setting a "private" GLOBAL(!!) config var with + * this value, this is subject to break if PhpDocumentor internals changes. + * + * @param string $sCustomtags + */ + public function setCustomtags($sCustomtags) { + global $_phpDocumentor_setting; + $_phpDocumentor_setting['customtags'] = $sCustomtags; + } + + /** + * Files to ignore + * + * @param string $sIgnore + */ + public function setIgnore($sIgnore) { + global $_phpDocumentor_setting; + $_phpDocumentor_setting['ignore'] = $sIgnore; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.php new file mode 100755 index 00000000..70fcc9e2 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.php @@ -0,0 +1,224 @@ +<?php +/* + * $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/FileOutputStream.php'; + +/** + * PhpDocumentor2 Task (http://www.phpdoc.org) + * Based on the DocBlox Task + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: eaa494390770adc752097a412d63fb863482fd5d $ + * @since 2.4.10 + * @package phing.tasks.ext.phpdoc + */ +class PhpDocumentor2Task extends Task +{ + /** + * List of filesets + * @var FileSet[] + */ + private $filesets = array(); + + /** + * Destination/target directory + * @var PhingFile + */ + private $destDir = null; + + /** + * name of the template to use + * @var string + */ + private $template = "responsive"; + + /** + * Title of the project + * @var string + */ + private $title = ""; + + /** + * Force phpDocumentor to be quiet + * @var boolean + */ + private $quiet = true; + + /** + * Nested creator, adds a set of files (nested fileset attribute). + * + * @return FileSet + */ + public function createFileSet() + { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Sets destination/target directory + * @param PhingFile $destDir + */ + public function setDestDir(PhingFile $destDir) + { + $this->destDir = $destDir; + } + + /** + * Convenience setter (@see setDestDir) + * @param PhingFile $output + */ + public function setOutput(PhingFile $output) + { + $this->destDir = $output; + } + + /** + * Sets the template to use + * @param strings $template + */ + public function setTemplate($template) + { + $this->template = (string) $template; + } + + /** + * Sets the title of the project + * @param strings $title + */ + public function setTitle($title) + { + $this->title = (string) $title; + } + + /** + * Forces phpDocumentor to be quiet + * @param boolean $quiet + */ + public function setQuiet($quiet) + { + $this->quiet = (boolean) $quiet; + } + + /** + * Finds and initializes the phpDocumentor installation + */ + private function initializePhpDocumentor() + { + $phpDocumentorPath = null; + + foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) { + $testPhpDocumentorPath = $path . DIRECTORY_SEPARATOR . 'phpDocumentor' . DIRECTORY_SEPARATOR . 'src'; + + if (file_exists($testPhpDocumentorPath)) { + $phpDocumentorPath = $testPhpDocumentorPath; + } + } + + if (empty($phpDocumentorPath)) { + throw new BuildException("Please make sure PhpDocumentor 2 is installed and on the include_path.", $this->getLocation()); + } + + set_include_path($phpDocumentorPath . PATH_SEPARATOR . get_include_path()); + + require_once $phpDocumentorPath . '/phpDocumentor/Bootstrap.php'; + + $bootstrap = phpDocumentor_Bootstrap::createInstance(); + + $autoloader = $bootstrap->registerAutoloader(); + + if ($this->quiet) { + phpDocumentor_Core_Abstract::config()->logging->level = 'quiet'; + } else { + phpDocumentor_Core_Abstract::config()->logging->level = 'debug'; + } + + $bootstrap->registerPlugins($autoloader); + } + + /** + * Build a list of files (from the fileset elements) + * and call the phpDocumentor parser + * + * @return string + */ + private function parseFiles() + { + $parser = new phpDocumentor_Parser(); + + //Only initialize the dispatcher when not already done + if (is_null(phpDocumentor_Parser_Abstract::$event_dispatcher)) { + phpDocumentor_Parser_Abstract::$event_dispatcher = new sfEventDispatcher(); + } + $parser->setTitle($this->title); + + $paths = array(); + + // filesets + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($this->project); + $dir = $fs->getDir($this->project); + $srcFiles = $ds->getIncludedFiles(); + + foreach ($srcFiles as $file) { + $paths[] = $dir . FileSystem::getFileSystem()->getSeparator() . $file; + } + } + + $this->log("Will parse " . count($paths) . " file(s)", Project::MSG_VERBOSE); + + $files = new phpDocumentor_Parser_Files(); + $files->addFiles($paths); + + $parser->setPath($files->getProjectRoot()); + + return $parser->parseFiles($files); + } + + /** + * Task entry point + * @see Task::main() + */ + public function main() + { + if (empty($this->destDir)) { + throw new BuildException("You must supply the 'destdir' attribute", $this->getLocation()); + } + + if (empty($this->filesets)) { + throw new BuildException("You have not specified any files to include (<fileset>)", $this->getLocation()); + } + + $this->initializePhpDocumentor(); + + $xml = $this->parseFiles(); + + $this->log("Transforming...", Project::MSG_VERBOSE); + + $transformer = new phpDocumentor_Transformer(); + $transformer->setTemplatesPath(phpDocumentor_Core_Abstract::config()->paths->templates); + $transformer->setTemplates($this->template); + $transformer->setSource($xml); + $transformer->setTarget($this->destDir->getAbsolutePath()); + $transformer->execute(); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php new file mode 100755 index 00000000..fb2a0b2b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php @@ -0,0 +1,265 @@ +<?php + +/** + * $Id: 6a6c740651bb91c9854fcdf0cb1d7e768b84f805 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phpdoc/PhpDocumentorTask.php'; + +/** + * Task to run phpDocumentor with an external process + * + * This classes uses the commandline phpdoc script to build documentation. + * Use this task instead of the PhpDocumentorTask when you've a clash with the + * Smarty libraries. + * + * @author Michiel Rook <mrook@php.net> + * @author Markus Fischer <markus@fischer.name> + * @version $Id: 6a6c740651bb91c9854fcdf0cb1d7e768b84f805 $ + * @package phing.tasks.ext.phpdoc + */ +class PhpDocumentorExternalTask extends PhpDocumentorTask +{ + /** + * The path to the executable for phpDocumentor + */ + protected $programPath = 'phpdoc'; + + protected $sourcepath = NULL; + + /** + * @var bool ignore symlinks to other files or directories + */ + protected $ignoresymlinks = false; + + /** + * Sets the path to the phpDocumentor executable + */ + public function setProgramPath($programPath) + { + $this->programPath = $programPath; + } + + /** + * Returns the path to the phpDocumentor executable + */ + public function getProgramPath() + { + return $this->programPath; + } + + /** + * Set the source path. A directory or a comma separate list of directories. + */ + public function setSourcepath($sourcepath) + { + $this->sourcepath = $sourcepath; + } + + /** + * Ignore symlinks to other files or directories. + * + * @param bool $bSet + */ + public function setIgnoresymlinks($bSet) { + $this->ignoresymlinks = $bSet; + } + + /** + * Main entrypoint of the task + */ + public function main() + { + $this->validate(); + $arguments = join(' ', $this->constructArguments()); + + $this->log("Running phpDocumentor..."); + + exec($this->programPath . " " . $arguments, $output, $return); + + if ($return != 0) + { + throw new BuildException("Could not execute phpDocumentor: " . implode(' ', $output)); + } + + foreach($output as $line) + { + if(strpos($line, 'ERROR') !== false) + { + $this->log($line, Project::MSG_ERR); + continue; + } + + $this->log($line, Project::MSG_VERBOSE); + } + } + + /** + * Constructs an argument string for phpDocumentor + * @return array + */ + protected function constructArguments() + { + $aArgs = array(); + if ($this->title) + { + $aArgs[] = '--title "' . $this->title . '"'; + } + + if ($this->destdir) + { + $aArgs[] = '--target "' . $this->destdir->getAbsolutePath() . '"'; + } + + if ($this->sourcepath) + { + $aArgs[] = '--directory "' . $this->sourcepath . '"'; + } + + if ($this->output) + { + $aArgs[] = '--output ' . $this->output; + } + + if ($this->linksource) + { + $aArgs[] = '--sourcecode on'; + } + + if ($this->parseprivate) + { + $aArgs[] = '--parseprivate on'; + } + + if ($this->ignore) + { + $aArgs[] = '--ignore ' . $this->ignore; + } + + // append any files in filesets + $filesToParse = array(); + foreach($this->filesets as $fs) { + $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); + foreach($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $filesToParse[] = $f->getAbsolutePath(); + } + } + if (count($filesToParse) > 0) { + $aArgs[] = '--filename "' . join(',', $filesToParse) . '"'; + } + + // append any files in filesets + $ricFiles = array(); + foreach($this->projDocFilesets as $fs) { + $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); + foreach($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $ricFiles[] = $f->getAbsolutePath(); + } + } + if (count($ricFiles) > 0) { + $aArgs[] = '--readmeinstallchangelog "' . + join(',', $ricFiles) . '"'; + } + + if ($this->javadocDesc) { + $aArgs[] = '--javadocdesc on'; + } + + if ($this->quiet) { + $aArgs[] = '--quiet on'; + } + + if ($this->packages) { + $aArgs[] = '--packageoutput "' . $this->packages . '"'; + } + + if ($this->ignoreTags) { + $aArgs[] = '--ignore-tags "' . $this->ignoreTags . '"'; + } + + if ($this->defaultCategoryName) { + $aArgs[] = '--defaultcategoryname "' . $this->defaultCategoryName . + '"'; + } + + if ($this->examplesDir) { + $aArgs[] = '--examplesdir "' . $this->examplesDir->getAbsolutePath() + . '"'; + } + + if ($this->templateBase) { + $aArgs[] = '--templatebase "' . $this->templateBase->getAbsolutePath() + . '"'; + } + + if ($this->pear) { + $aArgs[] = '--pear on'; + } + + if ($this->undocumentedelements) { + $aArgs[] = '--undocumentedelements on'; + } + + if ($this->customtags) { + $aArgs[] = '--customtags "' . $this->customtags . '"'; + } + + if ($this->ignoresymlinks) { + $aArgs[] = '--ignoresymlinks on'; + } + + return $aArgs; + } + + /** + * Override PhpDocumentorTask::init() because they're specific to the phpdoc + * API which we don't use. + */ + public function init() { + } + + /** + * Validates that necessary minimum options have been set. Based on + * PhpDocumentorTask::validate(). + */ + protected function validate() { + if (!$this->destdir) { + throw new BuildException("You must specify a destdir for phpdoc.", + $this->getLocation()); + } + if (!$this->output) { + throw new BuildException("You must specify an output format for " . + "phpdoc (e.g. HTML:frames:default).", $this->getLocation()); + } + if (empty($this->filesets) && !$this->sourcepath) { + throw new BuildException("You have not specified any files to " . + "include (<fileset> or sourcepath attribute) for phpdoc.", + $this->getLocation()); + } + if ($this->configdir) { + $this->log('Ignoring unsupported configdir-Attribute', + Project::MSG_VERBOSE); + } + } +}; + + + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php new file mode 100755 index 00000000..e4ae363a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php @@ -0,0 +1,480 @@ +<?php + +/** + * $Id: 23a04ddae9cad46198e15081a0fb44354135b1c8 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * Task to run PhpDocumentor. + * + * @author Hans Lellelid <hans@xmpl.org> + * @author Michiel Rook <mrook@php.net> + * @version $Id: 23a04ddae9cad46198e15081a0fb44354135b1c8 $ + * @package phing.tasks.ext.phpdoc + */ +class PhpDocumentorTask extends Task +{ + + /** + * @var string Title for browser window / package index. + */ + protected $title; + + /** + * @var PhingFile The target directory for output files. + */ + protected $destdir; + + /** + * @var array FileSet[] Filesets for files to parse. + */ + protected $filesets = array(); + + /** + * @var array FileSet[] Project documentation (README/INSTALL/CHANGELOG) files. + */ + protected $projDocFilesets = array(); + + /** + * @var string Package output format. + */ + protected $output; + + /** + * @var boolean Whether to generate sourcecode for each file parsed. + */ + protected $linksource = false; + + /** + * @var boolean Whether to parse private members. + */ + protected $parsePrivate = false; + + /** + * @var boolean Whether to use javadoc descriptions (more primitive). + */ + protected $javadocDesc = false; + + /** + * @var PhingFile Base directory for locating template files. + */ + protected $templateBase; + + /** + * @var boolean Wheter to suppress output. + */ + protected $quiet = false; + + /** + * @var string Comma-separated list of packages to output. + */ + protected $packages; + + /** + * @var string Comma-separated list of tags to ignore. + */ + protected $ignoreTags; + + /** + * @var string Default package name. + */ + protected $defaultPackageName; + + /** + * @var string Default category name. + */ + protected $defaultCategoryName; + + /** + * @var PhingFile Directory in which to look for examples. + */ + protected $examplesDir; + + /** + * @var PhingFile Directory in which to look for configuration files. + */ + protected $configDir; + + /** + * @var boolean Whether to parse as a PEAR repository. + */ + protected $pear = false; + + /** + * @var boolean Control whether or not warnings will be shown for + * undocumented elements. Useful for identifying classes and + * methods that haven't yet been documented. + */ + protected $undocumentedelements = false; + + /** + * @var string custom tags, will be recognized and put in tags[] instead of + * unknowntags[]. + */ + protected $customtags = ''; + + /** + * @var string files to ignore + */ + protected $ignore = ''; + + /** + * Set the title for the generated documentation + */ + public function setTitle($title) { + $this->title = $title; + } + + /** + * Set the destination directory for the generated documentation + */ + public function setDestdir(PhingFile $destdir) { + $this->destdir = $destdir; + } + + /** + * Alias for {@link setDestdir()}. + * @see setDestdir() + */ + public function setTarget(PhingFile $destdir) { + $this->setDestdir($destdir); + } + + /** + * Set the output format (e.g. HTML:Smarty:PHP). + * @param string $output + */ + public function setOutput($output) { + $this->output = $output; + } + + /** + * Set whether to generate sourcecode for each file parsed + * @param boolean + */ + public function setSourcecode($b) { + $this->setLinksource($b); + } + + /** + * Set whether to generate sourcecode for each file parsed + * @param boolean + */ + public function setLinksource($b) { + $this->linksource = $b; + } + + /** + * Set whether to suppress output. + * @param boolean $b + */ + public function setQuiet($b) { + $this->quiet = $b; + } + + /** + * Should private members/classes be documented + * @param boolean + */ + public function setParseprivate($parseprivate) { + $this->parsePrivate = $parseprivate; + } + + /** + * Whether to use javadoc descriptions (more primitive). + * @param boolean + */ + public function setJavadocdesc($javadoc) { + $this->javadocDesc = $javadoc; + } + + /** + * Set (comma-separated) list of packages to output. + * + * @param string $packages + */ + public function setPackageoutput($packages) { + $this->packages = $packages; + } + + /** + * Set (comma-separated) list of tags to ignore. + * + * @param string $tags + */ + public function setIgnoretags($tags) { + $this->ignoreTags = $tags; + } + + /** + * Set a directory to search for examples in. + * @param PhingFile $d + */ + public function setExamplesdir(PhingFile $d) { + $this->examplesDir = $d; + } + + /** + * Set a directory to search for configuration files in. + * @param PhingFile $d + */ + public function setConfigdir(PhingFile $d) { + $this->configDir = $d; + } + + /** + * Sets the default package name. + * @param string $name + */ + public function setDefaultpackagename($name) { + $this->defaultPackageName = $name; + } + + /** + * Sets the default category name. + * @param string $name + */ + public function setDefaultcategoryname($name) { + $this->defaultCategoryName = $name; + } + + /** + * Set whether to parse as PEAR repository. + * @param boolean $b + */ + public function setPear($b) { + $this->pear = $b; + } + + /** + * Creates a FileSet. + * @return FileSet + */ + public function createFileset() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Creates a readme/install/changelog fileset. + * @return FileSet + */ + public function createProjdocfileset() { + $num = array_push($this->projDocFilesets, new FileSet()); + return $this->projDocFilesets[$num-1]; + } + + /** + * Control whether or not warnings will be shown for undocumented elements. + * Useful for identifying classes and methods that haven't yet been + * documented. + * @param boolean $b + */ + public function setUndocumentedelements($b) { + $this->undocumentedelements = $b; + } + + /** + * custom tags, will be recognized and put in tags[] instead of + * unknowntags[]. + * + * @param string $sCustomtags + */ + public function setCustomtags($sCustomtags) { + $this->customtags = $sCustomtags; + } + + /** + * Set base location of all templates for this parse. + * + * @param PhingFile $destdir + */ + public function setTemplateBase(PhingFile $oTemplateBase) { + $this->templateBase = $oTemplateBase; + } + + /** + * Set files to ignore + * @param string $sIgnore + */ + public function setIgnore($sIgnore) { + $this->ignore = $sIgnore; + } + + /** + * Searches include_path for PhpDocumentor install and adjusts include_path appropriately. + * @throws BuildException - if unable to find PhpDocumentor on include_path + */ + protected function findPhpDocumentorInstall() + { + $found = null; + foreach(explode(PATH_SEPARATOR, get_include_path()) as $path) { + $testpath = $path . DIRECTORY_SEPARATOR . 'PhpDocumentor'; + if (file_exists($testpath)) { + $found = $testpath; + break; + } + } + if (!$found) { + throw new BuildException("PhpDocumentor task depends on PhpDocumentor being installed and on include_path.", $this->getLocation()); + } + // otherwise, adjust the include_path to path to include the PhpDocumentor directory ... + set_include_path(get_include_path() . PATH_SEPARATOR . $found); + include_once ("phpDocumentor/Setup.inc.php"); + if (!class_exists('phpDocumentor_setup')) { + throw new BuildException("Error including PhpDocumentor setup class file."); + } + } + + /** + * Main entrypoint of the task + * Loads the necessary environment for running PhpDoc, then runs PhpDoc + * + * @throws BuildException - if the phpdoc classes can't be loaded. + */ + function main() + { + $this->findPhpDocumentorInstall(); + include_once 'phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php'; + + $this->validate(); + $configdir = $this->configDir ? $this->configDir->getAbsolutePath() : null; + $phpdoc = new PhingPhpDocumentorSetup($configdir, $this); + $this->setPhpDocumentorOptions($phpdoc); + //$phpdoc->readCommandLineSettings(); + $phpdoc->setupConverters($this->output); + $phpdoc->createDocs(); + } + + /** + * Validates that necessary minimum options have been set. + * @throws BuildException if validation doesn't pass + */ + protected function validate() + { + if (!$this->destdir) { + throw new BuildException("You must specify a destdir for phpdoc.", $this->getLocation()); + } + if (!$this->output) { + throw new BuildException("You must specify an output format for phpdoc (e.g. HTML:frames:default).", $this->getLocation()); + } + if (empty($this->filesets)) { + throw new BuildException("You have not specified any files to include (<fileset>) for phpdoc.", $this->getLocation()); + } + } + + /** + * Sets the options on the passed-in phpdoc setup object. + * @param PhingPhpDocumentorSetup $phpdoc + */ + protected function setPhpDocumentorOptions(PhingPhpDocumentorSetup $phpdoc) + { + + // Title MUST be set first ... (because it re-initializes the internal state of the PhpDocu renderer) + if ($this->title) { + $phpdoc->setTitle($this->title); + } + + if ($this->parsePrivate) { + $phpdoc->setParsePrivate(); + } + + if ($this->javadocDesc) { + $phpdoc->setJavadocDesc(); + } + + if ($this->quiet) { + $phpdoc->setQuietMode(); + } + + if ($this->destdir) { + $phpdoc->setTargetDir($this->destdir->getAbsolutePath()); + } + + if ($this->packages) { + $phpdoc->setPackageOutput($this->packages); + } + + if ($this->templateBase) { + $phpdoc->setTemplateBase($this->templateBase->getAbsolutePath()); + } + + if ($this->linksource) { + $phpdoc->setGenerateSourcecode($this->linksource); + } + + if ($this->examplesDir) { + $phpdoc->setExamplesDir($this->examplesDir->getAbsolutePath()); + } + + if ($this->ignoreTags) { + $phpdoc->setIgnoreTags($this->ignoreTags); + } + + if ($this->defaultPackageName) { + $phpdoc->setDefaultPackageName($this->defaultPackageName); + } + + if ($this->defaultCategoryName) { + $phpdoc->setDefaultCategoryName($this->defaultCategoryName); + } + + if ($this->pear) { + $phpdoc->setPear($this->pear); + } + + if ($this->ignore) { + $phpdoc->setIgnore($this->ignore); + } + + // append any files in filesets + $filesToParse = array(); + foreach($this->filesets as $fs) { + $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); + foreach($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $filesToParse[] = $f->getAbsolutePath(); + } + } + //print_r(implode(",", $filesToParse)); + $phpdoc->setFilesToParse(implode(",", $filesToParse)); + + + // append any files in filesets + $ricFiles = array(); + foreach($this->projDocFilesets as $fs) { + $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); + foreach($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $ricFiles[] = $f->getName(); + } + } + $phpdoc->setRicFiles($ricFiles); + + if ($this->undocumentedelements) { + $phpdoc->setUndocumentedelements($this->undocumentedelements); + } + + if ($this->customtags) { + $phpdoc->setCustomtags($this->customtags); + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php new file mode 100644 index 00000000..c327e331 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php @@ -0,0 +1,181 @@ +<?php +/** + * $Id: 69fc758899446b96312ac12f26b461969eb41b6e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; + +/** + * A wrapper for the implementations of PHPMDResultFormatter. + * + * @package phing.tasks.ext.phpmd + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 69fc758899446b96312ac12f26b461969eb41b6e $ + * @since 2.4.1 + */ +class PHPMDFormatterElement +{ + /** + * @var PHPMDResultFormatter + */ + protected $formatter = null; + + /** + * The type of the formatter. + * + * @var string + */ + protected $type = ""; + + /** + * Whether to use file (or write output to phing log). + * + * @var boolean + */ + protected $useFile = true; + + /** + * Output file for formatter. + * + * @var PhingFile + */ + protected $outfile = null; + + /** + * Sets the formatter type. + * + * @param string $type Type of the formatter + * + * @return void + */ + public function setType($type) + { + $this->type = $type; + + switch ($this->type) { + case 'xml': + include_once 'PHP/PMD/Renderer/XMLRenderer.php'; + break; + + case 'html': + include_once 'PHP/PMD/Renderer/HTMLRenderer.php'; + break; + + case 'text': + include_once 'PHP/PMD/Renderer/TextRenderer.php'; + break; + + default: + throw new BuildException("Formatter '" . $this->type . "' not implemented"); + } + } + + /** + * Get the formatter type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set whether to write formatter results to file or not. + * + * @param boolean $useFile True or false. + * + * @return void + */ + public function setUseFile($useFile) + { + $this->useFile = (boolean) $useFile; + } + + /** + * Return whether to write formatter results to file or not. + * + * @return boolean + */ + public function getUseFile() + { + return $this->useFile; + } + + /** + * Sets the output file for the formatter results. + * + * @param PhingFile $outfile The output file + * + * @return void + */ + public function setOutfile(PhingFile $outfile) + { + $this->outfile = $outfile; + } + + /** + * Get the output file. + * + * @return PhingFile + */ + public function getOutfile() + { + return $this->outfile; + } + + /** + * Creates a report renderer instance based on the formatter type. + * + * @return PHP_PMD_AbstractRenderer + * @throws BuildException When the specified renderer does not exist. + */ + public function getRenderer() + { + switch ($this->type) { + case 'xml': + $renderer = new PHP_PMD_Renderer_XMLRenderer(); + break; + + case 'html': + $renderer = new PHP_PMD_Renderer_HTMLRenderer(); + break; + + case 'text': + $renderer = new PHP_PMD_Renderer_TextRenderer(); + break; + + default: + throw new BuildException("PHP_MD renderer '" . $this->type . "' not implemented"); + } + + // Create a report stream + if ($this->getUseFile() === false || $this->getOutfile() === null) { + $stream = STDOUT; + } else { + $stream = fopen($this->getOutfile()->getAbsoluteFile(), 'wb'); + } + + require_once 'PHP/PMD/Writer/Stream.php'; + + $renderer->setWriter(new PHP_PMD_Writer_Stream($stream)); + + return $renderer; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDTask.php new file mode 100644 index 00000000..1c4d34bf --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpmd/PHPMDTask.php @@ -0,0 +1,284 @@ +<?php +/** + * $Id: 35668c2c6fbf1ca87fab21c26fd55ef630458fc7 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/phpmd/PHPMDFormatterElement.php'; + +/** + * Runs PHP Mess Detector. Checking PHP files for several potential problems + * based on rulesets. + * + * @package phing.tasks.ext.phpmd + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 35668c2c6fbf1ca87fab21c26fd55ef630458fc7 $ + * @since 2.4.1 + */ +class PHPMDTask extends Task +{ + /** + * A php source code filename or directory + * + * @var PhingFile + */ + protected $file = null; + + /** + * All fileset objects assigned to this task + * + * @var array<FileSet> + */ + protected $filesets = array(); + + /** + * The rule-set filenames or identifier. + * + * @var string + */ + protected $rulesets = 'codesize,unusedcode'; + + /** + * The minimum priority for rules to load. + * + * @var integer + */ + protected $minimumPriority = 0; + + /** + * List of valid file extensions for analyzed files. + * + * @var array + */ + protected $allowedFileExtensions = array('php'); + + /** + * List of exclude directory patterns. + * + * @var array + */ + protected $ignorePatterns = array('.git', '.svn', 'CVS', '.bzr', '.hg'); + + /** + * The format for the report + * + * @var string + */ + protected $format = 'text'; + + /** + * Formatter elements. + * + * @var array<PHPMDFormatterElement> + */ + protected $formatters = array(); + + /** + * Set the input source file or directory. + * + * @param PhingFile $file The input source file or directory. + * + * @return void + */ + public function setFile(PhingFile $file) + { + $this->file = $file; + } + + /** + * Nested creator, adds a set of files (nested fileset attribute). + * + * @return FileSet The created fileset object + */ + public function createFileSet() + { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Sets the minimum rule priority. + * + * @param integer $minimumPriority Minimum rule priority. + * + * @return void + */ + public function setMinimumPriority($minimumPriority) + { + $this->minimumPriority = $minimumPriority; + } + + /** + * Sets the rule-sets. + * + * @param string $ruleSetFileNames Comma-separated string of rule-set filenames + * or identifier. + * + * @return void + */ + public function setRulesets($ruleSetFileNames) + { + $this->rulesets = $ruleSetFileNames; + } + + /** + * Sets a list of filename extensions for valid php source code files. + * + * @param string $fileExtensions List of valid file extensions without leading dot. + * + * @return void + */ + public function setAllowedFileExtensions($fileExtensions) + { + $this->allowedFileExtensions = array(); + + $token = ' ,;'; + $ext = strtok($fileExtensions, $token); + + while ($ext !== false) { + $this->allowedFileExtensions[] = $ext; + $ext = strtok($token); + } + } + + /** + * Sets a list of ignore patterns that is used to exclude directories from + * the source analysis. + * + * @param string $ignorePatterns List of ignore patterns. + * + * @return void + */ + public function setIgnorePatterns($ignorePatterns) + { + $this->ignorePatterns = array(); + + $token = ' ,;'; + $pattern = strtok($ignorePatterns, $token); + + while ($pattern !== false) { + $this->ignorePatterns[] = $pattern; + $pattern = strtok($token); + } + } + + /** + * Create object for nested formatter element. + * + * @return PHPMDFormatterElement + */ + public function createFormatter() + { + $num = array_push($this->formatters, new PHPMDFormatterElement()); + return $this->formatters[$num-1]; + } + + /** + * Executes PHPMD against PhingFile or a FileSet + * + * @throws BuildException - if the phpmd classes can't be loaded. + * @return void + */ + public function main() + { + /** + * Find PHPMD + */ + @include_once 'PHP/PMD.php'; + + if (! class_exists('PHP_PMD')) { + throw new BuildException( + 'PHPMDTask depends on PHPMD being installed and on include_path.', + $this->getLocation() + ); + } + + require_once 'PHP/PMD/AbstractRule.php'; + + if (!$this->minimumPriority) { + $this->minimumPriority = PHP_PMD_AbstractRule::LOWEST_PRIORITY; + } + + if (!isset($this->file) and count($this->filesets) == 0) { + throw new BuildException("Missing either a nested fileset or attribute 'file' set"); + } + + if (count($this->formatters) == 0) { + // turn legacy format attribute into formatter + $fmt = new PHPMDFormatterElement(); + $fmt->setType($this->format); + $fmt->setUseFile(false); + $this->formatters[] = $fmt; + } + + $reportRenderers = array(); + + foreach ($this->formatters as $fe) { + if ($fe->getType() == '') { + throw new BuildException("Formatter missing required 'type' attribute."); + } + if ($fe->getUsefile() && $fe->getOutfile() === null) { + throw new BuildException("Formatter requires 'outfile' attribute when 'useFile' is true."); + } + + $reportRenderers[] = $fe->getRenderer(); + } + + // Create a rule set factory + $ruleSetFactory = new PHP_PMD_RuleSetFactory(); + $ruleSetFactory->setMinimumPriority($this->minimumPriority); + + $phpmd = new PHP_PMD(); + + $phpmd->setFileExtensions($this->allowedFileExtensions); + $phpmd->setIgnorePattern($this->ignorePatterns); + + $filesToParse = array(); + + if ($this->file instanceof PhingFile) { + $filesToParse[] = $this->file->getPath(); + } else { + // append any files in filesets + foreach ($this->filesets as $fs) { + $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); + foreach ($files as $filename) { + $f = new PhingFile($fs->getDir($this->project), $filename); + $filesToParse[] = $f->getAbsolutePath(); + } + } + } + + if (count($filesToParse) > 0) { + $inputPath = implode(',', $filesToParse); + + $this->log('Processing files...'); + + $phpmd->processFiles( + $inputPath, + $this->rulesets, + $reportRenderers, + $ruleSetFactory + ); + + $this->log('Finished processing files'); + } else { + $this->log('No files to process'); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/BatchTest.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/BatchTest.php new file mode 100755 index 00000000..6a6cec24 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/BatchTest.php @@ -0,0 +1,230 @@ +<?php +/** + * $Id: 4067d915614ff7a864c31f19549bcf6a96c0f92d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phpunit/PHPUnitUtil.php'; +require_once 'phing/types/FileSet.php'; + +/** + * Scans a list of files given by the fileset attribute, extracts valid test cases + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 4067d915614ff7a864c31f19549bcf6a96c0f92d $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class BatchTest +{ + /** the list of filesets containing the testcase filename rules */ + private $filesets = array(); + + /** the reference to the project */ + private $project = NULL; + + /** the classpath to use with Phing::__import() calls */ + private $classpath = NULL; + + /** names of classes to exclude */ + private $excludeClasses = array(); + + /** name of the batchtest/suite */ + protected $name = "Phing Batchtest"; + + /** + * Create a new batchtest instance + * + * @param Project the project it depends on. + */ + public function __construct(Project $project) + { + $this->project = $project; + } + + /** + * Sets the name of the batchtest/suite + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Sets the classes to exclude + */ + public function setExclude($exclude) + { + $this->excludeClasses = explode(" ", $exclude); + } + + /** + * Sets the classpath + */ + public function setClasspath(Path $classpath) + { + if ($this->classpath === null) + { + $this->classpath = $classpath; + } + else + { + $this->classpath->append($classpath); + } + } + + /** + * Creates a new Path object + */ + public function createClasspath() + { + $this->classpath = new Path(); + return $this->classpath; + } + + /** + * Returns the classpath + */ + public function getClasspath() + { + return $this->classpath; + } + + /** + * Add a new fileset containing the XML results to aggregate + * + * @param FileSet the new fileset containing XML results. + */ + public function addFileSet(FileSet $fileset) + { + $this->filesets[] = $fileset; + } + + /** + * Iterate over all filesets and return the filename of all files. + * + * @return array an array of filenames + */ + private function getFilenames() + { + $filenames = array(); + + foreach ($this->filesets as $fileset) + { + $ds = $fileset->getDirectoryScanner($this->project); + $ds->scan(); + + $files = $ds->getIncludedFiles(); + + foreach ($files as $file) + { + $filenames[] = $ds->getBaseDir() . "/" . $file; + } + } + + return $filenames; + } + + /** + * Checks wheter $input is a PHPUnit Test + */ + private function isTestCase($input) + { + return is_subclass_of($input, 'PHPUnit_Framework_TestCase') || is_subclass_of($input, 'PHPUnit_Framework_TestSuite'); + } + + /** + * Filters an array of classes, removes all classes that are not test cases or test suites, + * or classes that are declared abstract + */ + private function filterTests($input) + { + $reflect = new ReflectionClass($input); + + return $this->isTestCase($input) && (!$reflect->isAbstract()); + } + + /** + * Returns an array of test cases and test suites that are declared + * by the files included by the filesets + * + * @return array an array of tests. + */ + protected function elements() + { + $filenames = $this->getFilenames(); + + $declaredClasses = array(); + + foreach ($filenames as $filename) + { + $definedClasses = PHPUnitUtil::getDefinedClasses($filename, $this->classpath); + + foreach($definedClasses as $definedClass) { + $this->project->log("(PHPUnit) Adding $definedClass (from $filename) to tests.", Project::MSG_DEBUG); + } + + $declaredClasses = array_merge($declaredClasses, $definedClasses); + } + + $elements = array_filter($declaredClasses, array($this, "filterTests")); + + return $elements; + } + + /** + * Returns a testsuite containing all the tests in this batch + * + * @deprecated + * @return PHPUnit_Framework_TestSuite + */ + public function getTestSuite() + { + $suite = new PHPUnit_Framework_TestSuite($this->name); + + foreach ($this->elements() as $test) + { + $testClass = new $test(); + if (!($testClass instanceof PHPUnit_Framework_TestSuite)) + { + $testClass = new ReflectionClass($test); + } + + $suite->addTestSuite($testClass); + } + + return $suite; + } + + /** + * Add the tests in this batchtest to a test suite + * @param PHPUnit_Framework_TestSuite $suite + */ + public function addToTestSuite(PHPUnit_Framework_TestSuite $suite) + { + foreach ($this->elements() as $element) { + $testClass = new $element(); + if (!($testClass instanceof PHPUnit_Framework_TestSuite)) + { + $testClass = new ReflectionClass($element); + } + $suite->addTestSuite($testClass); + } + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/FormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/FormatterElement.php new file mode 100755 index 00000000..c220b79d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/FormatterElement.php @@ -0,0 +1,178 @@ +<?php +/** + * $Id: 296214ebac3a12e51bffed3dcc2c0bb93fb0754e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; + +/** + * A wrapper for the implementations of PHPUnit2ResultFormatter. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 296214ebac3a12e51bffed3dcc2c0bb93fb0754e $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class FormatterElement +{ + protected $formatter = NULL; + + protected $type = ""; + + protected $useFile = true; + + protected $toDir = "."; + + protected $outfile = ""; + + protected $parent = NULL; + + /** + * Sets parent task + * @param Task $parent Calling Task + */ + public function setParent($parent) + { + $this->parent = $parent; + } + + /** + * Loads a specific formatter type + * @param string $type + */ + public function setType($type) + { + $this->type = $type; + + if ($this->type == "summary") + { + require_once 'phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php'; + $this->formatter = new SummaryPHPUnitResultFormatter($this->parent); + } + else + if ($this->type == "clover") + { + require_once 'phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php'; + $this->formatter = new CloverPHPUnitResultFormatter($this->parent); + } + else + if ($this->type == "xml") + { + require_once 'phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php'; + $this->formatter = new XMLPHPUnitResultFormatter($this->parent); + } + else + if ($this->type == "plain") + { + require_once 'phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php'; + $this->formatter = new PlainPHPUnitResultFormatter($this->parent); + } + else + { + throw new BuildException("Formatter '" . $this->type . "' not implemented"); + } + } + + /** + * Loads a specific formatter class + */ + public function setClassName($className) + { + $classNameNoDot = Phing::import($className); + + $this->formatter = new $classNameNoDot(); + } + + /** + * Sets whether to store formatting results in a file + */ + public function setUseFile($useFile) + { + $this->useFile = $useFile; + } + + /** + * Returns whether to store formatting results in a file + */ + public function getUseFile() + { + return $this->useFile; + } + + /** + * Sets output directory + * @param string $toDir + */ + public function setToDir($toDir) + { + $this->toDir = $toDir; + } + + /** + * Returns output directory + * @return string + */ + public function getToDir() + { + return $this->toDir; + } + + /** + * Sets output filename + * @param string $outfile + */ + public function setOutfile($outfile) + { + $this->outfile = $outfile; + } + + /** + * Returns output filename + * @return string + */ + public function getOutfile() + { + if ($this->outfile) + { + return $this->outfile; + } + else + { + return $this->formatter->getPreferredOutfile() . $this->getExtension(); + } + } + + /** + * Returns extension + * @return string + */ + public function getExtension() + { + return $this->formatter->getExtension(); + } + + /** + * Returns formatter object + * @return PHPUnitResultFormatter + */ + public function getFormatter() + { + return $this->formatter; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php new file mode 100755 index 00000000..87338da7 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php @@ -0,0 +1,248 @@ +<?php +/** + * $Id: b88d6fa4ca4717177b562a0475c81d92c161d9b4 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/FileWriter.php'; +require_once 'phing/util/ExtendedFileStream.php'; + +/** + * Transform a PHPUnit xml report using XSLT. + * This transformation generates an html report in either framed or non-framed + * style. The non-framed style is convenient to have a concise report via mail, + * the framed report is much more convenient if you want to browse into + * different packages or testcases since it is a Javadoc like report. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: b88d6fa4ca4717177b562a0475c81d92c161d9b4 $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class PHPUnitReportTask extends Task +{ + private $format = "noframes"; + private $styleDir = ""; + private $toDir = ""; + + /** + * Whether to use the sorttable JavaScript library, defaults to false + * See {@link http://www.kryogenix.org/code/browser/sorttable/)} + * + * @var boolean + */ + private $useSortTable = false; + + /** the directory where the results XML can be found */ + private $inFile = "testsuites.xml"; + + /** + * Set the filename of the XML results file to use. + */ + public function setInFile(PhingFile $inFile) + { + $this->inFile = $inFile; + } + + /** + * Set the format of the generated report. Must be noframes or frames. + */ + public function setFormat($format) + { + $this->format = $format; + } + + /** + * Set the directory where the stylesheets are located. + */ + public function setStyleDir($styleDir) + { + $this->styleDir = $styleDir; + } + + /** + * Set the directory where the files resulting from the + * transformation should be written to. + */ + public function setToDir(PhingFile $toDir) + { + $this->toDir = $toDir; + } + + /** + * Sets whether to use the sorttable JavaScript library, defaults to false + * See {@link http://www.kryogenix.org/code/browser/sorttable/)} + * + * @param boolean $useSortTable + */ + public function setUseSortTable($useSortTable) + { + $this->useSortTable = (boolean) $useSortTable; + } + + /** + * Returns the path to the XSL stylesheet + */ + protected function getStyleSheet() + { + $xslname = "phpunit-" . $this->format . ".xsl"; + + if ($this->styleDir) + { + $file = new PhingFile($this->styleDir, $xslname); + } + else + { + $path = Phing::getResourcePath("phing/etc/$xslname"); + + if ($path === NULL) + { + $path = Phing::getResourcePath("etc/$xslname"); + + if ($path === NULL) + { + throw new BuildException("Could not find $xslname in resource path"); + } + } + + $file = new PhingFile($path); + } + + if (!$file->exists()) + { + throw new BuildException("Could not find file " . $file->getPath()); + } + + return $file; + } + + /** + * Transforms the DOM document + */ + protected function transform(DOMDocument $document) + { + if (!$this->toDir->exists()) + { + throw new BuildException("Directory '" . $this->toDir . "' does not exist"); + } + + $xslfile = $this->getStyleSheet(); + + $xsl = new DOMDocument(); + $xsl->load($xslfile->getAbsolutePath()); + + $proc = new XSLTProcessor(); + if (defined('XSL_SECPREF_WRITE_FILE')) + { + if (version_compare(PHP_VERSION,'5.4',"<")) + { + ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); + } + else + { + $proc->setSecurityPrefs(XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); + } + } + + $proc->importStyleSheet($xsl); + $proc->setParameter('', 'output.sorttable', $this->useSortTable); + + if ($this->format == "noframes") + { + $writer = new FileWriter(new PhingFile($this->toDir, "phpunit-noframes.html")); + $writer->write($proc->transformToXML($document)); + $writer->close(); + } + else + { + ExtendedFileStream::registerStream(); + + $toDir = (string) $this->toDir; + + // urlencode() the path if we're on Windows + if (FileSystem::getFileSystem()->getSeparator() == '\\') { + $toDir = urlencode($toDir); + } + + // no output for the framed report + // it's all done by extension... + $proc->setParameter('', 'output.dir', $toDir); + $proc->transformToXML($document); + + ExtendedFileStream::unregisterStream(); + } + } + + /** + * Fixes DOM document tree: + * - adds package="default" to 'testsuite' elements without + * package attribute + * - removes outer 'testsuite' container(s) + */ + protected function fixDocument(DOMDocument $document) + { + $rootElement = $document->firstChild; + + $xp = new DOMXPath($document); + + $nodes = $xp->query("/testsuites/testsuite"); + + foreach ($nodes as $node) { + $children = $xp->query("./testsuite", $node); + + if ($children->length) { + foreach ($children as $child) { + if (!$child->hasAttribute('package')) + { + $child->setAttribute('package', 'default'); + } + $rootElement->appendChild($child); + } + + $rootElement->removeChild($node); + } + } + } + + /** + * Initialize the task + */ + public function init() + { + if (!class_exists('XSLTProcessor')) { + throw new BuildException("PHPUnitReportTask requires the XSL extension"); + } + } + + /** + * The main entry point + * + * @throws BuildException + */ + public function main() + { + $testSuitesDoc = new DOMDocument(); + $testSuitesDoc->load((string) $this->inFile); + + $this->fixDocument($testSuitesDoc); + + $this->transform($testSuitesDoc); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php new file mode 100755 index 00000000..5b842b95 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php @@ -0,0 +1,378 @@ +<?php +/** + * $Id: 4554fdd642b6ef7774cbb89c537ccba90f3ca972 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/Writer.php'; +require_once 'phing/util/LogWriter.php'; + +/** + * Runs PHPUnit tests. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 4554fdd642b6ef7774cbb89c537ccba90f3ca972 $ + * @package phing.tasks.ext.phpunit + * @see BatchTest + * @since 2.1.0 + */ +class PHPUnitTask extends Task +{ + private $batchtests = array(); + private $formatters = array(); + private $bootstrap = ""; + private $haltonerror = false; + private $haltonfailure = false; + private $haltonincomplete = false; + private $haltonskipped = false; + private $errorproperty; + private $failureproperty; + private $incompleteproperty; + private $skippedproperty; + private $printsummary = false; + private $testfailed = false; + private $testfailuremessage = ""; + private $codecoverage = null; + private $groups = array(); + private $excludeGroups = array(); + private $processIsolation = false; + private $usecustomerrorhandler = true; + + /** + * Initialize Task. + * This method includes any necessary PHPUnit libraries and triggers + * appropriate error if they cannot be found. This is not done in header + * because we may want this class to be loaded w/o triggering an error. + */ + public function init() { + /** + * Determine PHPUnit version number + */ + @include_once 'PHPUnit/Runner/Version.php'; + + if (!class_exists('PHPUnit_Runner_Version')) { + throw new BuildException("PHPUnitTask requires PHPUnit to be installed", $this->getLocation()); + } + + $version = PHPUnit_Runner_Version::id(); + + if (version_compare($version, '3.6.0') < 0) + { + throw new BuildException("PHPUnitTask requires PHPUnit version >= 3.6.0", $this->getLocation()); + } + + /** + * Other dependencies that should only be loaded when class is actually used. + */ + require_once 'phing/tasks/ext/phpunit/PHPUnitTestRunner.php'; + require_once 'phing/tasks/ext/phpunit/BatchTest.php'; + require_once 'phing/tasks/ext/phpunit/FormatterElement.php'; + + /** + * point PHPUnit_MAIN_METHOD define to non-existing method + */ + if (!defined('PHPUnit_MAIN_METHOD')) + { + define('PHPUnit_MAIN_METHOD', 'PHPUnitTask::undefined'); + } + } + + /** + * Sets the name of a bootstrap file that is run before + * executing the tests + * + * @param string $bootstrap the name of the bootstrap file + */ + public function setBootstrap($bootstrap) + { + $this->bootstrap = $bootstrap; + } + + public function setErrorproperty($value) + { + $this->errorproperty = $value; + } + + public function setFailureproperty($value) + { + $this->failureproperty = $value; + } + + public function setIncompleteproperty($value) + { + $this->incompleteproperty = $value; + } + + public function setSkippedproperty($value) + { + $this->skippedproperty = $value; + } + + public function setHaltonerror($value) + { + $this->haltonerror = $value; + } + + public function setHaltonfailure($value) + { + $this->haltonfailure = $value; + } + + public function getHaltonfailure() + { + return $this->haltonfailure; + } + + public function setHaltonincomplete($value) + { + $this->haltonincomplete = $value; + } + + public function getHaltonincomplete() + { + return $this->haltonincomplete; + } + + public function setHaltonskipped($value) + { + $this->haltonskipped = $value; + } + + public function getHaltonskipped() + { + return $this->haltonskipped; + } + + public function setPrintsummary($printsummary) + { + $this->printsummary = $printsummary; + } + + public function setCodecoverage($codecoverage) + { + $this->codecoverage = $codecoverage; + } + + public function setProcessIsolation($processIsolation) + { + $this->processIsolation = $processIsolation; + } + + public function setUseCustomErrorHandler($usecustomerrorhandler) + { + $this->usecustomerrorhandler = $usecustomerrorhandler; + } + + public function setGroups($groups) + { + $token = ' ,;'; + $this->groups = array(); + $tok = strtok($groups, $token); + while ($tok !== false) { + $this->groups[] = $tok; + $tok = strtok($token); + } + } + + public function setExcludeGroups($excludeGroups) + { + $token = ' ,;'; + $this->excludeGroups = array(); + $tok = strtok($excludeGroups, $token); + while ($tok !== false) { + $this->excludeGroups[] = $tok; + $tok = strtok($token); + } + } + + /** + * Add a new formatter to all tests of this task. + * + * @param FormatterElement formatter element + */ + public function addFormatter(FormatterElement $fe) + { + $fe->setParent($this); + $this->formatters[] = $fe; + } + + /** + * The main entry point + * + * @throws BuildException + */ + public function main() + { + if ($this->codecoverage && !extension_loaded('xdebug')) + { + throw new Exception("PHPUnitTask depends on Xdebug being installed to gather code coverage information."); + } + + if ($this->printsummary) + { + $fe = new FormatterElement(); + $fe->setParent($this); + $fe->setType("summary"); + $fe->setUseFile(false); + $this->formatters[] = $fe; + } + + $autoloadSave = spl_autoload_functions(); + + if ($this->bootstrap) + { + require_once $this->bootstrap; + } + + $suite = new PHPUnit_Framework_TestSuite('AllTests'); + + foreach ($this->batchtests as $batchtest) + { + $batchtest->addToTestSuite($suite); + } + + $this->execute($suite); + + if ($this->testfailed) + { + throw new BuildException($this->testfailuremessage); + } + + $autoloadNew = spl_autoload_functions(); + foreach ($autoloadNew as $autoload) { + spl_autoload_unregister($autoload); + } + + foreach ($autoloadSave as $autoload) { + spl_autoload_register($autoload); + } + } + + /** + * @throws BuildException + */ + protected function execute($suite) + { + $runner = new PHPUnitTestRunner($this->project, $this->groups, $this->excludeGroups, $this->processIsolation); + + if ($this->codecoverage) { + /** + * Add some defaults to the PHPUnit filter + */ + $pwd = dirname(__FILE__); + $path = realpath($pwd . '/../../../'); + + $filter = new PHP_CodeCoverage_Filter(); + $filter->addDirectoryToBlacklist($path); + $runner->setCodecoverage(new PHP_CodeCoverage(null, $filter)); + } + + $runner->setUseCustomErrorHandler($this->usecustomerrorhandler); + + foreach ($this->formatters as $fe) + { + $formatter = $fe->getFormatter(); + + if ($fe->getUseFile()) + { + $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); + + $writer = new FileWriter($destFile->getAbsolutePath()); + + $formatter->setOutput($writer); + } + else + { + $formatter->setOutput($this->getDefaultOutput()); + } + + $runner->addFormatter($formatter); + + $formatter->startTestRun(); + } + + $runner->run($suite); + + foreach ($this->formatters as $fe) + { + $formatter = $fe->getFormatter(); + $formatter->endTestRun(); + } + + $retcode = $runner->getRetCode(); + + if ($retcode == PHPUnitTestRunner::ERRORS) { + if ($this->errorproperty) { + $this->project->setNewProperty($this->errorproperty, true); + } + if ($this->haltonerror) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastErrorMessage(); + } + } elseif ($retcode == PHPUnitTestRunner::FAILURES) { + if ($this->failureproperty) { + $this->project->setNewProperty($this->failureproperty, true); + } + + if ($this->haltonfailure) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastFailureMessage(); + } + } elseif ($retcode == PHPUnitTestRunner::INCOMPLETES) { + if ($this->incompleteproperty) { + $this->project->setNewProperty($this->incompleteproperty, true); + } + + if ($this->haltonincomplete) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastIncompleteMessage(); + } + } elseif ($retcode == PHPUnitTestRunner::SKIPPED) { + if ($this->skippedproperty) { + $this->project->setNewProperty($this->skippedproperty, true); + } + + if ($this->haltonskipped) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastSkippedMessage(); + } + } + } + + protected function getDefaultOutput() + { + return new LogWriter($this); + } + + /** + * Adds a set of tests based on pattern matching. + * + * @return BatchTest a new instance of a batch test. + */ + public function createBatchTest() + { + $batchtest = new BatchTest($this->getProject()); + + $this->batchtests[] = $batchtest; + + return $batchtest; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.php new file mode 100755 index 00000000..6c7e5e68 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.php @@ -0,0 +1,312 @@ +<?php +/** + * $Id: 5926dfc1177ec0c52ec275a8e542979c8deb6e6f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PHPUnit/Autoload.php'; +require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; +require_once 'phing/system/util/Timer.php'; + +/** + * Simple Testrunner for PHPUnit that runs all tests of a testsuite. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 5926dfc1177ec0c52ec275a8e542979c8deb6e6f $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class PHPUnitTestRunner extends PHPUnit_Runner_BaseTestRunner implements PHPUnit_Framework_TestListener +{ + const SUCCESS = 0; + const FAILURES = 1; + const ERRORS = 2; + const INCOMPLETES = 3; + const SKIPPED = 4; + + private $retCode = 0; + private $lastErrorMessage = ''; + private $lastFailureMessage = ''; + private $lastIncompleteMessage = ''; + private $lastSkippedMessage = ''; + private $formatters = array(); + + private $codecoverage = null; + + private $project = NULL; + + private $groups = array(); + private $excludeGroups = array(); + + private $processIsolation = false; + + private $useCustomErrorHandler = true; + + public function __construct(Project $project, $groups = array(), $excludeGroups = array(), $processIsolation = false) + { + $this->project = $project; + $this->groups = $groups; + $this->excludeGroups = $excludeGroups; + $this->processIsolation = $processIsolation; + $this->retCode = self::SUCCESS; + } + + public function setCodecoverage($codecoverage) + { + $this->codecoverage = $codecoverage; + } + + public function setUseCustomErrorHandler($useCustomErrorHandler) + { + $this->useCustomErrorHandler = $useCustomErrorHandler; + } + + public function addFormatter($formatter) + { + $this->formatters[] = $formatter; + } + + public function handleError($level, $message, $file, $line) + { + return PHPUnit_Util_ErrorHandler::handleError($level, $message, $file, $line); + } + + /** + * Run a test + */ + public function run(PHPUnit_Framework_TestSuite $suite) + { + $res = new PHPUnit_Framework_TestResult(); + + if ($this->codecoverage) + { + $whitelist = CoverageMerger::getWhiteList($this->project); + + $this->codecoverage->filter()->addFilesToWhiteList($whitelist); + + $res->setCodeCoverage($this->codecoverage); + } + + $res->addListener($this); + + foreach ($this->formatters as $formatter) + { + $res->addListener($formatter); + } + + /* Set PHPUnit error handler */ + if ($this->useCustomErrorHandler) + { + $oldErrorHandler = set_error_handler(array($this, 'handleError'), E_ALL | E_STRICT); + } + + $suite->run($res, false, $this->groups, $this->excludeGroups, $this->processIsolation); + + foreach ($this->formatters as $formatter) + { + $formatter->processResult($res); + } + + /* Restore Phing error handler */ + if ($this->useCustomErrorHandler) + { + restore_error_handler(); + } + + if ($this->codecoverage) + { + CoverageMerger::merge($this->project, $this->codecoverage->getData()); + } + + if ($res->errorCount() != 0) + { + $this->retCode = self::ERRORS; + } + else if ($res->failureCount() != 0) + { + $this->retCode = self::FAILURES; + } + else if ($res->notImplementedCount() != 0) + { + $this->retCode = self::INCOMPLETES; + } + else if ($res->skippedCount() != 0) + { + $this->retCode = self::SKIPPED; + } + } + + public function getRetCode() + { + return $this->retCode; + } + + public function getLastErrorMessage() + { + return $this->lastErrorMessage; + } + + public function getLastFailureMessage() + { + return $this->lastFailureMessage; + } + + public function getLastIncompleteMessage() + { + return $this->lastIncompleteMessage; + } + + public function getLastSkippedMessage() + { + return $this->lastSkippedMessage; + } + + protected function composeMessage($message, PHPUnit_Framework_Test $test, Exception $e) + { + return "Test $message (" . $test->getName() . " in class " . get_class($test) . "): " . $e->getMessage(); + } + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->lastErrorMessage = $this->composeMessage("ERROR", $test, $e); + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + $this->lastFailureMessage = $this->composeMessage("FAILURE", $test, $e); + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->lastIncompleteMessage = $this->composeMessage("INCOMPLETE", $test, $e); + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->lastSkippedMessage = $this->composeMessage("SKIPPED", $test, $e); + } + + /** + * A test started. + * + * @param string $testName + */ + public function testStarted($testName) + { + } + + /** + * A test ended. + * + * @param string $testName + */ + public function testEnded($testName) + { + } + + /** + * A test failed. + * + * @param integer $status + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + */ + public function testFailed($status, PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e) + { + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + * + * @param string $message + */ + protected function runFailed($message) + { + throw new BuildException($message); + } + + /** + * A test suite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test suite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php new file mode 100755 index 00000000..25a85f4c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php @@ -0,0 +1,141 @@ +<?php +/** + * $Id: c569f96e625ed8f9c6ae5add2b2f4a0a6c3e5a54 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Various utility functions + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: c569f96e625ed8f9c6ae5add2b2f4a0a6c3e5a54 $ + * @package phing.tasks.ext.phpunit + * @since 2.1.0 + */ +class PHPUnitUtil +{ + protected static $definedClasses = array(); + + /** + * Returns the package of a class as defined in the docblock of the class using @package + * + * @param string the name of the class + * @return string the name of the package + */ + static function getPackageName($classname) + { + $reflect = new ReflectionClass($classname); + + if (preg_match('/@package[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches)) + { + return $matches[1]; + } + else + { + return "default"; + } + } + + /** + * Returns the subpackage of a class as defined in the docblock of the class + * using @subpackage + * + * @param string $classname the name of the class + * + * @author Benjamin Schultz <bschultz@proqrent.de> + * @return string|null the name of the subpackage + */ + public static function getSubpackageName($classname) + { + $reflect = new ReflectionClass($classname); + + if (preg_match('/@subpackage[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches)) { + return $matches[1]; + } else { + return null; + } + } + + /** + * Derives the classname from a filename. + * Assumes that there is only one class defined in that particular file, and that + * the naming follows the dot-path (Java) notation scheme. + * + * @param string the filename + * @return string the name fo the class + */ + public static function getClassFromFileName($filename) + { + $filename = basename($filename); + + $rpos = strrpos($filename, '.'); + + if ($rpos != -1) + { + $filename = substr($filename, 0, $rpos); + } + + return $filename; + } + + /** + * @param string the filename + * @param Path optional classpath + * @return array list of classes defined in the file + */ + public static function getDefinedClasses($filename, $classpath = NULL) + { + $filename = realpath($filename); + + if (!file_exists($filename)) + { + throw new Exception("File '" . $filename . "' does not exist"); + } + + if (isset(self::$definedClasses[$filename])) + { + return self::$definedClasses[$filename]; + } + + Phing::__import($filename, $classpath); + + $declaredClasses = get_declared_classes(); + + foreach ($declaredClasses as $classname) + { + $reflect = new ReflectionClass($classname); + + self::$definedClasses[$reflect->getFilename()][] = $classname; + + if (is_array(self::$definedClasses[$reflect->getFilename()])) + { + self::$definedClasses[$reflect->getFilename()] = array_unique(self::$definedClasses[$reflect->getFilename()]); + } + } + + if (isset(self::$definedClasses[$filename])) + { + return self::$definedClasses[$filename]; + } + else + { + return array(); + } + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php new file mode 100755 index 00000000..4d03078d --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php @@ -0,0 +1,87 @@ +<?php +/** + * $Id: 97f504caad678a6c7d231fe298c27d1281008e48 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints Clover XML output of the test + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 97f504caad678a6c7d231fe298c27d1281008e48 $ + * @package phing.tasks.ext.formatter + * @since 2.4.0 + */ +class CloverPHPUnitResultFormatter extends PHPUnitResultFormatter +{ + /** + * @var PHPUnit_Framework_TestResult + */ + private $result = NULL; + + /** + * PHPUnit version + * @var string + */ + private $version = NULL; + + public function __construct(PHPUnitTask $parentTask) + { + parent::__construct($parentTask); + + $this->version = PHPUnit_Runner_Version::id(); + } + + public function getExtension() + { + return ".xml"; + } + + public function getPreferredOutfile() + { + return "clover-coverage"; + } + + public function processResult(PHPUnit_Framework_TestResult $result) + { + $this->result = $result; + } + + public function endTestRun() + { + require_once 'PHP/CodeCoverage/Report/Clover.php'; + + $coverage = $this->result->getCodeCoverage(); + + if (!empty($coverage)) { + $clover = new PHP_CodeCoverage_Report_Clover(); + + $contents = $clover->process($coverage); + + if ($this->out) + { + $this->out->write($contents); + $this->out->close(); + } + } + + parent::endTestRun(); + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php new file mode 100755 index 00000000..1b09dbc1 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php @@ -0,0 +1,203 @@ +<?php +/** + * $Id: cbf356a8395e116cd6ecddb7f5a822d4b6edf01c $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PHPUnit/Framework/TestListener.php'; + +require_once 'phing/system/io/Writer.php'; + +/** + * This abstract class describes classes that format the results of a PHPUnit testrun. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: cbf356a8395e116cd6ecddb7f5a822d4b6edf01c $ + * @package phing.tasks.ext.phpunit.formatter + * @since 2.1.0 + */ +abstract class PHPUnitResultFormatter implements PHPUnit_Framework_TestListener +{ + protected $out = NULL; + + protected $project = NULL; + + private $timers = false; + + private $runCounts = false; + + private $failureCounts = false; + + private $errorCounts = false; + + private $incompleteCounts = false; + + private $skipCounts = false; + + /** + * Constructor + * @param PHPUnitTask $parentTask Calling Task + */ + public function __construct(PHPUnitTask $parentTask) + { + $this->project = $parentTask->getProject(); + } + + /** + * Sets the writer the formatter is supposed to write its results to. + */ + public function setOutput(Writer $out) + { + $this->out = $out; + } + + /** + * Returns the extension used for this formatter + * + * @return string the extension + */ + public function getExtension() + { + return ""; + } + + public function getPreferredOutfile() + { + return ""; + } + + public function processResult(PHPUnit_Framework_TestResult $result) + { + } + + public function startTestRun() + { + $this->timers = array($this->getMicrotime()); + $this->runCounts = array(0); + $this->failureCounts = array(0); + $this->errorCounts = array(0); + $this->incompleteCounts = array(0); + $this->skipCounts = array(0); + } + + public function endTestRun() + { + } + + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $this->timers[] = $this->getMicrotime(); + $this->runCounts[] = 0; + $this->failureCounts[] = 0; + $this->errorCounts[] = 0; + $this->incompleteCounts[] = 0; + $this->skipCounts[] = 0; + } + + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $lastRunCount = array_pop($this->runCounts); + $this->runCounts[count($this->runCounts) - 1] += $lastRunCount; + + $lastFailureCount = array_pop($this->failureCounts); + $this->failureCounts[count($this->failureCounts) - 1] += $lastFailureCount; + + $lastErrorCount = array_pop($this->errorCounts); + $this->errorCounts[count($this->errorCounts) - 1] += $lastErrorCount; + + $lastIncompleteCount = array_pop($this->incompleteCounts); + $this->incompleteCounts[count($this->incompleteCounts) - 1] += $lastIncompleteCount; + + $lastSkipCount = array_pop($this->skipCounts); + $this->skipCounts[count($this->skipCounts) - 1] += $lastSkipCount; + + array_pop($this->timers); + } + + public function startTest(PHPUnit_Framework_Test $test) + { + $this->runCounts[count($this->runCounts) - 1]++; + } + + public function endTest(PHPUnit_Framework_Test $test, $time) + { + } + + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->errorCounts[count($this->errorCounts) - 1]++; + } + + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + $this->failureCounts[count($this->failureCounts) - 1]++; + } + + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->incompleteCounts[count($this->incompleteCounts) - 1]++; + } + + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->skipCounts[count($this->skipCounts) - 1]++; + } + + public function getRunCount() + { + return end($this->runCounts); + } + + public function getFailureCount() + { + return end($this->failureCounts); + } + + public function getErrorCount() + { + return end($this->errorCounts); + } + + public function getIncompleteCount() + { + return end($this->incompleteCounts); + } + + public function getSkippedCount() + { + return end($this->skipCounts); + } + + public function getElapsedTime() + { + if (end($this->timers)) + { + return $this->getMicrotime() - end($this->timers); + } + else + { + return 0; + } + } + + private function getMicrotime() { + list($usec, $sec) = explode(' ', microtime()); + return (float)$usec + (float)$sec; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php new file mode 100755 index 00000000..e67cfd2b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.php @@ -0,0 +1,128 @@ +<?php +/** + * $Id: 529f9b6ab9ced7b78871e3612cd8afce58261a6f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints plain text output of the test to a specified Writer. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 529f9b6ab9ced7b78871e3612cd8afce58261a6f $ + * @package phing.tasks.ext.phpunit.formatter + * @since 2.1.0 + */ +class PlainPHPUnitResultFormatter extends PHPUnitResultFormatter +{ + private $inner = ""; + + public function getExtension() + { + return ".txt"; + } + + public function getPreferredOutfile() + { + return "testresults"; + } + + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + parent::startTestSuite($suite); + + $this->inner = ""; + } + + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + if ($suite->getName() == 'AllTests') + { + return false; + } + + $sb = "Testsuite: " . $suite->getName() . "\n"; + $sb.= "Tests run: " . $this->getRunCount(); + $sb.= ", Failures: " . $this->getFailureCount(); + $sb.= ", Errors: " . $this->getErrorCount(); + $sb.= ", Incomplete: " . $this->getIncompleteCount(); + $sb.= ", Skipped: " . $this->getSkippedCount(); + $sb.= ", Time elapsed: " . sprintf('%0.5f', $this->getElapsedTime()) . " s\n"; + + if ($this->out != NULL) + { + $this->out->write($sb); + $this->out->write($this->inner); + } + + parent::endTestSuite($suite); + } + + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + parent::addError($test, $e, $time); + + $this->formatError("ERROR", $test, $e); + } + + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + parent::addFailure($test, $e, $time); + $this->formatError("FAILED", $test, $e); + } + + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + parent::addIncompleteTest($test, $e, $time); + + $this->formatError("INCOMPLETE", $test); + } + + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + parent::addSkippedTest($test, $e, $time); + $this->formatError("SKIPPED", $test); + } + + private function formatError($type, PHPUnit_Framework_Test $test, Exception $e = null) + { + if ($test != null) + { + $this->endTest($test, time()); + } + + $this->inner.= $test->getName() . " " . $type . "\n"; + + if ($e !== null) { + $this->inner.= $e->getMessage() . "\n"; + // $this->inner.= PHPUnit_Util_Filter::getFilteredStackTrace($e, true) . "\n"; + } + } + + public function endTestRun() + { + parent::endTestRun(); + + if ($this->out != NULL) + { + $this->out->close(); + } + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php new file mode 100755 index 00000000..0007c235 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php @@ -0,0 +1,62 @@ +<?php +/** + * $Id: bd9c51fa75c9b856105fc810200028d855a3782d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints short summary output of the test to Phing's logging system. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: bd9c51fa75c9b856105fc810200028d855a3782d $ + * @package phing.tasks.ext.formatter + * @since 2.1.0 + */ +class SummaryPHPUnitResultFormatter extends PHPUnitResultFormatter +{ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + parent::endTestSuite($suite); + } + + public function endTestRun() + { + parent::endTestRun(); + + $sb = "Total tests run: " . $this->getRunCount(); + $sb.= ", Failures: " . $this->getFailureCount(); + $sb.= ", Errors: " . $this->getErrorCount(); + $sb.= ", Incomplete: " . $this->getIncompleteCount(); + $sb.= ", Skipped: " . $this->getSkippedCount(); + $sb.= ", Time elapsed: " . sprintf('%0.5f', $this->getElapsedTime()) . " s\n"; + + if ($this->out != NULL) + { + $this->out->write($sb); + $this->out->close(); + } + } + + public function getExtension() + { + return NULL; + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php new file mode 100755 index 00000000..7fef7454 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php @@ -0,0 +1,120 @@ +<?php +/** + * $Id: 3d9c47a29ded9b67b3a3e10c55602b0ab2a9ea38 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'PHPUnit/Util/Log/JUnit.php'; + +require_once 'phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php'; + +/** + * Prints XML output of the test to a specified Writer + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 3d9c47a29ded9b67b3a3e10c55602b0ab2a9ea38 $ + * @package phing.tasks.ext.formatter + * @since 2.1.0 + */ +class XMLPHPUnitResultFormatter extends PHPUnitResultFormatter +{ + /** + * @var PHPUnit_Util_Log_JUnit + */ + private $logger = NULL; + + public function __construct(PHPUnitTask $parentTask) + { + parent::__construct($parentTask); + + $logIncompleteSkipped = $parentTask->getHaltonincomplete() || $parentTask->getHaltonskipped(); + + $this->logger = new PHPUnit_Util_Log_JUnit(null, $logIncompleteSkipped); + $this->logger->setWriteDocument(false); + } + + public function getExtension() + { + return ".xml"; + } + + public function getPreferredOutfile() + { + return "testsuites"; + } + + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + parent::startTestSuite($suite); + + $this->logger->startTestSuite($suite); + } + + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + parent::endTestSuite($suite); + + $this->logger->endTestSuite($suite); + } + + public function startTest(PHPUnit_Framework_Test $test) + { + parent::startTest($test); + + $this->logger->startTest($test); + } + + public function endTest(PHPUnit_Framework_Test $test, $time) + { + parent::endTest($test, $time); + + $this->logger->endTest($test, $time); + } + + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + parent::addError($test, $e, $time); + + $this->logger->addError($test, $e, $time); + } + + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + parent::addFailure($test, $e, $time); + + $this->logger->addFailure($test, $e, $time); + } + + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + parent::addIncompleteTest($test, $e, $time); + + $this->logger->addIncompleteTest($test, $e, $time); + } + + public function endTestRun() + { + parent::endTestRun(); + + if ($this->out) + { + $this->out->write($this->logger->getXML()); + $this->out->close(); + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php deleted file mode 100644 index 63f8911a..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php -/** - * $Id: BatchTest.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'phing/types/FileSet.php'; - -/** - * Scans a list of (.php) files given by the fileset attribute, extracts - * all subclasses of PHPUnit2_Framework_TestCase. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: BatchTest.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class BatchTest -{ - /** the list of filesets containing the testcase filename rules */ - private $filesets = array(); - - /** the reference to the project */ - private $project = NULL; - - /** the classpath to use with Phing::__import() calls */ - private $classpath = NULL; - - /** names of classes to exclude */ - private $excludeClasses = array(); - - /** - * Create a new batchtest instance - * - * @param Project the project it depends on. - */ - function __construct(Project $project) - { - $this->project = $project; - } - - /** - * Sets the classes to exclude - */ - function setExclude($exclude) - { - $this->excludeClasses = explode(" ", $exclude); - } - - /** - * Sets the classpath - */ - function setClasspath(Path $classpath) - { - if ($this->classpath === null) - { - $this->classpath = $classpath; - } - else - { - $this->classpath->append($classpath); - } - } - - /** - * Creates a new Path object - */ - function createClasspath() - { - $this->classpath = new Path(); - return $this->classpath; - } - - /** - * Returns the classpath - */ - function getClasspath() - { - return $this->classpath; - } - - /** - * Add a new fileset containing the XML results to aggregate - * - * @param FileSet the new fileset containing XML results. - */ - function addFileSet(FileSet $fileset) - { - $this->filesets[] = $fileset; - } - - /** - * Iterate over all filesets and return the filename of all files - * that end with .php. - * - * @return array an array of filenames - */ - private function getFilenames() - { - $filenames = array(); - - foreach ($this->filesets as $fileset) - { - $ds = $fileset->getDirectoryScanner($this->project); - $ds->scan(); - - $files = $ds->getIncludedFiles(); - - foreach ($files as $file) - { - if (strstr($file, ".php")) - { - $filenames[] = $ds->getBaseDir() . "/" . $file; - } - } - } - - return $filenames; - } - - /** - * Filters an array of classes, removes all classes that are not subclasses of PHPUnit2_Framework_TestCase, - * or classes that are declared abstract - */ - private function filterTests($input) - { - $reflect = new ReflectionClass($input); - - return is_subclass_of($input, 'PHPUnit2_Framework_TestCase') && (!$reflect->isAbstract()); - } - - /** - * Returns an array of PHPUnit2_Framework_TestCase classes that are declared - * by the files included by the filesets - * - * @return array an array of PHPUnit2_Framework_TestCase classes. - */ - function elements() - { - $filenames = $this->getFilenames(); - - $declaredClasses = array(); - - foreach ($filenames as $filename) - { - $definedClasses = PHPUnit2Util::getDefinedClasses($filename); - - $declaredClasses = array_merge($declaredClasses, $definedClasses); - } - - $elements = array_filter($declaredClasses, array($this, "filterTests")); - - return $elements; - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php deleted file mode 100644 index 9d2a4656..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php -/** - * $Id: FormatterElement.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php'; -require_once 'phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php'; -require_once 'phing/system/io/PhingFile.php'; - -/** - * A wrapper for the implementations of PHPUnit2ResultFormatter. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: FormatterElement.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class FormatterElement -{ - protected $formatter = NULL; - - protected $type = ""; - - protected $useFile = true; - - protected $toDir = "."; - - protected $outfile = ""; - - function setType($type) - { - $this->type = $type; - - if ($this->type == "xml") - { - $destFile = new PhingFile($this->toDir, 'testsuites.xml'); - $this->formatter = new XMLPHPUnit2ResultFormatter(); - } - else - if ($this->type == "plain") - { - $this->formatter = new PlainPHPUnit2ResultFormatter(); - } - else - { - throw new BuildException("Formatter '" . $this->type . "' not implemented"); - } - } - - function setClassName($className) - { - $classNameNoDot = Phing::import($className); - - $this->formatter = new $classNameNoDot(); - } - - function setUseFile($useFile) - { - $this->useFile = $useFile; - } - - function getUseFile() - { - return $this->useFile; - } - - function setToDir($toDir) - { - $this->toDir = $toDir; - } - - function getToDir() - { - return $this->toDir; - } - - function setOutfile($outfile) - { - $this->outfile = $outfile; - } - - function getOutfile() - { - if ($this->outfile) - { - return $this->outfile; - } - else - { - return $this->formatter->getPreferredOutfile() . $this->getExtension(); - } - } - - function getExtension() - { - return $this->formatter->getExtension(); - } - - function getFormatter() - { - return $this->formatter; - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php deleted file mode 100644 index 1e08e79c..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php -/** - * $Id: PHPUnit2ReportTask.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'phing/Task.php'; -require_once 'phing/system/io/PhingFile.php'; -require_once 'phing/system/io/FileWriter.php'; -require_once 'phing/util/ExtendedFileStream.php'; - -/** - * Transform a PHPUnit2 xml report using XSLT. - * This transformation generates an html report in either framed or non-framed - * style. The non-framed style is convenient to have a concise report via mail, - * the framed report is much more convenient if you want to browse into - * different packages or testcases since it is a Javadoc like report. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2ReportTask.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PHPUnit2ReportTask extends Task -{ - private $format = "noframes"; - private $styleDir = ""; - private $toDir = ""; - - /** the directory where the results XML can be found */ - private $inFile = "testsuites.xml"; - - /** - * Set the filename of the XML results file to use. - */ - function setInFile($inFile) - { - $this->inFile = $inFile; - } - - /** - * Set the format of the generated report. Must be noframes or frames. - */ - function setFormat($format) - { - $this->format = $format; - } - - /** - * Set the directory where the stylesheets are located. - */ - function setStyleDir($styleDir) - { - $this->styleDir = $styleDir; - } - - /** - * Set the directory where the files resulting from the - * transformation should be written to. - */ - function setToDir($toDir) - { - $this->toDir = $toDir; - } - - private function getStyleSheet() - { - $xslname = "phpunit2-" . $this->format . ".xsl"; - - if ($this->styleDir) - { - $file = new PhingFile($this->styleDir, $xslname); - } - else - { - $path = Phing::getResourcePath("phing/etc/$xslname"); - - if ($path === NULL) - { - $path = Phing::getResourcePath("etc/$xslname"); - - if ($path === NULL) - { - throw new BuildException("Could not find $xslname in resource path"); - } - } - - $file = new PhingFile($path); - } - - if (!$file->exists()) - { - throw new BuildException("Could not find file " . $file->getPath()); - } - - return $file; - } - - function transform($document) - { - $dir = new PhingFile($this->toDir); - - if (!$dir->exists()) - { - throw new BuildException("Directory '" . $this->toDir . "' does not exist"); - } - - $xslfile = $this->getStyleSheet(); - - $xsl = new DOMDocument(); - $xsl->load($xslfile->getAbsolutePath()); - - $proc = new XSLTProcessor(); - $proc->importStyleSheet($xsl); - - if ($this->format == "noframes") - { - $writer = new FileWriter(new PhingFile($this->toDir, "phpunit2-noframes.html")); - $writer->write($proc->transformToXML($document)); - $writer->close(); - } - else - { - ExtendedFileStream::registerStream(); - - // no output for the framed report - // it's all done by extension... - $dir = new PhingFile($this->toDir); - $proc->setParameter('', 'output.dir', $dir->getAbsolutePath()); - $proc->transformToXML($document); - } - } - - /** - * The main entry point - * - * @throws BuildException - */ - function main() - { - $testSuitesDoc = new DOMDocument(); - $testSuitesDoc->load($this->inFile); - - $this->transform($testSuitesDoc); - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php deleted file mode 100644 index 5722c63e..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -/** - * $Id: PHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'PHPUnit2/Framework/TestListener.php'; - -require_once 'phing/system/io/Writer.php'; - -/** - * This abstract class describes classes that format the results of a PHPUnit2 testrun. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -abstract class PHPUnit2ResultFormatter implements PHPUnit2_Framework_TestListener -{ - protected $out = NULL; - - protected $project = NULL; - - private $timer = NULL; - - private $runCount = 0; - - private $failureCount = 0; - - private $errorCount = 0; - - /** - * Sets the writer the formatter is supposed to write its results to. - */ - function setOutput(Writer $out) - { - $this->out = $out; - } - - /** - * Returns the extension used for this formatter - * - * @return string the extension - */ - function getExtension() - { - return ""; - } - - /** - * Sets the project - * - * @param Project the project - */ - function setProject(Project $project) - { - $this->project = $project; - } - - function getPreferredOutfile() - { - return ""; - } - - function startTestRun() - { - } - - function endTestRun() - { - } - - function startTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - $this->runCount = 0; - $this->failureCount = 0; - $this->errorCount = 0; - - $this->timer = new Timer(); - $this->timer->start(); - } - - function endTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - $this->timer->stop(); - } - - function startTest(PHPUnit2_Framework_Test $test) - { - $this->runCount++; - } - - function endTest(PHPUnit2_Framework_Test $test) - { - } - - function addError(PHPUnit2_Framework_Test $test, Exception $e) - { - $this->errorCount++; - } - - function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t) - { - $this->failureCount++; - } - - function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) - { - } - - function getRunCount() - { - return $this->runCount; - } - - function getFailureCount() - { - return $this->failureCount; - } - - function getErrorCount() - { - return $this->errorCount; - } - - function getElapsedTime() - { - if ($this->timer) - { - return $this->timer->getElapsedTime(); - } - else - { - return 0; - } - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php deleted file mode 100644 index ffd36405..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php -/** - * $Id: PHPUnit2Task.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'phing/Task.php'; -require_once 'phing/system/io/PhingFile.php'; -require_once 'phing/system/io/Writer.php'; -require_once 'phing/util/LogWriter.php'; - -/** - * Runs PHPUnit2 tests. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2Task.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @see BatchTest - * @since 2.1.0 - */ -class PHPUnit2Task extends Task -{ - private $batchtests = array(); - private $formatters = array(); - private $haltonerror = false; - private $haltonfailure = false; - private $failureproperty; - private $errorproperty; - private $printsummary = false; - private $testfailed = false; - private $codecoverage = false; - - /** - * Initialize Task. - * This method includes any necessary PHPUnit2 libraries and triggers - * appropriate error if they cannot be found. This is not done in header - * because we may want this class to be loaded w/o triggering an error. - */ - function init() { - include_once 'PHPUnit2/Util/Filter.php'; - if (!class_exists('PHPUnit2_Util_Filter')) { - throw new BuildException("PHPUnit2Task depends on PEAR PHPUnit2 package being installed.", $this->getLocation()); - } - - if (version_compare(PHP_VERSION, '5.0.3') < 0) { - throw new BuildException("PHPUnit2Task requires PHP version >= 5.0.3.", $this->getLocation()); - } - - // other dependencies that should only be loaded when class is actually used. - require_once 'phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php'; - require_once 'phing/tasks/ext/phpunit2/BatchTest.php'; - require_once 'phing/tasks/ext/phpunit2/FormatterElement.php'; - require_once 'phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php'; - - // add some defaults to the PHPUnit2 Filter - PHPUnit2_Util_Filter::addFileToFilter('PHPUnit2Task.php'); - PHPUnit2_Util_Filter::addFileToFilter('PHPUnit2TestRunner.php'); - PHPUnit2_Util_Filter::addFileToFilter('phing/Task.php'); - PHPUnit2_Util_Filter::addFileToFilter('phing/Target.php'); - PHPUnit2_Util_Filter::addFileToFilter('phing/Project.php'); - PHPUnit2_Util_Filter::addFileToFilter('phing/Phing.php'); - PHPUnit2_Util_Filter::addFileToFilter('phing.php'); - - } - - function setFailureproperty($value) - { - $this->failureproperty = $value; - } - - function setErrorproperty($value) - { - $this->errorproperty = $value; - } - - function setHaltonerror($value) - { - $this->haltonerror = $value; - } - - function setHaltonfailure($value) - { - $this->haltonfailure = $value; - } - - function setPrintsummary($printsummary) - { - $this->printsummary = $printsummary; - } - - function setCodecoverage($codecoverage) - { - $this->codecoverage = $codecoverage; - } - - /** - * Add a new formatter to all tests of this task. - * - * @param FormatterElement formatter element - */ - function addFormatter(FormatterElement $fe) - { - $this->formatters[] = $fe; - } - - /** - * The main entry point - * - * @throws BuildException - */ - function main() - { - $tests = array(); - - if ($this->printsummary) - { - $fe = new FormatterElement(); - $fe->setClassName('SummaryPHPUnit2ResultFormatter'); - $fe->setUseFile(false); - $this->formatters[] = $fe; - } - - foreach ($this->batchtests as $batchtest) - { - $tests = array_merge($tests, $batchtest->elements()); - } - - foreach ($this->formatters as $fe) - { - $formatter = $fe->getFormatter(); - $formatter->setProject($this->getProject()); - - if ($fe->getUseFile()) - { - $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); - - $writer = new FileWriter($destFile->getAbsolutePath()); - - $formatter->setOutput($writer); - } - else - { - $formatter->setOutput($this->getDefaultOutput()); - } - - $formatter->startTestRun(); - } - - foreach ($tests as $test) - { - $this->execute(new PHPUnit2_Framework_TestSuite(new ReflectionClass($test))); - } - - foreach ($this->formatters as $fe) - { - $formatter = $fe->getFormatter(); - $formatter->endTestRun(); - } - - if ($this->testfailed) - { - throw new BuildException("One or more tests failed"); - } - } - - /** - * @throws BuildException - */ - private function execute($suite) - { - $runner = new PHPUnit2TestRunner($suite, $this->project); - - $runner->setCodecoverage($this->codecoverage); - - foreach ($this->formatters as $fe) - { - $formatter = $fe->getFormatter(); - - $runner->addFormatter($formatter); - } - - $runner->run(); - - $retcode = $runner->getRetCode(); - - if ($retcode == PHPUnit2TestRunner::ERRORS) { - if ($this->errorproperty) { - $this->project->setNewProperty($this->errorproperty, true); - } - if ($this->haltonerror) { - $this->testfailed = true; - } - } elseif ($retcode == PHPUnit2TestRunner::FAILURES) { - if ($this->failureproperty) { - $this->project->setNewProperty($this->failureproperty, true); - } - - if ($this->haltonfailure) { - $this->testfailed = true; - } - } - - } - - private function getDefaultOutput() - { - return new LogWriter($this); - } - - /** - * Adds a set of tests based on pattern matching. - * - * @return BatchTest a new instance of a batch test. - */ - function createBatchTest() - { - $batchtest = new BatchTest($this->getProject()); - - $this->batchtests[] = $batchtest; - - return $batchtest; - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php deleted file mode 100644 index bbd19f34..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php -/** - * $Id: PHPUnit2TestRunner.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'PHPUnit2/Framework/TestListener.php'; -require_once 'PHPUnit2/Framework/TestResult.php'; -require_once 'PHPUnit2/Framework/TestSuite.php'; - -require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; - -require_once 'phing/system/util/Timer.php'; - -/** - * Simple Testrunner for PHPUnit2 that runs all tests of a testsuite. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2TestRunner.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PHPUnit2TestRunner -{ - const SUCCESS = 0; - const FAILURES = 1; - const ERRORS = 2; - - private $test = NULL; - private $suite = NULL; - private $retCode = 0; - private $formatters = array(); - - private $codecoverage = false; - - private $project = NULL; - - function __construct(PHPUnit2_Framework_TestSuite $suite, Project $project) - { - $this->suite = $suite; - $this->project = $project; - $this->retCode = self::SUCCESS; - } - - function setCodecoverage($codecoverage) - { - $this->codecoverage = $codecoverage; - } - - function addFormatter(PHPUnit2_Framework_TestListener $formatter) - { - $this->formatters[] = $formatter; - } - - function run() - { - $res = new PHPUnit2_Framework_TestResult(); - - if ($this->codecoverage) - { - $res->collectCodeCoverageInformation(TRUE); - } - - foreach ($this->formatters as $formatter) - { - $res->addListener($formatter); - } - - $this->suite->run($res); - - if ($this->codecoverage) - { - CoverageMerger::merge($this->project, $res->getCodeCoverageInformation()); - } - - if ($res->errorCount() != 0) - { - $this->retCode = self::ERRORS; - } - - else if ($res->failureCount() != 0 || $res->notImplementedCount() != 0) - { - $this->retCode = self::FAILURES; - } - } - - function getRetCode() - { - return $this->retCode; - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php deleted file mode 100644 index f4d1f62a..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php -/** - * $Id: PHPUnit2Util.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -/** - * Various utility functions - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PHPUnit2Util.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PHPUnit2Util -{ - protected static $definedClasses = array(); - - /** - * Returns the package of a class as defined in the docblock of the class using @package - * - * @param string the name of the class - * @return string the name of the package - */ - static function getPackageName($classname) - { - $reflect = new ReflectionClass($classname); - - if (preg_match('/@package[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches)) - { - return $matches[1]; - } - else - { - return "default"; - } - } - - /** - * Derives the classname from a filename. - * Assumes that there is only one class defined in that particular file, and that - * the naming follows the dot-path (Java) notation scheme. - * - * @param string the filename - * @return string the name fo the class - */ - static function getClassFromFileName($filename) - { - $filename = basename($filename); - - $rpos = strrpos($filename, '.'); - - if ($rpos != -1) - { - $filename = substr($filename, 0, $rpos); - } - - return $filename; - } - - /** - * @param string the filename - * @param Path optional classpath - * @return array list of classes defined in the file - */ - static function getDefinedClasses($filename, $classpath = NULL) - { - $filename = realpath($filename); - - if (!file_exists($filename)) - { - throw new Exception("File '" . $filename . "' does not exist"); - } - - if (isset(self::$definedClasses[$filename])) - { - return self::$definedClasses[$filename]; - } - - Phing::__import($filename, $classpath); - - $declaredClasses = get_declared_classes(); - - foreach ($declaredClasses as $classname) - { - $reflect = new ReflectionClass($classname); - - self::$definedClasses[$reflect->getFilename()][] = $classname; - - if (is_array(self::$definedClasses[$reflect->getFilename()])) - { - self::$definedClasses[$reflect->getFilename()] = array_unique(self::$definedClasses[$reflect->getFilename()]); - } - } - - return self::$definedClasses[$filename]; - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php deleted file mode 100644 index b0a9ae58..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php -/** - * $Id: PlainPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'PHPUnit2/Framework/Test.php'; -require_once 'PHPUnit2/Util/Filter.php'; - -require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php'; - -/** - * Prints plain text output of the test to a specified Writer. - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: PlainPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class PlainPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter -{ - private $inner = ""; - - function getExtension() - { - return ".txt"; - } - - function getPreferredOutfile() - { - return "testresults"; - } - - function startTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - parent::startTestSuite($suite); - - $this->inner = ""; - } - - function endTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - parent::endTestSuite($suite); - - $sb = "Testsuite: " . $suite->getName() . "\n"; - $sb.= "Tests run: " . $this->getRunCount(); - $sb.= ", Failures: " . $this->getFailureCount(); - $sb.= ", Errors: " . $this->getErrorCount(); - $sb.= ", Time elapsed: " . $this->getElapsedTime(); - $sb.= " sec\n"; - - if ($this->out != NULL) - { - $this->out->write($sb); - $this->out->write($this->inner); - } - } - - function addError(PHPUnit2_Framework_Test $test, Exception $e) - { - parent::addError($test, $e); - - $this->formatError("ERROR", $test, $e); - } - - function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t) - { - parent::addFailure($test, $t); - - $this->formatError("FAILED", $test, $t); - } - - function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) - { - parent::addIncompleteTest($test, $e); - - $this->formatError("INCOMPLETE", $test, $e); - } - - private function formatError($type, PHPUnit2_Framework_Test $test, Exception $e) - { - if ($test != null) - { - $this->endTest($test); - } - - $this->inner.= $test->getName() . " " . $type . "\n"; - $this->inner.= $e->getMessage() . "\n"; - $this->inner.= PHPUnit2_Util_Filter::getFilteredStackTrace($e) . "\n"; - } - - function endTestRun() - { - parent::endTestRun(); - - if ($this->out != NULL) - { - $this->out->close(); - } - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php deleted file mode 100644 index ac2fec8f..00000000 --- a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php -/** - * $Id: XMLPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software consists of voluntary contributions made by many individuals - * and is licensed under the LGPL. For more information please see - * <http://phing.info>. - */ - -require_once 'PHPUnit2/Framework/Test.php'; -require_once 'PHPUnit2/Runner/Version.php'; - -require_once 'PHPUnit2/Util/Log/XML.php'; - -require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php'; - -/** - * Prints XML output of the test to a specified Writer - * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: XMLPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ - * @package phing.tasks.ext.phpunit2 - * @since 2.1.0 - */ -class XMLPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter -{ - private $logger = NULL; - - function __construct() - { - $this->logger = new PHPUnit2_Util_Log_XML(); - $this->logger->setWriteDocument(false); - } - - function getExtension() - { - return ".xml"; - } - - function getPreferredOutfile() - { - return "testsuites"; - } - - function startTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - parent::startTestSuite($suite); - - $this->logger->startTestSuite($suite); - } - - function endTestSuite(PHPUnit2_Framework_TestSuite $suite) - { - parent::endTestSuite($suite); - - $this->logger->endTestSuite($suite); - } - - function startTest(PHPUnit2_Framework_Test $test) - { - parent::startTest($test); - - $this->logger->startTest($test); - } - - function endTest(PHPUnit2_Framework_Test $test) - { - parent::endTest($test); - - $this->logger->endTest($test); - } - - function addError(PHPUnit2_Framework_Test $test, Exception $e) - { - parent::addError($test, $e); - - $this->logger->addError($test, $e); - } - - function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t) - { - parent::addFailure($test, $t); - - $this->logger->addFailure($test, $t); - } - - function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) - { - parent::addIncompleteTest($test, $e); - - $this->logger->addIncompleteTest($test, $e); - } - - function endTestRun() - { - parent::endTestRun(); - - if ($this->out) - { - $this->out->write($this->logger->getXML()); - $this->out->close(); - } - } -} -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/rSTTask.php b/buildscripts/phing/classes/phing/tasks/ext/rSTTask.php new file mode 100644 index 00000000..77170f18 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/rSTTask.php @@ -0,0 +1,476 @@ +<?php + +/** + * reStructuredText rendering task for Phing, the PHP build tool. + * + * PHP version 5 + * + * @category Tasks + * @package phing.tasks.ext + * @author Christian Weiske <cweiske@cweiske.de> + * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link http://www.phing.info/ + * @version SVN: $Id: ad2ac21008b4635c4f557e3a65c9306a350ca1f2 $ + */ + +require_once 'phing/Task.php'; +require_once 'phing/util/FileUtils.php'; + +/** + * reStructuredText rendering task for Phing, the PHP build tool. + * + * PHP version 5 + * + * @category Tasks + * @package phing.tasks.ext + * @author Christian Weiske <cweiske@cweiske.de> + * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link http://www.phing.info/ + */ +class rSTTask extends Task +{ + /** + * @var string Taskname for logger + */ + protected $taskName = 'rST'; + + /** + * Result format, defaults to "html". + * @see $supportedFormats for all possible options + * + * @var string + */ + protected $format = 'html'; + + /** + * Array of supported output formats + * + * @var array + * @see $format + * @see $targetExt + */ + protected static $supportedFormats = array( + 'html', 'latex', 'man', 'odt', 's5', 'xml' + ); + + /** + * Maps formats to file extensions + * + * @var array + */ + protected static $targetExt = array( + 'html' => 'html', + 'latex' => 'tex', + 'man' => '3', + 'odt' => 'odt', + 's5' => 'html', + 'xml' => 'xml', + ); + + /** + * Input file in rST format. + * Required + * + * @var string + */ + protected $file = null; + + /** + * Additional rst2* tool parameters. + * + * @var string + */ + protected $toolParam = null; + + /** + * Full path to the tool, i.e. /usr/local/bin/rst2html + * + * @var string + */ + protected $toolPath = null; + + /** + * Output file or directory. May be omitted. + * When it ends with a slash, it is considered to be a directory + * + * @var string + */ + protected $destination = null; + + protected $filesets = array(); // all fileset objects assigned to this task + protected $mapperElement = null; + + /** + * all filterchains objects assigned to this task + * + * @var array + */ + protected $filterChains = array(); + + /** + * mode to create directories with + * + * @var integer + */ + protected $mode = 0755; + + /** + * Only render files whole source files are newer than the + * target files + * + * @var boolean + */ + protected $uptodate = false; + + + /** + * Init method: requires the PEAR System class + */ + public function init() + { + require_once 'System.php'; + } + + /** + * The main entry point method. + * + * @return void + */ + public function main() + { + $tool = $this->getToolPath($this->format); + if (count($this->filterChains)) { + $this->fileUtils = new FileUtils(); + } + + if ($this->file != '') { + $file = $this->file; + $targetFile = $this->getTargetFile($file, $this->destination); + $this->render($tool, $file, $targetFile); + return; + } + + if (!count($this->filesets)) { + throw new BuildException( + '"file" attribute or "fileset" subtag required' + ); + } + + // process filesets + $mapper = null; + if ($this->mapperElement !== null) { + $mapper = $this->mapperElement->getImplementation(); + } + + $project = $this->getProject(); + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $fromDir = $fs->getDir($project); + $srcFiles = $ds->getIncludedFiles(); + + foreach ($srcFiles as $src) { + $file = new PhingFile($fromDir, $src); + if ($mapper !== null) { + $results = $mapper->main($file); + if ($results === null) { + throw new BuildException( + sprintf( + 'No filename mapper found for "%s"', + $file + ) + ); + } + $targetFile = reset($results); + } else { + $targetFile = $this->getTargetFile($file, $this->destination); + } + $this->render($tool, $file, $targetFile); + } + } + } + + + + /** + * Renders a single file and applies filters on it + * + * @param string $tool conversion tool to use + * @param string $source rST source file + * @param string $targetFile target file name + * + * @return void + */ + protected function render($tool, $source, $targetFile) + { + if (count($this->filterChains) == 0) { + return $this->renderFile($tool, $source, $targetFile); + } + + $tmpTarget = tempnam(sys_get_temp_dir(), 'rST-'); + $this->renderFile($tool, $source, $tmpTarget); + + $this->fileUtils->copyFile( + new PhingFile($tmpTarget), + new PhingFile($targetFile), + true, false, $this->filterChains, + $this->getProject(), $this->mode + ); + unlink($tmpTarget); + } + + + + /** + * Renders a single file with the rST tool. + * + * @param string $tool conversion tool to use + * @param string $source rST source file + * @param string $targetFile target file name + * + * @return void + * + * @throws BuildException When the conversion fails + */ + protected function renderFile($tool, $source, $targetFile) + { + if ($this->uptodate && file_exists($targetFile) + && filemtime($source) <= filemtime($targetFile) + ) { + //target is up to date + return; + } + //work around a bug in php by replacing /./ with / + $targetDir = str_replace('/./', '/', dirname($targetFile)); + if (!is_dir($targetDir)) { + $this->log("Creating directory '$targetDir'", Project::MSG_VERBOSE); + mkdir($targetDir, $this->mode, true); + } + + $cmd = $tool + . ' --exit-status=2' + . ' ' . $this->toolParam + . ' ' . escapeshellarg($source) + . ' ' . escapeshellarg($targetFile) + . ' 2>&1'; + + $this->log('command: ' . $cmd, Project::MSG_VERBOSE); + exec($cmd, $arOutput, $retval); + if ($retval != 0) { + $this->log(implode("\n", $arOutput), Project::MSG_INFO); + throw new BuildException('Rendering rST failed'); + } + $this->log(implode("\n", $arOutput), Project::MSG_DEBUG); + } + + + + /** + * Finds the rst2* binary path + * + * @param string $format Output format + * + * @return string Full path to rst2$format + * + * @throws BuildException When the tool cannot be found + */ + protected function getToolPath($format) + { + if ($this->toolPath !== null) { + return $this->toolPath; + } + + $tool = 'rst2' . $format; + $path = System::which($tool); + if (!$path) { + throw new BuildException( + sprintf('"%s" not found. Install python-docutils.', $tool) + ); + } + + return $path; + } + + + + /** + * Determines and returns the target file name from the + * input file and the configured destination name. + * + * @param string $file Input file + * @param string $destination Destination file or directory name, + * may be null + * + * @return string Target file name + * + * @uses $format + * @uses $targetExt + */ + public function getTargetFile($file, $destination = null) + { + if ($destination != '' + && substr($destination, -1) !== '/' + && substr($destination, -1) !== '\\' + ) { + return $destination; + } + + if (strtolower(substr($file, -4)) == '.rst') { + $file = substr($file, 0, -4); + } + + return $destination . $file . '.' . self::$targetExt[$this->format]; + } + + + + /** + * The setter for the attribute "file" + * + * @param string $file Path of file to render + * + * @return void + */ + public function setFile($file) + { + $this->file = $file; + } + + + + /** + * The setter for the attribute "format" + * + * @param string $format Output format + * + * @return void + * + * @throws BuildException When the format is not supported + */ + public function setFormat($format) + { + if (!in_array($format, self::$supportedFormats)) { + throw new BuildException( + sprintf( + 'Invalid output format "%s", allowed are: %s', + $format, + implode(', ', self::$supportedFormats) + ) + ); + } + $this->format = $format; + } + + + + /** + * The setter for the attribute "destination" + * + * @param string $destination Output file or directory. When it ends + * with a slash, it is taken as directory. + * + * @return void + */ + public function setDestination($destination) + { + $this->destination = $destination; + } + + /** + * The setter for the attribute "toolparam" + * + * @param string $param Additional rst2* tool parameters + * + * @return void + */ + public function setToolparam($param) + { + $this->toolParam = $param; + } + + /** + * The setter for the attribute "toolpath" + * + * @param string $param Full path to tool path, i.e. /usr/local/bin/rst2html + * + * @return void + * + * @throws BuildException When the tool does not exist or is not executable + */ + public function setToolpath($path) + { + if (!file_exists($path)) { + $fullpath = System::which($path); + if ($fullpath === false) { + throw new BuildException( + 'Tool does not exist. Path: ' . $path + ); + } + $path = $fullpath; + } + if (!is_executable($path)) { + throw new BuildException( + 'Tool not executable. Path: ' . $path + ); + } + $this->toolPath = $path; + } + + /** + * The setter for the attribute "uptodate" + * + * @param string $uptodate True/false + * + * @return void + */ + public function setUptodate($uptodate) + { + $this->uptodate = (boolean)$uptodate; + } + + + + /** + * Add a set of files to be rendered. + * + * @param FileSet $fileset Set of rst files to render + * + * @return void + */ + public function addFileset(FileSet $fileset) + { + $this->filesets[] = $fileset; + } + + + + /** + * Nested creator, creates one Mapper for this task + * + * @return Mapper The created Mapper type object + * + * @throws BuildException + */ + public function createMapper() + { + if ($this->mapperElement !== null) { + throw new BuildException( + 'Cannot define more than one mapper', $this->location + ); + } + $this->mapperElement = new Mapper($this->project); + return $this->mapperElement; + } + + + + /** + * Creates a filterchain, stores and returns it + * + * @return FilterChain The created filterchain object + */ + public function createFilterChain() + { + $num = array_push($this->filterChains, new FilterChain($this->project)); + return $this->filterChains[$num-1]; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php index 654d65dd..32fbc212 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestCountResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: ae09aa1a433f4de854fa7c27903e7eb0957bc90b $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,29 +24,28 @@ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php'; /** * Dummy result formatter used to count SimpleTest results * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestCountResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: ae09aa1a433f4de854fa7c27903e7eb0957bc90b $ * @package phing.tasks.ext.simpletest * @since 2.2.0 */ class SimpleTestCountResultFormatter extends SimpleTestResultFormatter { - const SUCCESS = 0; - const FAILURES = 1; - const ERRORS = 2; - - function getRetCode() - { - if ($this->getExceptionCount() != 0) - { - return self::ERRORS; - } - else if ($this->getFailCount() != 0) - { - return self::FAILURES; - } - - return self::SUCCESS; - } + const SUCCESS = 0; + const FAILURES = 1; + const ERRORS = 2; + + function getRetCode() + { + if ($this->getExceptionCount() != 0) + { + return self::ERRORS; + } + else if ($this->getFailCount() != 0) + { + return self::FAILURES; + } + + return self::SUCCESS; + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php new file mode 100755 index 00000000..de78ab24 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php @@ -0,0 +1,119 @@ +<?php +/** + * $Id: d7e7e397e81588c3eafcb9e758666fec0fa166f5 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php'; + +/** + * Prints plain text output of the test to a specified Writer. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: d7e7e397e81588c3eafcb9e758666fec0fa166f5 $ + * @package phing.tasks.ext.simpletest + * @since 2.2.0 + */ +class SimpleTestDebugResultFormatter extends SimpleTestResultFormatter +{ + protected $current_case = ""; + protected $current_test = ""; + private $failingTests = array(); + + function printFailingTests() { + foreach ($this->failingTests as $test) { + $this->out->write($test . "\n"); + } + } + + function paintCaseStart($test_name) + { + parent::paintCaseStart($test_name); + $this->paint( "Testsuite: $test_name\n"); + $this->current_case = $test_name; + } + + function paintMethodStart($test_name) + { + parent::paintMethodStart($test_name); + $this->current_test = $test_name; + //$msg = "{$this->current_case} :: $test_name\n"; + $msg = " TestCase: $test_name"; + $this->paint($msg); + } + + function paint($msg) { + if ($this->out == null ) { + print $msg; + } else { + $this->out->write($msg); + } + } + + function paintMethodEnd($test_name) { + parent::paintMethodEnd($test_name); + $this->paint("\n"); + } + + function paintCaseEnd($test_name) + { + parent::paintCaseEnd($test_name); + $this->current_case = ""; + /* Only count suites where more than one test was run */ + + if ($this->getRunCount() && false) + { + $sb = ""; + $sb.= "Tests run: " . $this->getRunCount(); + $sb.= ", Failures: " . $this->getFailureCount(); + $sb.= ", Errors: " . $this->getErrorCount(); + $sb.= ", Time elapsed: " . $this->getElapsedTime(); + $sb.= " sec\n"; + $this->paint($sb); + } + + } + + function paintError($message) + { + parent::paintError($message); + $this->formatError("ERROR", $message); + $this->failingTests[] = $this->current_case . "->" . $this->current_test; + } + + function paintFail($message) + { + parent::paintFail($message); + $this->formatError("FAILED", $message); + $this->failingTests[] = $this->current_case . "->" . $this->current_test; + } + function paintException($message) + { + parent::paintException($message); + $this->failingTests[] = $this->current_case . "->" . $this->current_test; + $this->formatError("Exception", $message); + } + + + + private function formatError($type, $message) + { + $this->paint("ERROR: $type: $message"); + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php index 768a041f..5ae9ba23 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestFormatterElement.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: 2441f1b83b9f9d1aeb2a4afd7e049c840d70bbd9 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,108 +19,50 @@ * <http://phing.info>. */ -require_once 'phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php'; -require_once 'phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php'; -require_once 'phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php'; +require_once 'phing/tasks/ext/phpunit/FormatterElement.php'; /** * Child class of "FormatterElement", overrides setType to provide other * formatter classes for SimpleTest * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestFormatterElement.php 58 2006-04-28 14:41:04Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 2441f1b83b9f9d1aeb2a4afd7e049c840d70bbd9 $ * @package phing.tasks.ext.simpletest * @since 2.2.0 */ -class SimpleTestFormatterElement +class SimpleTestFormatterElement extends FormatterElement { - protected $formatter = NULL; - - protected $type = ""; - - protected $useFile = true; - - protected $toDir = "."; - - protected $outfile = ""; - - function setType($type) - { - $this->type = $type; - - if ($this->type == "xml") - { - //$destFile = new PhingFile($this->toDir, 'testsuites.xml'); - $this->formatter = new SimpleTestXmlResultFormatter(); - } - else - if ($this->type == "plain") - { - $this->formatter = new SimpleTestPlainResultFormatter(); - } - else - if ($this->type == "summary") - { - $this->formatter = new SimpleTestSummaryResultFormatter(); - } - else - { - throw new BuildException("Formatter '" . $this->type . "' not implemented"); - } - } - - function setClassName($className) - { - $classNameNoDot = Phing::import($className); - - $this->formatter = new $classNameNoDot(); - } - - function setUseFile($useFile) - { - $this->useFile = $useFile; - } - - function getUseFile() - { - return $this->useFile; - } - - function setToDir($toDir) - { - $this->toDir = $toDir; - } - - function getToDir() - { - return $this->toDir; - } - - function setOutfile($outfile) - { - $this->outfile = $outfile; - } - - function getOutfile() - { - if ($this->outfile) - { - return $this->outfile; - } - else - { - return $this->formatter->getPreferredOutfile() . $this->getExtension(); - } - } - - function getExtension() - { - return $this->formatter->getExtension(); - } - - function getFormatter() - { - return $this->formatter; - } + function setType($type) + { + $this->type = $type; + + if ($this->type == "xml") + { + require_once 'phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php'; + $destFile = new PhingFile($this->toDir, 'testsuites.xml'); + $this->formatter = new SimpleTestXmlResultFormatter(); + } + else + if ($this->type == "plain") + { + require_once 'phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php'; + $this->formatter = new SimpleTestPlainResultFormatter(); + } + else + if ($this->type == "summary") + { + require_once 'phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php'; + $this->formatter = new SimpleTestSummaryResultFormatter(); + } + else + if ($this->type == "debug") + { + require_once 'phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php'; + $this->formatter = new SimpleTestDebugResultFormatter(); + } + else + { + throw new BuildException("Formatter '" . $this->type . "' not implemented"); + } + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php index 9d570486..cfba9533 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c0fa060b8f439f7d0013a0ec016ede4c5a76b42d $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,72 +24,72 @@ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php'; /** * Prints plain text output of the test to a specified Writer. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: c0fa060b8f439f7d0013a0ec016ede4c5a76b42d $ * @package phing.tasks.ext.simpletest * @since 2.2.0 */ class SimpleTestPlainResultFormatter extends SimpleTestResultFormatter { - private $inner = ""; + private $inner = ""; + + function getExtension() + { + return ".txt"; + } + + function getPreferredOutfile() + { + return "testresults"; + } - function getExtension() - { - return ".txt"; - } + function paintCaseStart($test_name) + { + parent::paintCaseStart($test_name); + + $this->inner = ""; + } + + function paintCaseEnd($test_name) + { + parent::paintCaseEnd($test_name); + + $sb = ""; + /* Only count suites where more than one test was run */ + if ($this->getRunCount()) + { + $sb.= "Testsuite: $test_name\n"; + $sb.= "Tests run: " . $this->getRunCount(); + $sb.= ", Failures: " . $this->getFailureCount(); + $sb.= ", Errors: " . $this->getErrorCount(); + $sb.= ", Time elapsed: " . $this->getElapsedTime(); + $sb.= " sec\n"; - function getPreferredOutfile() - { - return "testresults"; - } + if ($this->out != NULL) + { + $this->out->write($sb); + $this->out->write($this->inner); + } + } + } - function paintCaseStart($test_name) - { - parent::paintCaseStart($test_name); + function paintError($message) + { + parent::paintError($message); + + $this->formatError("ERROR", $message); + } - $this->inner = ""; - } + function paintFail($message) + { + parent::paintFail($message); + + $this->formatError("FAILED", $message); + } - function paintCaseEnd($test_name) - { - parent::paintCaseEnd($test_name); - - /* Only count suites where more than one test was run */ - if ($this->getRunCount()) - { - $sb = "Testsuite: $test_name\n"; - $sb.= "Tests run: " . $this->getRunCount(); - $sb.= ", Failures: " . $this->getFailureCount(); - $sb.= ", Errors: " . $this->getErrorCount(); - $sb.= ", Time elapsed: " . $this->getElapsedTime(); - $sb.= " sec\n"; - - if ($this->out != NULL) - { - $this->out->write($sb); - $this->out->write($this->inner); - } - } - } - - function paintError($message) - { - parent::paintError($message); - - $this->formatError("ERROR", $message); - } - - function paintFail($message) - { - parent::paintFail($message); - - $this->formatError("FAILED", $message); - } - - private function formatError($type, $message) - { - $this->inner.= $this->getTestName() . " " . $type . "\n"; - $this->inner.= $message . "\n"; - } + private function formatError($type, $message) + { + $this->inner.= $this->getTestName() . " " . $type . "\n"; + $this->inner.= $message . "\n"; + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php index 35077210..8efcbb63 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: b9fbde1e1a21cccbcf6c3bdc29765cf0cf681e31 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -19,144 +19,143 @@ * <http://phing.info>. */ -//require_once 'simpletest/scorer.php'; +require_once 'simpletest/scorer.php'; require_once 'phing/system/io/Writer.php'; /** * This abstract class describes classes that format the results of a SimpleTest testrun. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestResultFormatter.php 58 2006-04-28 14:41:04Z mrook $ - * @package phing.tasks.ext.phpunit2 + * @author Michiel Rook <mrook@php.net> + * @version $Id: b9fbde1e1a21cccbcf6c3bdc29765cf0cf681e31 $ + * @package phing.tasks.ext.simpletest * @since 2.2.0 */ abstract class SimpleTestResultFormatter extends SimpleReporter { - protected $out = NULL; - - protected $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; - } - } + 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; + } + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php index a2fafb0a..e0a78f11 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestSummaryResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: cd15496bfbce39bfd20fe17d52f9348848df0706 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,31 +24,30 @@ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php'; /** * Prints short summary output of the test to Phing's logging system. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestSummaryResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: cd15496bfbce39bfd20fe17d52f9348848df0706 $ * @package phing.tasks.ext.simpletest * @since 2.2.0 */ class SimpleTestSummaryResultFormatter extends SimpleTestResultFormatter { - function paintCaseEnd($test_name) - { - parent::paintCaseEnd($test_name); + function paintCaseEnd($test_name) + { + parent::paintCaseEnd($test_name); + + /* Only count suites where more than one test was run */ + if ($this->getRunCount()) + { + $sb.= "Tests run: " . $this->getRunCount(); + $sb.= ", Failures: " . $this->getFailureCount(); + $sb.= ", Errors: " . $this->getErrorCount(); + $sb.= ", Time elapsed: " . $this->getElapsedTime(); + $sb.= " sec\n"; - /* Only count suites where more than one test was run */ - if ($this->getRunCount()) - { - $sb= "Tests run: " . $this->getRunCount(); - $sb.= ", Failures: " . $this->getFailureCount(); - $sb.= ", Errors: " . $this->getErrorCount(); - $sb.= ", Time elapsed: " . $this->getElapsedTime(); - $sb.= " sec\n"; - - if ($this->out != NULL) - { - $this->out->write($sb); - } - } - } + if ($this->out != NULL) + { + $this->out->write($sb); + } + } + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php index e32c31c6..8082e1ee 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestTask.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: d53b946f773798618069fe162d47ac5f6643662a $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,208 +27,238 @@ require_once 'phing/util/LogWriter.php'; /** * Runs SimpleTest tests. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestTask.php 58 2006-04-28 14:41:04Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: d53b946f773798618069fe162d47ac5f6643662a $ * @package phing.tasks.ext.simpletest * @since 2.2.0 */ class SimpleTestTask extends Task { - private $formatters = array(); - private $haltonerror = false; - private $haltonfailure = false; - private $failureproperty; - private $errorproperty; - private $printsummary = false; - private $testfailed = false; - private $filesets=array(); - - /** - * 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() { - - if (!class_exists('SimpleReporter')) { - throw new BuildException("SimpleTestTask depends on SimpleTest package being installed.", $this->getLocation()); - } - require_once 'phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php'; - require_once 'phing/tasks/ext/simpletest/SimpleTestFormatterElement.php'; - } - - function 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); - } + private $formatters = array(); + private $haltonerror = false; + private $haltonfailure = false; + private $failureproperty; + private $errorproperty; + private $printsummary = false; + private $testfailed = false; + private $debug = false; + + /** + * Initialize Task. + * This method includes any necessary SimpleTest libraries and triggers + * appropriate error if they cannot be found. This is not done in header + * because we may want this class to be loaded w/o triggering an error. + */ + function init() { + @include_once 'simpletest/scorer.php'; + + if (!class_exists('SimpleReporter')) { + throw new BuildException("SimpleTestTask depends on SimpleTest package being installed.", $this->getLocation()); + } + + require_once 'simpletest/reporter.php'; + require_once 'simpletest/xml.php'; + require_once 'simpletest/test_case.php'; + require_once 'phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php'; + require_once 'phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php'; + require_once 'phing/tasks/ext/simpletest/SimpleTestFormatterElement.php'; + } + + function setFailureproperty($value) + { + $this->failureproperty = $value; + } + + function setErrorproperty($value) + { + $this->errorproperty = $value; + } + + function setHaltonerror($value) + { + $this->haltonerror = $value; + } + + function setHaltonfailure($value) + { + $this->haltonfailure = $value; + } + + function setPrintsummary($printsummary) + { + $this->printsummary = $printsummary; + } + + public function setDebug($debug) + { + $this->debug = $debug; + } + + public function getDebug() + { + return $this->debug; + } + + /** + * Add a new formatter to all tests of this task. + * + * @param SimpleTestFormatterElement formatter element + */ + function addFormatter(SimpleTestFormatterElement $fe) + { + $this->formatters[] = $fe; + } + + /** + * 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() + { + $suite= new TestSuite(); + + $filenames = $this->getFilenames(); + + foreach ($filenames as $testfile) + { + $suite->addFile($testfile); + } + + if ($this->debug) + { + $fe = new SimpleTestFormatterElement(); + $fe->setType('debug'); + $fe->setUseFile(false); + $this->formatters[] = $fe; + } + + if ($this->printsummary) + { + $fe = new SimpleTestFormatterElement(); + $fe->setType('summary'); + $fe->setUseFile(false); + $this->formatters[] = $fe; + } + + foreach ($this->formatters as $fe) + { + $formatter = $fe->getFormatter(); + $formatter->setProject($this->getProject()); + + 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($suite); + + if ($this->testfailed && $this->formatters[0]->getFormatter() instanceof SimpleTestDebugResultFormatter ) + { + $this->getDefaultOutput()->write("Failed tests: "); + $this->formatters[0]->getFormatter()->printFailingTests(); + } + + if ($this->testfailed) + { + throw new BuildException("One or more tests failed"); + } + } + + private function execute($suite) + { + $counter = new SimpleTestCountResultFormatter(); + $reporter = new MultipleReporter(); + $reporter->attachReporter($counter); + + foreach ($this->formatters as $fe) + { + // SimpleTest 1.0.1 workaround + $formatterList[] = $fe->getFormatter(); + + $reporter->attachReporter(end($formatterList)); + } + + $suite->run($reporter); + + $retcode = $counter->getRetCode(); + + if ($retcode == SimpleTestCountResultFormatter::ERRORS) + { + if ($this->errorproperty) + { + $this->project->setNewProperty($this->errorproperty, true); + } + + if ($this->haltonerror) + { + $this->testfailed = true; + } + } + elseif ($retcode == SimpleTestCountResultFormatter::FAILURES) + { + if ($this->failureproperty) + { + $this->project->setNewProperty($this->failureproperty, true); + } + + if ($this->haltonfailure) + { + $this->testfailed = true; + } + } + } + + private function getDefaultOutput() + { + return new LogWriter($this); + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php index 66c4ccd8..5ffa668b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php +++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 03b9f976a961a2688d51c9429087a98c31326f42 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,135 +20,159 @@ */ require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php'; +require_once 'simpletest/xml.php'; /** * Prints plain text output of the test to a specified Writer. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 03b9f976a961a2688d51c9429087a98c31326f42 $ * @package phing.tasks.ext.simpletest * @since 2.2.0 */ class SimpleTestXmlResultFormatter extends SimpleTestResultFormatter { - private $results=array(); - private $currentSuite; - private $currentTest; - private $methodCounts=0; - private $methodTime=0; + /** + * @var XmlReporter + */ + private $logger = NULL; + + private $xmlData = ""; - function paintFooter($test_name) - { - if($test_name=='GroupTest') - $this->printXml($test_name); + function __construct() + { + $this->logger = new XmlReporter(); + } + + function getExtension() + { + return ".xml"; + } + + function getPreferredOutfile() + { + return "testsuites"; + } + + private function captureStart() + { + ob_start(); + } + + private function captureStop() + { + $this->xmlData .= ob_get_contents(); + ob_end_clean(); } - protected function printXml($test_name) - { - $suites = $this->printXmlSuites($this->results); -$content = <<<EOD -<?xml version="1.0" encoding="UTF-8"?> -<testsuites total="{$this->getRunCount()}" name="{$test_name}"> -$suites -</testsuites> -EOD; - $this->out->write($content); - } + function paintGroupStart($test_name, $size) + { + parent::paintGroupStart($test_name, $size); + + $this->captureStart(); + $this->logger->paintGroupStart($test_name, $size); + $this->captureStop(); + } + + function paintGroupEnd($test_name) + { + parent::paintGroupEnd($test_name); + + $this->captureStart(); + $this->logger->paintGroupEnd($test_name); + $this->captureStop(); - protected function printXmlSuites($results) - { - $contents = ''; - foreach($results as $suiteName => $suite) - { - $tests = $this->printXmlTests($suite['tests'],$suiteName); -$contents .= <<<EOD -<testsuite name="{$suiteName}" tests="{$suite['total']}" failures="{$suite['failures']}" errors="{$suite['errors']}" time="{$suite['time']}"> - $tests -</testsuite> -EOD; - } - return $contents; - } + if (count($this->_test_stack) == 0) + { + if ($this->out) + { + $this->out->write($this->xmlData); + $this->out->close(); + } + } + } - protected function printXmlTests($tests,$suiteName) - { - $contents = ''; - foreach($tests as $name => $result) - { - if(count($result['results'])==0) - { - $contents .= <<<EOD -<testcase name="{$name}" class="{$suiteName}" result="success" time="{$result['time']}"/> -EOD; - } - else - { - $type = strtolower($result['results']['type']); - $message = htmlspecialchars($result['results']['message']); -$contents .= <<<EOD -<testcase name="{$name}" class="{$suiteName}" result="{$type}" time="{$result['time']}"> - <{$type}>$message</{$type}> -</testcase> -EOD; - } - } - return $contents; - } + function paintCaseStart($test_name) + { + $this->captureStart(); + $this->logger->paintCaseStart($test_name); + $this->captureStop(); + } + + function paintCaseEnd($test_name) + { + $this->captureStart(); + $this->logger->paintCaseEnd($test_name); + $this->captureStop(); + } - function paintCaseStart($test_name) - { - parent::paintCaseStart($test_name); - $this->results[$test_name] = array('tests'=>array()); - $this->currentSuite=$test_name; - $this->methodCounts=0; - } + function paintMethodStart($test_name) + { + $this->captureStart(); + $this->logger->paintMethodStart($test_name); + $this->captureStop(); + } + + function paintMethodEnd($test_name) + { + $this->captureStart(); + $this->logger->paintMethodEnd($test_name); + $this->captureStop(); + } - function paintCaseEnd($test_name) - { - parent::paintCaseEnd($test_name); - $details = array( - 'total' => $this->methodCounts, - 'failures' => $this->getFailureCount(), - 'errors' => $this->getErrorCount(), - 'time' => $this->getElapsedTime()); + function paintPass($message) + { + $this->captureStart(); + $this->logger->paintPass($message); + $this->captureStop(); + } + + function paintError($message) + { + $this->captureStart(); + $this->logger->paintError($message); + $this->captureStop(); + } - $this->results[$test_name] = array_merge($this->results[$test_name],$details); - } + function paintFail($message) + { + $this->captureStart(); + $this->logger->paintFail($message); + $this->captureStop(); + } - function paintMethodStart($test_name) - { - $this->currentTest=$test_name; - parent::paintMethodStart($test_name); - $this->results[$this->currentSuite]['tests'][$test_name]['results'] = array(); - $this->methodCounts++; - $this->methodTime = new Timer(); - $this->methodTime->start(); - } + function paintException($exception) + { + $this->captureStart(); + $this->logger->paintException($exception); + $this->captureStop(); + } - function paintMethodEnd($test_name) - { - parent::paintMethodEnd($test_name); - $this->methodTime->stop(); - $this->results[$this->currentSuite]['tests'][$test_name]['time'] = $this->methodTime->getElapsedTime(); - } + function paintSkip($message) + { + $this->captureStart(); + $this->logger->paintSkip($message); + $this->captureStop(); + } - function paintError($message) - { - parent::paintError($message); - $this->formatError("ERROR", $message); - } + function paintMessage($message) + { + $this->captureStart(); + $this->logger->paintMessage($message); + $this->captureStop(); + } - function paintFail($message) - { - parent::paintFail($message); - $this->formatError("FAILED", $message); - } + function paintFormattedMessage($message) + { + $this->captureStart(); + $this->logger->paintFormattedMessage($message); + $this->captureStop(); + } - private function formatError($type, $message) - { - $result = array('type'=>$type, 'message' => $message); - $this->results[$this->currentSuite]['tests'][$this->currentTest]['results'] = - $result; - } + function paintSignal($type, $payload) + { + $this->captureStart(); + $this->logger->paintSignal($type, $payload); + $this->captureStop(); + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php index 55c695cf..ed9cb276 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: SvnBaseTask.php 38 2006-03-09 14:05:11Z mrook $ + * $Id: b6c644f650a69cad32ced1d030685a7a7a46251c $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,159 +22,326 @@ include_once 'phing/Task.php'; /** - * Send a message by mail() + * Base class for Subversion tasks * - * <mail to="user@example.org" subject="build complete">The build process is a success...</mail> - * - * @author Francois Harvey at SecuriWeb (http://www.securiweb.net) - * @version $Id: SvnBaseTask.php 38 2006-03-09 14:05:11Z mrook $ - * @package phing.tasks.ext + * @author Michiel Rook <mrook@php.net> + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @version $Id: b6c644f650a69cad32ced1d030685a7a7a46251c $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.2.0 */ abstract class SvnBaseTask extends Task { - private $workingCopy = ""; - - private $repositoryUrl = ""; - - private $svnPath = "/usr/bin/svn"; - - private $svn = NULL; - - private $mode = ""; - - private $svnArgs = array(); + private $workingCopy = ""; + + private $repositoryUrl = ""; + + private $svnPath = "/usr/bin/svn"; + + private $svn = NULL; + + private $mode = ""; + + private $svnArgs = array(); + + private $svnSwitches = array(); - /** - * Initialize Task. - * This method includes any necessary SVN libraries and triggers - * appropriate error if they cannot be found. This is not done in header - * because we may want this class to be loaded w/o triggering an error. - */ - function init() { - include_once 'VersionControl/SVN.php'; - if (!class_exists('VersionControl_SVN')) { - throw new Exception("SvnLastRevisionTask depends on PEAR VersionControl_SVN package being installed."); - } - } + private $toDir = ""; + + protected $fetchMode = VERSIONCONTROL_SVN_FETCHMODE_ASSOC; - /** - * Sets the path to the workingcopy - */ - function setWorkingCopy($workingCopy) - { - $this->workingCopy = $workingCopy; - } + /** + * Initialize Task. + * This method includes any necessary SVN libraries and triggers + * appropriate error if they cannot be found. This is not done in header + * because we may want this class to be loaded w/o triggering an error. + */ + function init() { + include_once 'VersionControl/SVN.php'; + if (!class_exists('VersionControl_SVN')) { + throw new Exception("The SVN tasks depend on PEAR VersionControl_SVN package being installed."); + } + } - /** - * Returns the path to the workingcopy - */ - function getWorkingCopy() - { - return $this->workingCopy; - } + /** + * Sets the path to the workingcopy + */ + function setWorkingCopy($workingCopy) + { + $this->workingCopy = $workingCopy; + } - /** - * Sets the path/URI to the repository - */ - function setRepositoryUrl($repositoryUrl) - { - $this->repositoryUrl = $repositoryUrl; - } + /** + * Returns the path to the workingcopy + */ + function getWorkingCopy() + { + return $this->workingCopy; + } - /** - * Returns the path/URI to the repository - */ - function getRepositoryUrl() - { - return $this->repositoryUrl; - } + /** + * Sets the path/URI to the repository + */ + function setRepositoryUrl($repositoryUrl) + { + $this->repositoryUrl = $repositoryUrl; + } - /** - * Sets the path to the SVN executable - */ - function setSvnPath($svnPath) - { - $this->svnPath = $svnPath; - } + /** + * Returns the path/URI to the repository + */ + function getRepositoryUrl() + { + return $this->repositoryUrl; + } + /** + * Sets the path to the SVN executable + */ + function setSvnPath($svnPath) + { + $this->svnPath = $svnPath; + } + + /** + * Returns the path to the SVN executable + */ + function getSvnPath() + { + return $this->svnPath; + } + + // + // Args + // + + /** + * Sets the path to export/checkout to + */ + function setToDir($toDir) + { + $this->toDir = $toDir; + } + + /** + * Returns the path to export/checkout to + */ + function getToDir() + { + return $this->toDir; + } + + // + // Switches + // + + /** + * Sets the force switch + */ + function setForce($value) + { + $this->svnSwitches['force'] = $value; + } + + /** + * Returns the force switch + */ + function getForce() + { + return isset( $this->svnSwitches['force'] ) ? $this->svnSwitches['force'] : ''; + } + + /** + * Sets the username of the user to export + */ + function setUsername($value) + { + $this->svnSwitches['username'] = $value; + } + + /** + * Returns the username + */ + function getUsername() + { + return isset( $this->svnSwitches['username'] ) ? $this->svnSwitches['username'] : ''; + } + + /** + * Sets the password of the user to export + */ + function setPassword($value) + { + $this->svnSwitches['password'] = $value; + } + + /** + * Returns the password + */ + function getPassword() + { + return isset( $this->svnSwitches['password'] ) ? $this->svnSwitches['password'] : ''; + } + + /** + * Sets the no-auth-cache switch + */ + function setNoCache($value) + { + $this->svnSwitches['no-auth-cache'] = $value; + } + + /** + * Returns the no-auth-cache switch + */ + function getNoCache() + { + return isset( $this->svnSwitches['no-auth-cache'] ) ? $this->svnSwitches['no-auth-cache'] : ''; + } + + /** + * Sets the non-recursive switch + */ + function setRecursive($value) + { + $this->svnSwitches['non-recursive'] = is_bool($value) ? !$value : true; + } + + /** + * Returns the non-recursive switch + */ + function getRecursive() + { + return isset( $this->svnSwitches['non-recursive'] ) ? !$this->svnSwitches['non-recursive'] : true; + } + + /** + * Sets the ignore-externals switch + */ + function setIgnoreExternals($value) + { + $this->svnSwitches['ignore-externals'] = $value; + } + + /** + * Returns the ignore-externals switch + */ + function getIgnoreExternals() + { + return isset( $this->svnSwitches['ignore-externals'] ) ? $this->svnSwitches['ignore-externals'] : ''; + } + /** - * 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']); - } - } - } + * Sets the trust-server-cert switch + */ + public function setTrustServerCert($value) + { + $this->svnSwitches['trust-server-cert'] = $value; + } + + /** + * Returns the trust-server-cert switch + */ + public function getTrustServerCert() + { + return isset($this->svnSwitches['trust-server-cert']) ? $this->svnSwitches['trust-server-cert'] : ''; + } + + /** + * Creates a VersionControl_SVN class based on $mode + * + * @param string The SVN mode to use (info, export, checkout, ...) + * @throws BuildException + */ + protected function setup($mode) + { + $this->mode = $mode; + + // Set up runtime options. Will be passed to all + // subclasses. + $options = array('fetchmode' => $this->fetchMode, 'svn_path' => $this->getSvnPath()); + + // Pass array of subcommands we need to factory + $this->svn = VersionControl_SVN::factory($mode, $options); + + $this->svn->use_escapeshellcmd = false; + + if (!empty($this->repositoryUrl)) + { + $this->svnArgs = array($this->repositoryUrl); + } + else + if (!empty($this->workingCopy)) + { + if (is_dir($this->workingCopy)) + { + if (in_array(".svn", scandir($this->workingCopy))) + { + $this->svnArgs = array($this->workingCopy); + } + else + { + throw new BuildException("'".$this->workingCopy."' doesn't seem to be a working copy"); + } + } + else + if ($mode=='info' ) + { + if (is_file($this->workingCopy)) + { + $this->svnArgs = array($this->workingCopy); + } + else + { + throw new BuildException("'".$this->workingCopy."' is not a directory nor a file"); + } + } + else + { + throw new BuildException("'".$this->workingCopy."' is not a directory"); + } + } + } + + /** + * Executes the constructed VersionControl_SVN instance + * + * @param array Additional arguments to pass to SVN. + * @param array Switches to pass to SVN. + * @return string Output generated by SVN. + */ + protected function run($args = array(), $switches = array()) + { + $svnstack = PEAR_ErrorStack::singleton('VersionControl_SVN'); + + $tempArgs = $this->svnArgs; + + $tempArgs = array_merge($tempArgs, $args); + + $tempSwitches = $this->svnSwitches; + + $tempSwitches = array_merge($tempSwitches, $switches); + + if ($output = $this->svn->run($tempArgs, $tempSwitches)) + { + return $output; + } + else + { + if (count($errs = $svnstack->getErrors())) + { + $err = current($errs); + + $errorMessage = $err['message']; + + if (isset($err['params']['errstr'])) { + $errorMessage = $err['params']['errstr']; + } + + throw new BuildException("Failed to run the 'svn " . $this->mode . "' command: " . $errorMessage); + } + } + } } -?>
\ No newline at end of file + diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCheckoutTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCheckoutTask.php new file mode 100644 index 00000000..76dc976a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCheckoutTask.php @@ -0,0 +1,67 @@ +<?php +/** + * $Id: f8844430c9e30d1c603452d8763fbd1114d80051 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Checks out a repository to a local directory + * + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @version $Id: f8844430c9e30d1c603452d8763fbd1114d80051 $ + * @package phing.tasks.ext.svn + * @since 2.3.0 + */ +class SvnCheckoutTask extends SvnBaseTask +{ + /** + * Which Revision to Export + * + * @todo check if version_control_svn supports constants + * + * @var string + */ + private $revision = 'HEAD'; + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('checkout'); + + $this->log("Checking out SVN repository to '" . $this->getToDir() . "'". ($this->revision=='HEAD'?'':" (revision: {$this->revision})")); + + // revision + $switches = array( + 'r' => $this->revision, + ); + + $this->run(array($this->getToDir()), $switches); + } + + public function setRevision($revision) + { + $this->revision = $revision; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCommitTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCommitTask.php new file mode 100644 index 00000000..7eb1ce7a --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCommitTask.php @@ -0,0 +1,113 @@ +<?php +/** + * $Id: 6fdb36b57778f5c0cd46110fd36c8c261ced0e86 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Commits changes in a local working copy to the repository + * + * @author Johan Persson <johanp@aditus.nu> + * @version $Id: 6fdb36b57778f5c0cd46110fd36c8c261ced0e86 $ + * @package phing.tasks.ext.svn + * @since 2.4.0 + */ +class SvnCommitTask extends SvnBaseTask +{ + /** + * Commit message + */ + private $message = ''; + + /** + * Property name where we store the revision number of the just + * commited version. + */ + private $propertyName = "svn.committedrevision"; + + /** + * Sets the commit message + */ + function setMessage($message) + { + $this->message = $message; + } + + /** + * Gets the commit message + */ + function getMessage() + { + return $this->message; + } + + /** + * Sets the name of the property to use for returned revision + */ + function setPropertyName($propertyName) + { + $this->propertyName = $propertyName; + } + + /** + * Returns the name of the property to use for returned revision + */ + function getPropertyName() + { + return $this->propertyName; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + if( trim($this->message) === '' ) + { + throw new BuildException('SVN Commit message can not be empty.'); + } + + $this->setup('commit'); + + $this->log("Commiting SVN working copy at '" . $this->getWorkingCopy() . "' with message '".$this->GetMessage()."'"); + + $output = $this->run(array(), array('message' => $this->GetMessage() ) ); + + if( preg_match('/[\s]*Committed revision[\s]+([\d]+)/', $output, $matches) ) + { + $this->project->setProperty($this->getPropertyName(), $matches[1]); + } + else + { + /** + * If no new revision was committed set revision to "empty". Remember that + * this is not necessarily an error. It could be that the specified working + * copy is identical to to the copy in the repository and in that case + * there will be no update and no new revision number. + */ + $this->project->setProperty($this->getPropertyName(), '' ); + } + + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCopyTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCopyTask.php new file mode 100644 index 00000000..c1eb7089 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnCopyTask.php @@ -0,0 +1,70 @@ +<?php +/** + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Copies a repository from the repository url to another + * + * @version $Id: 6f39598901c83ecaf8e7fcb9d4065f70b38324cb $ + * @package phing.tasks.ext.svn + * @since 2.3.0 + */ +class SvnCopyTask extends SvnBaseTask +{ + private $message = ""; + + /** + * Sets the message + */ + function setMessage($message) + { + $this->message = $message; + } + + /** + * Gets the message + */ + function getMessage() + { + return $this->message; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('copy'); + + $this->log("Copying SVN repository from '" . $this->getRepositoryUrl() . "' to '" . $this->getToDir() . "'"); + + $options = array(); + + if (strlen($this->getMessage()) > 0) { + $options['message'] = $this->getMessage(); + } + + $this->run(array($this->getToDir()), $options); + } +} + diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php index 7cb6c897..e0b2e78b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SvnExportTask.php 37 2006-03-09 14:04:22Z mrook $ + * $Id: ca2d150a53b870fe410f5434f4d500decc7cda73 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,45 +24,47 @@ require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; /** * Exports/checks out a repository to a local directory + * with authentication * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SvnExportTask.php 37 2006-03-09 14:04:22Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @version $Id: ca2d150a53b870fe410f5434f4d500decc7cda73 $ * @package phing.tasks.ext.svn - * @see VersionControl_SVN - * @since 2.1.0 + * @since 2.2.0 */ class SvnExportTask extends SvnBaseTask { - private $toDir = ""; + /** + * Which Revision to Export + * + * @todo check if version_control_svn supports constants + * + * @var string + */ + private $revision = 'HEAD'; - /** - * Sets the path to export/checkout to - */ - function setToDir($toDir) - { - $this->toDir = $toDir; - } + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('export'); + + $this->log("Exporting SVN repository to '" . $this->getToDir() . "'"); - /** - * Returns the path to export/checkout to - */ - function getToDir() - { - return $this->toDir; - } + $switches = array(); - /** - * The main entry point - * - * @throws BuildException - */ - function main() - { - $this->setup('export'); - - $this->log("Exporting SVN repository to '" . $this->toDir . "'"); - - $this->run(array($this->toDir)); - } + if (!empty($this->revision)) { + $switches['r'] = $this->revision; + } + + $this->run(array($this->getToDir()), $switches); + } + + public function setRevision($revision) + { + $this->revision = $revision; + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnInfoTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnInfoTask.php new file mode 100644 index 00000000..68111d74 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnInfoTask.php @@ -0,0 +1,112 @@ +<?php +/** + * $Id: 36ffb2ececed4c83c9ca7ad3674b3fa11074f2a5 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Parses the output of 'svn info --xml' and + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 36ffb2ececed4c83c9ca7ad3674b3fa11074f2a5 $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.4.9 + */ +class SvnInfoTask extends SvnBaseTask +{ + private $propertyName = "svn.info"; + + private $element = 'url'; + private $subElement = null; + + /** + * Sets the name of the property to use + */ + public function setPropertyName($propertyName) + { + $this->propertyName = $propertyName; + } + + /** + * Returns the name of the property to use + */ + public function getPropertyName() + { + return $this->propertyName; + } + + /** + * Sets the name of the xml element to use + */ + public function setElement($element) + { + $this->element = $element; + } + + /** + * Returns the name of the xml element to use + */ + public function getElement() + { + return $this->element; + } + + /** + * Sets the name of the xml sub element to use + */ + public function setSubElement($subElement) + { + $this->subElement = $subElement; + } + + /** + * Returns the name of the xml sub element to use + */ + public function getSubElement() + { + return $this->subElement; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('info'); + + $output = $this->run(array('--xml', '--incremental')); + + if ($xmlObj = @simplexml_load_string($output)) { + $object = $xmlObj->{$this->element}; + + if (!empty($this->subElement)) { + $object = $object->{$this->subElement}; + } + + $this->project->setProperty($this->getPropertyName(), (string) $object); + } else { + throw new BuildException("Failed to parse the output of 'svn info --xml'."); + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php index e45ac50c..7305c27b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php @@ -1,6 +1,6 @@ <?php /** - * $Id: SvnLastRevisionTask.php 37 2006-03-09 14:04:22Z mrook $ + * $Id: 74d61db8c11978a2383f071b7ab7ed0afae6953c $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,51 +25,96 @@ require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; /** * Stores the number of the last revision of a workingcopy in a property * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Id: SvnLastRevisionTask.php 37 2006-03-09 14:04:22Z mrook $ + * @author Michiel Rook <mrook@php.net> + * @version $Id: 74d61db8c11978a2383f071b7ab7ed0afae6953c $ * @package phing.tasks.ext.svn * @see VersionControl_SVN * @since 2.1.0 */ class SvnLastRevisionTask extends SvnBaseTask { - private $propertyName = "svn.lastrevision"; + private $propertyName = "svn.lastrevision"; + private $forceCompatible = false; + private $lastChanged = false; - /** - * Sets the name of the property to use - */ - function setPropertyName($propertyName) - { - $this->propertyName = $propertyName; - } + /** + * Sets the name of the property to use + */ + function setPropertyName($propertyName) + { + $this->propertyName = $propertyName; + } - /** - * Returns the name of the property to use - */ - function getPropertyName() - { - return $this->propertyName; - } + /** + * Returns the name of the property to use + */ + function getPropertyName() + { + return $this->propertyName; + } + + /** + * Sets whether to force compatibility with older SVN versions (< 1.2) + */ + public function setForceCompatible($force) + { + $this->forceCompatible = (bool) $force; + } + + /** + * Sets whether to retrieve the last changed revision + */ + public function setLastChanged($lastChanged) + { + $this->lastChanged = (bool) $lastChanged; + } - /** - * The main entry point - * - * @throws BuildException - */ - function main() - { - $this->setup('info'); - - $output = $this->run(); - - if (preg_match('/Rev:[\s]+([\d]+)/', $output, $matches)) - { - $this->project->setProperty($this->getPropertyName(), $matches[1]); - } - else - { - throw new BuildException("Failed to parse the output of 'svn info'."); - } - } + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('info'); + + if ($this->forceCompatible) + { + $output = $this->run(); + + if ($this->lastChanged) { + $found = preg_match('/Rev:[\s]+([\d]+)/', $output, $matches); + } else { + $found = preg_match('/Last Changed Rev:[\s]+([\d]+)/', $output, $matches); + } + + if ($found) + { + $this->project->setProperty($this->getPropertyName(), $matches[1]); + } + else + { + throw new BuildException("Failed to parse the output of 'svn info'."); + } + } + else + { + $output = $this->run(array('--xml')); + + if ($xmlObj = @simplexml_load_string($output)) + { + if ($this->lastChanged) { + $lastRevision = (int)$xmlObj->entry->commit['revision']; + } else { + $lastRevision = (int)$xmlObj->entry['revision']; + } + + $this->project->setProperty($this->getPropertyName(), $lastRevision); + } + else + { + throw new BuildException("Failed to parse the output of 'svn info --xml'."); + } + } + } } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnListTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnListTask.php new file mode 100755 index 00000000..63d8445c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnListTask.php @@ -0,0 +1,128 @@ +<?php +/** + * $Id: 5dfcc23bc58efaad0eb11ef4964bcd7be0fb99e9 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Stores the output of a list command on a workingcopy or repositoryurl in a property. + * This stems from the SvnLastRevisionTask. + * + * @author Anton Stöckl <anton@stoeckl.de> + * @author Michiel Rook <mrook@php.net> (SvnLastRevisionTask) + * @version $Id: 5dfcc23bc58efaad0eb11ef4964bcd7be0fb99e9 $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.1.0 + */ +class SvnListTask extends SvnBaseTask +{ + private $propertyName = "svn.list"; + private $forceCompatible = true; + private $limit = null; + private $orderDescending = false; + + /** + * Sets the name of the property to use + */ + function setPropertyName($propertyName) + { + $this->propertyName = $propertyName; + } + + /** + * Returns the name of the property to use + */ + function getPropertyName() + { + return $this->propertyName; + } + + /** + * Sets whether to force compatibility with older SVN versions (< 1.2) + */ + public function setForceCompatible($force) + { + //$this->forceCompatible = (bool) $force; + // see below, we need this to be true as xml mode does not work + } + + /** + * Sets the max num of tags to display + */ + function setLimit($limit) + { + $this->limit = (int) $limit; + } + + /** + * Sets whether to sort tags in descending order + */ + function setOrderDescending($orderDescending) + { + $this->orderDescending = (bool) $orderDescending; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('list'); + + if ($this->forceCompatible) { + $output = $this->run(array('--verbose')); + $result = null; + + $lines = $output['.']['name']; + + if ($this->orderDescending) { + $lines = array_reverse($lines); + } + + $count = 0; + foreach ($lines as $line) { + if ($this->limit > 0 && $count >= $this->limit) { + break; + } + if (preg_match('@\s+(\d+)\s+(\S+)\s+(\S+ \S+ \S+)\s+(\S+)@', $line, $matches)) { + if ($matches[4] == '.') { + continue; + } + $result .= (!empty($result)) ? "\n" : ''; + $result .= $matches[1] . ' | ' . $matches[2] . ' | ' . $matches[3] . ' | ' . $matches[4]; + $count++; + } + } + + if (!empty($result)) { + $this->project->setProperty($this->getPropertyName(), $result); + } else { + throw new BuildException("Failed to parse the output of 'svn list --verbose'."); + } + } else { + // this is not possible at the moment as SvnBaseTask always uses fetchmode ASSOC + // which transfers everything into nasty assoc array instead of xml + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLogTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLogTask.php new file mode 100755 index 00000000..7f5c4025 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLogTask.php @@ -0,0 +1,108 @@ +<?php +/** + * $Id: fc8bc4cf4caa997c13dd66095997fa5478c47959 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Stores the output of a log command on a workingcopy or repositoryurl in a property. + * This stems from the SvnLastRevisionTask. + * + * @author Anton Stöckl <anton@stoeckl.de> + * @author Michiel Rook <mrook@php.net> (SvnLastRevisionTask) + * @version $Id: fc8bc4cf4caa997c13dd66095997fa5478c47959 $ + * @package phing.tasks.ext.svn + * @see VersionControl_SVN + * @since 2.1.0 + */ +class SvnLogTask extends SvnBaseTask +{ + private $propertyName = "svn.log"; + private $forceCompatible = true; + private $limit = null; + + /** + * Sets the name of the property to use + */ + function setPropertyName($propertyName) + { + $this->propertyName = $propertyName; + } + + /** + * Returns the name of the property to use + */ + function getPropertyName() + { + return $this->propertyName; + } + + /** + * Sets whether to force compatibility with older SVN versions (< 1.2) + */ + public function setForceCompatible($force) + { + //$this->forceCompatible = (bool) $force; + // see below, we need this to be true as xml mode does not work + } + + /** + * Sets the max num of log entries to get from svn + */ + function setLimit($limit) + { + $this->limit = (int) $limit; + } + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('log'); + + $switches= array(); + if ($this->limit > 0) { + $switches['limit'] = $this->limit; + } + + if ($this->forceCompatible) { + $output = $this->run(array(), $switches); + $result = null; + + foreach ($output as $line) { + $result .= (!empty($result)) ? "\n" : ''; + $result .= "{$line['REVISION']} | {$line['AUTHOR']} | {$line['DATE']} | {$line['MSG']}"; + } + + if (!empty($result)) { + $this->project->setProperty($this->getPropertyName(), $result); + } else { + throw new BuildException("Failed to parse the output of 'svn log'."); + } + } else { + // this is not possible at the moment as SvnBaseTask always uses fetchmode ASSOC + // which transfers everything into nasty assoc array instead of xml + } + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnSwitchTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnSwitchTask.php new file mode 100644 index 00000000..cb6c5ca4 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnSwitchTask.php @@ -0,0 +1,73 @@ +<?php +/** + * $Id: 2beb14d928ee47f36cceb9467b4a2ac9d2c81ef4 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Switches a repository at a given local directory to a different location + * + * @author Dom Udall <dom.udall@clock.co.uk> + * @version $Id: 2beb14d928ee47f36cceb9467b4a2ac9d2c81ef4 $ + * @package phing.tasks.ext.svn + * @since 2.4.3 + */ +class SvnSwitchTask extends SvnBaseTask +{ + /** + * Which Revision to Export + * + * @todo check if version_control_svn supports constants + * + * @var string + */ + private $revision = 'HEAD'; + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('switch'); + + $this->log("Switching SVN repository at '" . $this->getToDir() . "' to '" . $this->getRepositoryUrl() . "' " + . ($this->getRevision()=='HEAD'?'':" (revision: {$this->getRevision()})")); + + // revision + $switches = array( + 'r' => $this->getRevision(), + ); + + $this->run(array($this->getToDir()), $switches); + } + + public function setRevision($revision) + { + $this->revision = $revision; + } + + public function getRevision() + { + return $this->revision; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnUpdateTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnUpdateTask.php new file mode 100644 index 00000000..c70039fc --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnUpdateTask.php @@ -0,0 +1,67 @@ +<?php +/** + * $Id: 9f5e4de2948b03eb6c9e459b1065bcedd851c025 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/tasks/ext/svn/SvnBaseTask.php'; + +/** + * Updates a repository in local directory + * + * @author Andrew Eddie <andrew.eddie@jamboworks.com> + * @version $Id: 9f5e4de2948b03eb6c9e459b1065bcedd851c025 $ + * @package phing.tasks.ext.svn + * @since 2.3.0 + */ +class SvnUpdateTask extends SvnBaseTask +{ + /** + * Which Revision to Export + * + * @todo check if version_control_svn supports constants + * + * @var string + */ + private $revision = 'HEAD'; + + /** + * The main entry point + * + * @throws BuildException + */ + function main() + { + $this->setup('update'); + + $this->log("Updating SVN repository at '" . $this->getToDir() . "'". ($this->revision=='HEAD'?'':" (revision: {$this->revision})")); + + // revision + $switches = array( + 'r' => $this->revision, + ); + + $this->run(array($this->getToDir()), $switches); + } + + public function setRevision($revision) + { + $this->revision = $revision; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php new file mode 100644 index 00000000..33d2e4e3 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php @@ -0,0 +1,510 @@ +<?php + +/* + * $Id: cdbb2883ab70c650896a465a872b3da30f13eb00 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/tasks/system/MatchingTask.php'; +include_once 'phing/util/SourceFileScanner.php'; +include_once 'phing/mappers/MergeMapper.php'; +include_once 'phing/util/StringHelper.php'; + +/** + * Encodes files using Zeng Guard Encoder + * + * @author Petr Rybak <petr@rynawe.net> + * @version $Id: cdbb2883ab70c650896a465a872b3da30f13eb00 $ + * @package phing.tasks.ext.zendguard + * @since 2.4.3 + */ +class ZendGuardEncodeTask extends MatchingTask +{ + protected $filesets = array(); + protected $encodeCommand; + + + /** + * TASK PROPERTIES + * + * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf + * for more information on how to use ZendGuard + * + */ + /** + * Permanently deletes (see warning below) the original source files specified in the + * SourceInputPath and saves the encoded files in its place. + * This option has no option parameter. + * When this option is use, do not use the output_file parameter. + * + * Warning: + * To avoid permanent loss of non-encoded scripts, make a backup. Deleted files + * cannot be restored or recovered and will be permanently deleted with this option. + * If you are unsure about deleting the source files, use the ––rename-source option + * instead + * + * @var bool + */ + protected $deleteSource = true; + /** + * Move the original source file to <input_file>.<renameSourceExt> and save the encoded file in its + * place. + * + * If specified deleteSource will be automatically disabled. + * + * @var string + */ + protected $renameSourceExt = null; + /** + * Turns short PHP tag (“<?†) recognition either on or off. + * On or off must be specified as an argument when using this option. + * The default, when option is not used in the command-line, is - on + * + * @var bool + */ + protected $shortTags = true; + /** + * Turn ASP tag (“<%†) recognition on/off. (default: off). On or off must be specified + * as an argument when using this option. + * The default, when this option is not used in the command-line, is - off + * + * @var bool + */ + protected $aspTags = false; + /** + * + * Disables the PHP-compatible header that is added to the top of every encoded file + * by default. Encoded files generated with this option will not display a meaningful + * error when loaded by PHP that doesn't have the Zend Optimizer properly installed. + * Using this option saves approximately 1.5KB for every encoded file. Do not use it + * unless disk space constraints are critica + * + * @var bool + */ + protected $noHeader = false; + /** + * If cryptography should be used to encode the source code + * + * @var bool + */ + protected $useCrypto = false; + /** + * Force cooperation with other encoded files only. This option generates files that + * work exclusively with associated encoded files. Associated encoded files are + * those generated by the same company. Files that do not share the same encoded + * company association cannot call these files + * + * @var bool + */ + protected $encodedOnly = false; + /** + * Allow encoding previously encoded files. (NOT recommended!) + * + * @var bool + */ + protected $forceEncode = false; + /** + * Make an encoded file to expire on the given date. Date is in yyyy-mm-dd format. + * + * @var string + */ + protected $expires = null; + /** + * Level of obfuscation. Defaults to 0 (no obfuscation). + * + * @var int + */ + protected $obfuscationLevel = 0; + /** + * Optimization mask. (default value: [+++++++]) + * opt_mask is an integer representing a bit-mask. + * The default value enables all of the optimization passes. + * Each optimization pass of the Zend Optimizer can be turned on or off based on + * the mask entered + * + * @var int + */ + protected $optMask = null; + /** + * Path to the zend encoder binary + * + * @var string + */ + protected $zendEncoderPath = null; + /** + * Path to private key for licensing + * + * @var string + */ + protected $privateKeyPath = null; + /** + * Enable licensing. + * If enabled, productName must be defined. + * + * @var bool + */ + protected $licenseProduct = false; + /** + * If true the ownership, permissions and timestamps + * of the encoded files won't be preserved. + * + * @var bool + */ + protected $ignoreFileModes = false; + /** + * Enable signing + * If enabled, productName must be defined. + * + * @var bool + */ + protected $signProduct = false; + /** + * Product name. Must be defined if licenseProduct + * or signProduct is set to 1 + * + * @var string + */ + protected $productName = null; + /** + * Embed the information in the specified file into the header of the encoded file + * (overrides noHeader) + * + * @var string + */ + protected $prologFile = null; + + /** + * TASK PROPERTIES SETTERS + */ + public function setZendEncoderPath($value) + { + $this->zendEncoderPath = $value; + } + + public function setPrivateKeyPath($value) + { + $this->privateKeyPath = $value; + } + + public function setShortTags($value) + { + $this->shortTags = (bool) $value; + } + + public function setAspTags($value) + { + $this->aspTags = (bool) $value; + } + + public function setDeleteSource($value) + { + $this->shortTags = (bool) $value; + } + + public function setUseCrypto($value) + { + $this->useCrypto = (bool) $value; + } + + public function setObfuscationLevel($value) + { + $this->obfuscationLevel = (int) $value; + } + + public function setLicenseProduct($value) + { + $this->licenseProduct = (bool) $value; + } + + public function setPrologFile($value) + { + $this->prologFile = $value; + } + + public function setSignProduct($value) + { + $this->signProduct = (bool) $value; + } + + public function setForceEncode($value) + { + $this->forceEncode = (bool) $value; + } + + public function setEncodedOnly($value) + { + $this->encodedOnly = (bool) $value; + } + + public function setIgnoreFileModes($value) + { + $this->ignoreFileModes = (bool) $value; + } + + public function setExpires($value) + { + $this->expires = $value; + } + + public function setProductName($value) + { + $this->productName = $value; + } + + public function setOptMask($value) + { + $this->optMask = (int) $value; + } + + public function setRenameSourceExt($value) + { + $this->renameSourceExt = $value; + } + + public function setNoHeader($value) + { + $this->noHeader = (bool) $value; + } + + /** + * Add a new fileset. + * + * @return FileSet + */ + public function createFileSet() + { + $this->fileset = new ZendGuardFileSet(); + $this->filesets[] = $this->fileset; + return $this->fileset; + } + + /** + * Verifies that the configuration is correct + * + * @throws BuildException + */ + protected function verifyConfiguration() + { + // Check that the zend encoder path is specified + if (empty($this->zendEncoderPath)) { + throw new BuildException("Zend Encoder path must be specified"); + } + + // verify that the zend encoder binary exists + if (!file_exists($this->zendEncoderPath)) { + throw new BuildException("Zend Encoder not found on path " . $this->zendEncoderPath); + } + + // if either sign or license is required the private key path needs to be defined + // and the file has to exist and product name has to be specified + if ($this->signProduct || $this->licenseProduct) { + if (empty($this->privateKeyPath)) { + throw new BuildException("Licensing or signing requested but privateKeyPath not provided."); + } + if (!is_readable($this->privateKeyPath)) { + throw new BuildException("Licensing or signing requested but private key path doesn't exist or is unreadable."); + } + if (empty($this->productName)) { + throw new BuildException("Licensing or signing requested but product name not provided."); + } + } + + // verify prolog file exists + if (!empty($this->prologFile)) { + if (!file_exists($this->prologFile)) { + throw new BuildException("The prolog file doesn't exist: " . $this->prologFile); + } + } + } + + /** + * Do the work + * + * @throws BuildException + */ + public function main() + { + $this->verifyConfiguration(); + $this->prepareEncoderCommand(); + + try { + if (empty($this->filesets)) { + throw new BuildException("You must supply nested fileset.", + $this->getLocation()); + } + + $encodedFilesCounter = 0; + + foreach ($this->filesets as $fs) { + /* @var $fs FileSet */ + + /* @var $fsBasedir PhingFile */ + $fsBasedir = $fs->getDir($this->project)->getAbsolutePath(); + + $files = $fs->getFiles($this->project, false); + + foreach ($files as $file) { + $f = new PhingFile($fsBasedir, $file); + + if ($f->isFile()) { + $path = $f->getAbsolutePath(); + + $this->log("Encoding " . $path, Project::MSG_VERBOSE); + $this->encodeFile($path); + + $encodedFilesCounter++; + } + } + } + + $this->log("Encoded files: " . $encodedFilesCounter); + } catch (IOException $ioe) { + $msg = "Problem encoding files: " . $ioe->getMessage(); + throw new BuildException($msg, $ioe, $this->getLocation()); + } + } + + /** + * Prepares the main part of the command that will be + * used to encode the given file(s). + */ + protected function prepareEncoderCommand() + { + $command = $this->zendEncoderPath . " \\\n"; + + if (!empty($this->renameSourceExt)) { + $command .= " --rename-source " . $this->renameSourceExt . " \\\n"; + } elseif ($this->deleteSource) { + // delete source + $command .= " --delete-source \\\n"; + } + + // short tags + $command .= " --short-tags " . (($this->shortTags) ? 'on' : 'off') . " \\\n"; + + // asp tags + $command .= " --asp-tags " . (($this->aspTags) ? 'on' : 'off') . " \\\n"; + + // use crypto + if ($this->useCrypto) { + $command .= " --use-crypto \\\n"; + } + + // ignore file modes + if ($this->ignoreFileModes) { + $command .= " --ignore-file-modes \\\n"; + } + + // force encode + if ($this->forceEncode) { + $command .= " --force-encode \\\n"; + } + + // expires + if (!empty($this->expires)) { + $command .= " --expires " . $this->expires . " \\\n"; + } + + // insert prolog file name or no-header + if (!empty($this->prologFile)) { + $command .= " --prolog-filename " . $this->prologFile . " \\\n"; + } elseif ($this->noHeader) { + // no-header + $command .= " --no-header \\\n"; + } + + // obfuscation level + if ($this->obfuscationLevel > 0) { + $command .= " --obfuscation-level " . $this->obfuscationLevel . " \\\n"; + } + + // encoded only + if ($this->encodedOnly) { + $command .= " --encoded-only \\\n"; + } + + // opt mask + if (null !== $this->optMask) { + $command .= " --optimizations " . $this->optMask . " \\\n"; + } + + // Signing or licensing + if ($this->signProduct) { + $command .= " --sign-product " . $this->productName . " --private-key " . $this->privateKeyPath . " \\\n"; + } elseif ($this->licenseProduct) { + $command .= " --license-product " . $this->productName . " --private-key " . $this->privateKeyPath . " \\\n"; + } + + // add a blank space + $command .= " "; + + $this->encodeCommand = $command; + + } + + /** + * Encodes a file using currently defined Zend Guard settings + * + * @param string $filePath Path to the encoded file + */ + protected function encodeFile($filePath) + { + $command = $this->encodeCommand . $filePath . ' 2>&1'; + + $this->log('Running: ' . $command, Project::MSG_VERBOSE); + + $tmp = exec($command, $output, $return_var); + if ($return_var !== 0) { + throw new BuildException("Encoding failed. \n Msg: " . $tmp . " \n Encode command: " . $command); + } + + return true; + } + +} + +/** + * This is a FileSet with the to specify permissions. + * + * Permissions are currently not implemented by PEAR Archive_Tar, + * but hopefully they will be in the future. + * + * @package phing.tasks.ext.zendguard + */ +class ZendGuardFileSet extends FileSet +{ + private $files = null; + + /** + * Get a list of files and directories specified in the fileset. + * @return array a list of file and directory names, relative to + * the baseDir for the project. + */ + public function getFiles(Project $p, $includeEmpty = true) + { + + if ($this->files === null) { + + $ds = $this->getDirectoryScanner($p); + $this->files = $ds->getIncludedFiles(); + } // if ($this->files===null) + + return $this->files; + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.php b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.php new file mode 100644 index 00000000..2a3f71ca --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.php @@ -0,0 +1,524 @@ +<?php + +/* + * $Id: 96af59b9cbecaf7f146dffab1d0b5a806a56b47f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Produce license files using Zeng Guard. + * The task can produce a license file from the given + * license properties or it can use a template. + * + * @author Petr Rybak <petr@rynawe.net> + * @version $Id: 96af59b9cbecaf7f146dffab1d0b5a806a56b47f $ + * @package phing.tasks.ext.zendguard + * @since 2.4.3 + */ +class ZendGuardLicenseTask extends Task +{ + protected $zendsignCommand; + private $tmpLicensePath; + + /** + * TASK PROPERTIES + * + * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf + * for more information on how to use ZendGuard + * + */ + /** + * Path to Zend Guard zendenc_sign executable + * + * @var string + */ + protected $zendsignPath; + /** + * Path to private key that will be used to sign the license + * + * @var string + */ + protected $privateKeyPath; + /** + * Where to store the signed license file + * + * @var string + */ + protected $outputFile; + /** + * Path to license template. If specified all + * license properties will be ignored and the + * template will be used to generate the file. + * + * @var string + */ + protected $licenseTemplate; + /** + * The name assigned to Product. This must be the same name used when encoding + * the PHP files. + * + * REQUIRED + * + * @var string + */ + protected $productName; + /** + * The Name of the Registered owner of the license. + * + * REQUIRED + * + * @var string + */ + protected $registeredTo; + /** + * Expiration date of the license. Used if the license is issued with a date restriction. + * Possible values: + * - 'Never', '0' or false: the license won't expire + * - A Date in format DD-MM-YYYY to set expiration for that date + * - Relative date supported by the PHP strtotime function (e.g. +1 month) + * + * REQUIRED + * + * @var string + */ + protected $expires; + /** + * Limits the use of the license to IP addresses that fall within specification. Supports + * wildcards for any of the IP place holders, as well as the two types of net masks + * (filters). + * Netmask pair An IP a.b.c.d, and a netmask w.x.y.z. (That is., 10.1.0.0/255.255.0.0), + * where the binary of mask is applied to filter IP addresses. + * ip/nnn (similar to a CIDR specification) This mask consists of nnn high-order 1 bits. + * (That is, 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0). Instead of spelling out + * the bits of the subnet mask, this mask notation is simply listed as the number of 1s + * bits that start the mask. Rather than writing the address and subnet mask as + * 192.60.128.0/255.255.252.0 the network address would be written simply as: + * 192.60.128.0/22 which indicates starting address of the network and number of 1s + * bits (22) in the network portion of the address. The mask in binary is + * (11111111.11111111.11111100.00000000). + * + * OPTIONAL + * + * Example (Wildcard): + * IP-Range = 10.1.*.* + * Example (Net Mask): + * IP-Range = 10.1.0.0/255.255.0.0 + * Example (Net Mask): + * IP-Range = 10.1.0.0/16 + * + * @var string + */ + protected $ipRange; + /** + * Coded string (Zend Host ID) used to lock the license to a specific hardware. The + * Zend Host ID obtained from the machine where the encoded files and license are + * to be installed. The Zend Host ID code can be obtained by using the zendid utility. + * For more details, see Getting the Zend Host ID. + * + * REQUIRED if Hardware-Locked is set equal to YES. + * Meaningless if Hardware-Locked is set equal to NO. + * + * User semicolon to enter more than one Host-ID + * + * Example: + * Host-ID = H:MFM43-Q9CXC-B9EDX-GWYSU;H:MFM43-Q9CXC-B9EDX-GWYTY + * + * @var string + */ + protected $hostID; + /** + * Option that indicates if the license will be locked to a specific machine + * using the Zend Host ID code(s). If set to YES, the Host-ID is required. + * + * OPTIONAL + * + * @var bool + */ + protected $hardwareLocked; + /** + * Semi-colon separated user defined values that will be part of the license. These values + * CANNOT be modified after the license is produced. Modification + * would invalidate the license. + * + * OPTIONAL + * Example: + * Tea=Mint Flavor;Coffee=Arabica + * + * @var string + */ + protected $userDefinedValues; + /** + * Semi-colon separated user defined x-values that will be part of the license. These values + * CAN be modified after the license is produced. Modification + * won't invalidate the license. + * + * OPTIONAL + * Example: + * Tea=Mint Flavor;Coffee=Arabica + * + * @var string + */ + protected $xUserDefinedValues; + + + public function setLicenseTemplate($value) + { + $this->licenseTemplate = $value; + } + + public function setProductName($productName) + { + $this->productName = $productName; + } + + public function setRegisteredTo($registeredTo) + { + $this->registeredTo = $registeredTo; + } + + /** + * Process the expires property. If the value is + * empty (false, '', ...) it will set the value to 'Never' + * Otherwise it will run the value through strtotime so relative + * date and time notation can be used (e.g. +1 month) + * + * @param mixed $expires + * + * @return string + */ + public function setExpires($expires) + { + // process the expires value + if (false === $expires || '0' === $expires || strtolower($expires) == 'never' || '' === $expires) { + $this->expires = 'Never'; + } else { + $time = strtotime($expires); + if (!$time) { + throw new BuildException("Unsupported expires format: " . $expires); + } + $this->expires = date('d-M-Y', $time); + } + } + + public function setIpRange($iprange) + { + $this->ipRange = $iprange; + } + + public function setHostID($hostID) + { + $this->hostID = $hostID; + } + + public function setHardwareLocked($hardwareLocked) + { + $this->hardwareLocked = (bool) $hardwareLocked; + } + + public function setUserDefinedValues($userDefinedValues) + { + $this->userDefinedValues = $userDefinedValues; + } + + public function setXUserDefinedValues($xUserDefinedValues) + { + $this->xUserDefinedValues = $xUserDefinedValues; + } + + public function setZendsignPath($zendsignPath) + { + $this->zendsignPath = $zendsignPath; + } + + public function setPrivateKeyPath($privateKeyPath) + { + $this->privateKeyPath = $privateKeyPath; + } + + public function setOutputFile($outputFile) + { + $this->outputFile = $outputFile; + } + + /** + * Verifies that the configuration is correct + * + * @throws BuildException + */ + protected function verifyConfiguration() + { + // Check that the zend encoder path is specified + if (empty($this->zendsignPath)) { + throw new BuildException("Zendenc_sign path must be specified"); + } + // verify that the zend encoder binary exists + if (!file_exists($this->zendsignPath)) { + throw new BuildException("Zendenc_sign not found on path " . $this->zendsignPath); + } + + // verify that the private key path is defined + if (empty($this->privateKeyPath)) { + throw new BuildException("You must define privateKeyPath."); + } + // verify that the private key file is readable + if (!is_readable($this->privateKeyPath)) { + throw new BuildException("Private key file is not readable: " . $this->privateKeyPath); + } + + // if template is passed, verify that it is readable + if (!empty($this->licenseTemplate)) { + if (!is_readable($this->licenseTemplate)) { + throw new BuildException("License template file is not readable " . $this->licenseTemplate); + } + } + + // check that output file path is defined + if (empty($this->outputFile)) { + throw new BuildException("Path where to store the result file needs to be defined in outputFile property"); + } + + // if license template is NOT provided check that all required parameters are defined + if (empty($this->licenseTemplate)) { + + // check productName + if (empty($this->productName)) { + throw new BuildException("Property must be defined: productName"); + } + + // check expires + if (null === $this->expires) { + throw new BuildException("Property must be defined: expires"); + } + + // check registeredTo + if (empty($this->registeredTo)) { + throw new BuildException("Property must be defined: registeredTo"); + } + + // check hardwareLocked + if (null === $this->hardwareLocked) { + throw new BuildException("Property must be defined: hardwareLocked"); + } + + // if hardwareLocked is set to true, check that Host-ID is set + if ($this->hardwareLocked) { + if (empty($this->hostID)) { + throw new BuildException("If you set hardwareLocked to true hostID must be provided"); + } + } + } + } + + /** + * Do the work + * + * @throws BuildException + */ + public function main() + { + try { + $this->verifyConfiguration(); + + $this->generateLicense(); + } catch (Exception $e) { + // remove the license temp file if it was created + $this->cleanupTmpFiles(); + + throw $e; + } + $this->cleanupTmpFiles(); + } + + /** + * If temporary license file was created during the process + * this will remove it + * + * @return void + */ + private function cleanupTmpFiles() + { + if (!empty($this->tmpLicensePath) && file_exists($this->tmpLicensePath)) { + $this->log("Deleting temporary license template " . $this->tmpLicensePath, Project::MSG_VERBOSE); + + unlink($this->tmpLicensePath); + } + } + + /** + * Prepares and returns the command that will be + * used to create the license. + * + * @return string + */ + protected function prepareSignCommand() + { + $command = $this->zendsignPath; + + // add license path + $command .= ' ' . $this->getLicenseTemplatePath(); + + // add result file path + $command .= ' ' . $this->outputFile; + + // add key path + $command .= ' ' . $this->privateKeyPath; + + + $this->zendsignCommand = $command; + + return $command; + } + + /** + * Checks if the license template path is defined + * and returns it. + * If it the license template path is not defined + * it will generate a temporary template file and + * provide it as a template. + * + * @return string + */ + protected function getLicenseTemplatePath() + { + if (!empty($this->licenseTemplate)) { + return $this->licenseTemplate; + } else { + return $this->generateLicenseTemplate(); + } + } + + /** + * Creates the signed license at the defined output path + * + * @return void + */ + protected function generateLicense() + { + $command = $this->prepareSignCommand() . ' 2>&1'; + + $this->log('Creating license at ' . $this->outputFile); + + $this->log('Running: ' . $command, Project::MSG_VERBOSE); + $tmp = exec($command, $output, $return_var); + + // Check for exit value 1. Zendenc_sign command for some reason + // returns 0 in case of failure and 1 in case of success... + if ($return_var !== 1) { + throw new BuildException("Creating license failed. \n\nZendenc_sign msg:\n" . join("\n", $output) . "\n\n"); + } + } + + /** + * It will generate a temporary license template + * based on the properties defined. + * + * @return string Path of the temporary license template file + */ + protected function generateLicenseTemplate() + { + $this->tmpLicensePath = tempnam(sys_get_temp_dir(), 'zendlicense'); + + $this->log("Creating temporary license template " . $this->tmpLicensePath, Project::MSG_VERBOSE); + if (file_put_contents($this->tmpLicensePath, $this->generateLicenseTemplateContent()) === false) { + throw new BuildException("Unable to create temporary template license file: " . $this->tmpLicensePath); + } + + return $this->tmpLicensePath; + } + + /** + * Generates license template content based + * on the defined parameters + * + * @return string + */ + protected function generateLicenseTemplateContent() + { + $contentArr = array(); + + // Product Name + $contentArr[] = array('Product-Name', $this->productName); + // Registered to + $contentArr[] = array('Registered-To', $this->registeredTo); + // Hardware locked + $contentArr[] = array('Hardware-Locked', ($this->hardwareLocked ? 'Yes' : 'No')); + + // Expires + $contentArr[] = array('Expires', $this->expires); + + // IP-Range + if (!empty($this->ipRange)) { + $contentArr[] = array('IP-Range', $this->ipRange); + } + // Host-ID + if (!empty($this->hostID)) { + foreach (explode(';', $this->hostID) as $hostID) { + $contentArr[] = array('Host-ID', $hostID); + } + } else { + $contentArr[] = array('Host-ID', 'Not-Locked'); + } + + // parse user defined fields + if (!empty($this->userDefinedValues)) { + $this->parseAndAddUserDefinedValues($this->userDefinedValues, $contentArr); + } + // parse user defined x-fields + if (!empty($this->xUserDefinedValues)) { + $this->parseAndAddUserDefinedValues($this->xUserDefinedValues, $contentArr, 'X-'); + } + + // merge all the values + $content = ''; + foreach ($contentArr as $valuePair) { + + list($key, $value) = $valuePair; + + $content .= $key . " = " . $value . "\n"; + } + + return $content; + } + + /** + * Parse the given string in format like key1=value1;key2=value2;... and + * converts it to array + * (key1=>value1, key2=value2, ...) + * + * @param stirng $valueString Semi-colon separated value pairs + * @param array $valueArray Array to which the values will be added + * @param string $keyPrefix Prefix to use when adding the key + * + * @return void + */ + protected function parseAndAddUserDefinedValues($valueString, array &$valueArray, $keyPrefix = '', + $pairSeparator = ';') + { + // explode the valueString (semicolon) + $valuePairs = explode($pairSeparator, $valueString); + if (!empty($valuePairs)) { + foreach ($valuePairs as $valuePair) { + list($key, $value) = explode('=', $valuePair, 2); + + // add pair into the valueArray + $valueArray[] = array($keyPrefix . $key, $value); + } + } + } + +} diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php index e4c291a1..ce0ca210 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: AdhocTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 03a742eb03e5e1515c297d941970a86b00e1f69e $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ require_once 'phing/Task.php'; * Subclasses exist for conveniently declaring and registering tasks and types. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.6 $ + * @version $Id$ * @package phing.tasks.system */ class AdhocTask extends Task { @@ -51,10 +51,10 @@ class AdhocTask extends Task { $this->execute(); if ($this->newClasses) { foreach($this->newClasses as $classname) { - $this->log("Added adhoc class " . $classname, PROJECT_MSG_VERBOSE); + $this->log("Added adhoc class " . $classname, Project::MSG_VERBOSE); } } else { - $this->log("Adhoc task executed but did not result in any new classes.", PROJECT_MSG_VERBOSE); + $this->log("Adhoc task executed but did not result in any new classes.", Project::MSG_VERBOSE); } } diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php index ea336f84..03f80b27 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: AdhocTaskdefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: da14cd0fdc73a0eb13ecc8c0b5ae693550a052b1 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -46,10 +46,11 @@ require_once 'phing/tasks/system/AdhocTask.php'; * </target> * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.5 $ + * @version $Id$ * @package phing.tasks.system */ -class AdhocTaskdefTask extends AdhocTask { +class AdhocTaskdefTask extends AdhocTask +{ /** * The tag that refers to this task. @@ -60,31 +61,43 @@ class AdhocTaskdefTask extends AdhocTask { * Set the tag that will represent this adhoc task/type. * @param string $name */ - public function setName($name) { + public function setName($name) + { $this->name = $name; } /** Main entry point */ - public function main() { - if ($this->name === null) { + public function main() + { + if ($this->name === null) + { throw new BuildException("The name attribute is required for adhoc task definition.",$this->location); } - $this->execute(); + $taskdefs = $this->getProject()->getTaskDefinitions(); - $classes = $this->getNewClasses(); - if (count($classes) !== 1) { - throw new BuildException("You must define one (and only one) class for AdhocTaskdefTask."); - } - $classname = array_shift($classes); - - // instantiate it to make sure it is an instance of Task - $t = new $classname(); - if (!($t instanceof Task)) { - throw new BuildException("The adhoc class you defined must be an instance of phing.Task", $this->location); + if (!isset($taskdefs[$this->name])) + { + $this->execute(); + + $classes = $this->getNewClasses(); + + if (count($classes) < 1) + { + throw new BuildException("You must define at least one class for AdhocTaskdefTask."); + } + + $classname = array_pop($classes); + + // instantiate it to make sure it is an instance of Task + $t = new $classname(); + if (!($t instanceof Task)) + { + throw new BuildException("The adhoc class you defined must be an instance of phing.Task", $this->location); + } + + $this->log("Task " . $this->name . " will be handled by class " . $classname, Project::MSG_VERBOSE); + $this->project->addTaskDefinition($this->name, $classname); } - - $this->log("Task " . $this->name . " will be handled by class " . $classname, PROJECT_MSG_VERBOSE); - $this->project->addTaskDefinition($this->name, $classname); } } diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php index b836ad93..80be2fc9 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: AdhocTypedefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 679ed701a01fef022a2da8ff5db16cff658b77e6 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ require_once 'phing/tasks/system/AdhocTask.php'; * A class for creating adhoc datatypes in build file. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.4 $ + * @version $Id$ * @package phing.tasks.system */ class AdhocTypedefTask extends AdhocTask { @@ -65,7 +65,7 @@ class AdhocTypedefTask extends AdhocTask { throw new BuildException("The adhoc class you defined must be an instance of phing.ProjectComponent", $this->location); } - $this->log("Datatype " . $this->name . " will be handled by class " . $classname, PROJECT_MSG_VERBOSE); + $this->log("Datatype " . $this->name . " will be handled by class " . $classname, Project::MSG_VERBOSE); $this->project->addDataTypeDefinition($this->name, $classname); } } diff --git a/buildscripts/phing/classes/phing/tasks/system/AppendTask.php b/buildscripts/phing/classes/phing/tasks/system/AppendTask.php index feb797cf..a7c4dcda 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AppendTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AppendTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: AppendTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 056086ae305f5447baee1a4c7b1ad59ceb8cf50b $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -48,7 +48,7 @@ include_once 'phing/types/FileSet.php'; * </append> * </code> * @package phing.tasks.system - * @version $Revision: 1.14 $ + * @version $Id$ */ class AppendTask extends Task { @@ -80,7 +80,7 @@ class AppendTask extends Task { * @deprecated Will be removed with final release. */ function setTo(PhingFile $f) { - $this->log("The 'to' attribute is deprecated in favor of 'destFile'; please update your code.", PROJECT_MSG_WARN); + $this->log("The 'to' attribute is deprecated in favor of 'destFile'; please update your code.", Project::MSG_WARN); $this->to = $f; } @@ -165,7 +165,7 @@ class AppendTask extends Task { // out for better performance(?) $lines = explode("\n", $this->text); foreach($lines as $line) { - $this->log($line, PROJECT_MSG_VERBOSE); + $this->log($line, Project::MSG_VERBOSE); } $writer->write($this->text); @@ -177,7 +177,7 @@ class AppendTask extends Task { try { $this->appendFile($writer, $this->file); } catch (Exception $ioe) { - $this->log("Unable to append contents of file " . $this->file->getAbsolutePath() . ": " . $ioe->getMessage(), PROJECT_MSG_WARN); + $this->log("Unable to append contents of file " . $this->file->getAbsolutePath() . ": " . $ioe->getMessage(), Project::MSG_WARN); } } @@ -187,7 +187,7 @@ class AppendTask extends Task { $files = $fl->getFiles($this->project); $this->appendFiles($writer, $files, $fl->getDir($this->project)); } catch (BuildException $be) { - $this->log($be->getMessage(), PROJECT_MSG_WARN); + $this->log($be->getMessage(), Project::MSG_WARN); } } @@ -197,7 +197,7 @@ class AppendTask extends Task { $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); $this->appendFiles($writer, $files, $fs->getDir($this->project)); } catch (BuildException $be) { - $this->log($be->getMessage(), PROJECT_MSG_WARN); + $this->log($be->getMessage(), Project::MSG_WARN); } } @@ -224,7 +224,7 @@ class AppendTask extends Task { $pathSlot->setValue($f->getPath()); $this->appendFile($writer, $f); } catch (Exception $ioe) { - $this->log("Unable to append contents of file " . $f->getAbsolutePath() . ": " . $ioe->getMessage(), PROJECT_MSG_WARN); + $this->log("Unable to append contents of file " . $f->getAbsolutePath() . ": " . $ioe->getMessage(), Project::MSG_WARN); } } } // if !empty diff --git a/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php b/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php index 76de3e40..bd5701e4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: AvailableTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 7388bc66c9574987edd02ad3b2d6f14462f6b157 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,23 +28,25 @@ include_once 'phing/tasks/system/condition/ConditionBase.php'; * Note: implements condition interface (see condition/Condition.php) * * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.11 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id$ * @package phing.tasks.system */ class AvailableTask extends Task { /** Property to check for. */ private $property; - + /** Value property should be set to. */ private $value = "true"; - + /** Resource to check for */ private $resource; - + private $type = null; private $filepath = null; + + private $followSymlinks = false; function setProperty($property) { $this->property = (string) $property; @@ -65,6 +67,36 @@ class AvailableTask extends Task { function setType($type) { $this->type = (string) strtolower($type); } + + public function setFollowSymlinks($followSymlinks) + { + $this->followSymlinks = (bool) $followSymlinks; + } + + /** + * Set the path to use when looking for a file. + * + * @param Path $filepath a Path instance containing the search path for files. + */ + public function setFilepath(Path $filepath) { + if ($this->filepath === null) { + $this->filepath = $filepath; + } else { + $this->filepath->append($filepath); + } + } + + /** + * Creates a path to be configured + * + * @return Path + */ + public function createFilepath() { + if ($this->filepath === null) { + $this->filepath = new Path($this->project); + } + return $this->filepath->createPath(); + } function main() { if ($this->property === null) { @@ -77,20 +109,20 @@ class AvailableTask extends Task { function evaluate() { if ($this->file === null && $this->resource === null) { - throw new BuildException("At least one of (file|resource) is required", $this->location); + throw new BuildException("At least one of (file|resource) is required", $this->location); } if ($this->type !== null && ($this->type !== "file" && $this->type !== "dir")) { throw new BuildException("Type must be one of either dir or file", $this->location); } - + if (($this->file !== null) && !$this->_checkFile()) { - $this->log("Unable to find " . $this->file->__toString() . " to set property " . $this->property, PROJECT_MSG_VERBOSE); + $this->log("Unable to find " . $this->file->__toString() . " to set property " . $this->property, Project::MSG_VERBOSE); return false; } if (($this->resource !== null) && !$this->_checkResource($this->resource)) { - $this->log("Unable to load resource " . $this->resource . " to set property " . $this->property, PROJECT_MSG_VERBOSE); + $this->log("Unable to load resource " . $this->resource . " to set property " . $this->property, Project::MSG_VERBOSE); return false; } @@ -98,13 +130,13 @@ class AvailableTask extends Task { } // this is prepared for the path type - function _checkFile() { + private function _checkFile() { if ($this->filepath === null) { return $this->_checkFile1($this->file); } else { - $paths = $this->filepath->listDir(); + $paths = $this->filepath->listPaths(); for($i=0,$pcnt=count($paths); $i < $pcnt; $i++) { - $this->log("Searching " . $paths[$i], PROJECT_MSG_VERBOSE); + $this->log("Searching " . $paths[$i], Project::MSG_VERBOSE); $tmp = new PhingFile($paths[$i], $this->file->getName()); if($tmp->isFile()) { return true; @@ -114,7 +146,12 @@ class AvailableTask extends Task { return false; } - function _checkFile1($file) { + private function _checkFile1(PhingFile $file) { + // Resolve symbolic links + if ($this->followSymlinks && $file->isLink()) { + $file = new PhingFile($file->getLinkTarget()); + } + if ($this->type !== null) { if ($this->type === "dir") { return $file->isDirectory(); @@ -124,9 +161,12 @@ class AvailableTask extends Task { } return $file->exists(); } - - function _checkResource($resource) { - return $this->_checkFile1(new PhingFile(Phing::getResourcePath($resource))); + + private function _checkResource($resource) { + if (null != ($resourcePath = Phing::getResourcePath($resource))) { + return $this->_checkFile1(new PhingFile($resourcePath)); + } else { + return false; + } } - } diff --git a/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php b/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php index 80470dea..b2300459 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ChmodTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: fad30caf32ff1ee9ff98f63849d61053ab88f645 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ include_once 'phing/types/FileSet.php'; * * @author Manuel Holtgrewe <grin@gmx.net> * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.12 $ + * @version $Id: fad30caf32ff1ee9ff98f63849d61053ab88f645 $ * @package phing.tasks.system */ class ChmodTask extends Task { @@ -39,21 +39,22 @@ class ChmodTask extends Task { private $filesets = array(); private $filesystem; - - private $quiet = false; - private $failonerror = true; - - /** - * This flag means 'note errors to the output, but keep going' - * @see setQuiet() - */ + + private $quiet = false; + private $failonerror = true; + private $verbose = true; + + /** + * This flag means 'note errors to the output, but keep going' + * @see setQuiet() + */ function setFailonerror($bool) { $this->failonerror = $bool; - } + } /** * Set quiet mode, which suppresses warnings if chmod() fails. - * @see setFailonerror() + * @see setFailonerror() */ function setQuiet($bool) { $this->quiet = $bool; @@ -61,7 +62,15 @@ class ChmodTask extends Task { $this->failonerror = false; } } - + + /** + * Set verbosity, which if set to false surpresses all but an overview + * of what happened. + */ + function setVerbose($bool) { + $this->verbose = (bool)$bool; + } + /** * Sets a single source file to touch. If the file does not exist * an empty file will be created. @@ -118,16 +127,21 @@ class ChmodTask extends Task { * @return void */ private function chmod() { - - if (strlen($this->mode) === 4) { - $mode = octdec($this->mode); - } else { - // we need to prepend the 0 before converting - $mode = octdec("0". $this->mode); - } + + if (strlen($this->mode) === 4) { + $mode = octdec($this->mode); + } else { + // we need to prepend the 0 before converting + $mode = octdec("0". $this->mode); + } + + // counters for non-verbose output + $total_files = 0; + $total_dirs = 0; // one file if ($this->file !== null) { + $total_files = 1; $this->chmodFile($this->file, $mode); } @@ -140,38 +154,50 @@ class ChmodTask extends Task { $srcFiles = $ds->getIncludedFiles(); $srcDirs = $ds->getIncludedDirectories(); - for ($j = 0, $filecount = count($srcFiles); $j < $filecount; $j++) { + $filecount = count($srcFiles); + $total_files = $total_files + $filecount; + for ($j = 0; $j < $filecount; $j++) { $this->chmodFile(new PhingFile($fromDir, $srcFiles[$j]), $mode); } - for ($j = 0, $dircount = count($srcDirs); $j < $dircount; $j++) { + $dircount = count($srcDirs); + $total_dirs = $total_dirs + $dircount; + for ($j = 0; $j < $dircount; $j++) { $this->chmodFile(new PhingFile($fromDir, $srcDirs[$j]), $mode); } } + if (!$this->verbose) { + $this->log('Total files changed to ' . vsprintf('%o', $mode) . ': ' . $total_files); + $this->log('Total directories changed to ' . vsprintf('%o', $mode) . ': ' . $total_dirs); + } + } - /** - * Actually change the mode for the file. - * @param PhingFile $file - * @param int $mode - */ + /** + * Actually change the mode for the file. + * @param PhingFile $file + * @param int $mode + */ private function chmodFile(PhingFile $file, $mode) { if ( !$file->exists() ) { throw new BuildException("The file " . $file->__toString() . " does not exist"); } - - try { - $file->setMode($mode); - $this->log("Changed file mode on '" . $file->__toString() ."' to " . vsprintf("%o", $mode)); - } catch (Exception $e) { - if($this->failonerror) { - throw $e; - } else { - $this->log($e->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); - } - } + + try { + $file->setMode($mode); + if ($this->verbose) { + $this->log("Changed file mode on '" . $file->__toString() ."' to " . vsprintf("%o", $mode)); + } + } catch (Exception $e) { + if($this->failonerror) { + throw $e; + } else { + $this->log($e->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); + } + } } - + } + diff --git a/buildscripts/phing/classes/phing/tasks/system/ChownTask.php b/buildscripts/phing/classes/phing/tasks/system/ChownTask.php new file mode 100755 index 00000000..60b8105c --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/ChownTask.php @@ -0,0 +1,216 @@ +<?php +/* + * $Id: f7234abd52e7f80177f4b121436ae7276370993c $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +include_once 'phing/types/FileSet.php'; + +/** + * Task that changes the permissions on a file/directory. + * + * @author Mehmet Emre Yilmaz <mehmety@gmail.com> + * @version $Id: f7234abd52e7f80177f4b121436ae7276370993c $ + * @package phing.tasks.system + */ +class ChownTask extends Task { + + private $file; + + private $user; + private $group; + + private $filesets = array(); + + private $filesystem; + + private $quiet = false; + private $failonerror = true; + private $verbose = true; + + /** + * This flag means 'note errors to the output, but keep going' + * @see setQuiet() + */ + function setFailonerror($bool) { + $this->failonerror = $bool; + } + + /** + * Set quiet mode, which suppresses warnings if chown() fails. + * @see setFailonerror() + */ + function setQuiet($bool) { + $this->quiet = $bool; + if ($this->quiet) { + $this->failonerror = false; + } + } + + /** + * Set verbosity, which if set to false surpresses all but an overview + * of what happened. + */ + function setVerbose($bool) { + $this->verbose = (bool)$bool; + } + + /** + * Sets a single source file to touch. If the file does not exist + * an empty file will be created. + */ + function setFile(PhingFile $file) { + $this->file = $file; + } + + /** + * Sets the user + */ + function setUser($user) { + $this->user = $user; + } + + /** + * Sets the group + */ + function setGroup($group) { + $this->group = $group; + } + + /** + * Nested creator, adds a set of files (nested fileset attribute). + */ + function addFileSet(FileSet $fs) { + $this->filesets[] = $fs; + } + + /** + * Execute the touch operation. + * @return void + */ + function main() { + // Check Parameters + $this->checkParams(); + $this->chown(); + } + + /** + * Ensure that correct parameters were passed in. + * @return void + */ + private function checkParams() { + + if ($this->file === null && empty($this->filesets)) { + throw new BuildException("Specify at least one source - a file or a fileset."); + } + + if ($this->user === null && $this->group === null) { + throw new BuildException("You have to specify either an owner or a group for chown."); + } + } + + /** + * Does the actual work. + * @return void + */ + private function chown() { + $userElements = explode('.', $this->user); + + $user = $userElements[0]; + + if (count($userElements) > 1) { + $group = $userElements[1]; + } else { + $group = $this->group; + } + + // counters for non-verbose output + $total_files = 0; + $total_dirs = 0; + + // one file + if ($this->file !== null) { + $total_files = 1; + $this->chownFile($this->file, $user, $group); + } + + // filesets + foreach($this->filesets as $fs) { + + $ds = $fs->getDirectoryScanner($this->project); + $fromDir = $fs->getDir($this->project); + + $srcFiles = $ds->getIncludedFiles(); + $srcDirs = $ds->getIncludedDirectories(); + + $filecount = count($srcFiles); + $total_files = $total_files + $filecount; + for ($j = 0; $j < $filecount; $j++) { + $this->chownFile(new PhingFile($fromDir, $srcFiles[$j]), $user, $group); + } + + $dircount = count($srcDirs); + $total_dirs = $total_dirs + $dircount; + for ($j = 0; $j < $dircount; $j++) { + $this->chownFile(new PhingFile($fromDir, $srcDirs[$j]), $user, $group); + } + } + + if (!$this->verbose) { + $this->log('Total files changed to ' . $user . ($group ? "." . $group : "") . ': ' . $total_files); + $this->log('Total directories changed to ' . $user . ($group ? "." . $group : "") . ': ' . $total_dirs); + } + + } + + /** + * Actually change the mode for the file. + * @param PhingFile $file + * @param string $user + * @param string $group + */ + private function chownFile(PhingFile $file, $user, $group = "") { + if ( !$file->exists() ) { + throw new BuildException("The file " . $file->__toString() . " does not exist"); + } + + try { + if (!empty($user)) { + $file->setUser($user); + } + + if (!empty($group)) { + $file->setGroup($group); + } + + if ($this->verbose) { + $this->log("Changed file owner on '" . $file->__toString() ."' to " . $user . ($group ? "." . $group : "")); + } + } catch (Exception $e) { + if($this->failonerror) { + throw $e; + } else { + $this->log($e->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); + } + } + } + +} + + diff --git a/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php b/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php index fe6ee60b..040fff8a 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ConditionTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 31dfd9d24212a4cf5afcce43a9ae337669bafc35 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,8 +31,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php'; * ConditionBase.</p> * * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.7 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id$ * @access public * @package phing.tasks.system */ diff --git a/buildscripts/phing/classes/phing/tasks/system/CopyTask.php b/buildscripts/phing/classes/phing/tasks/system/CopyTask.php index c5e4c2a5..2533bb95 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/CopyTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/CopyTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: CopyTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 86322e73609da671413e4c959082958c16a510cc $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -18,7 +18,7 @@ * and is licensed under the LGPL. For more information please see * <http://phing.info>. */ - + require_once 'phing/Task.php'; include_once 'phing/system/io/PhingFile.php'; include_once 'phing/util/FileUtils.php'; @@ -33,27 +33,33 @@ include_once 'phing/mappers/FlattenMapper.php'; * exist. It is possible to explictly overwrite existing files. * * @author Andreas Aderhold, andi@binarycloud.com - * @version $Revision: 1.16 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @version $Id: 86322e73609da671413e4c959082958c16a510cc $ * @package phing.tasks.system */ class CopyTask extends Task { - + protected $file = null; // the source file (from xml attribute) protected $destFile = null; // the destiantion file (from xml attribute) protected $destDir = null; // the destination dir (from xml attribute) protected $overwrite = false; // overwrite destination (from xml attribute) - protected $preserveLMT = true; // sync timestamps (from xml attribute) + protected $preserveLMT = false; // sync timestamps (from xml attribute) protected $includeEmpty = true; // include empty dirs? (from XML) protected $flatten = false; // apply the FlattenMapper right way (from XML) protected $mapperElement = null; protected $fileCopyMap = array(); // asoc array containing mapped file names protected $dirCopyMap = array(); // asoc array containing mapped file names + protected $completeDirMap= array(); // asoc array containing complete dir names protected $fileUtils = null; // a instance of fileutils protected $filesets = array(); // all fileset objects assigned to this task + protected $filelists = array(); // all filelist objects assigned to this task protected $filterChains = array(); // all filterchains objects assigned to this task - protected $verbosity = PROJECT_MSG_VERBOSE; + protected $verbosity = Project::MSG_VERBOSE; + + protected $mode = 0755; // mode to create directories with + + protected $haltonerror = true; // stop build on errors /** * Sets up this object internal stuff. i.e. the Fileutils instance @@ -84,14 +90,21 @@ class CopyTask extends Task { */ function setVerbose($verbosity) { if ($verbosity) { - $this->verbosity = PROJECT_MSG_INFO; + $this->verbosity = Project::MSG_INFO; } else { - $this->verbosity = PROJECT_MSG_VERBOSE; + $this->verbosity = Project::MSG_VERBOSE; } } - + /** - * Set the preserve timestmap flag. IntrospectionHelper takes care of + * @see CopyTask::setPreserveLastModified + */ + function setTstamp($bool) { + $this->setPreserveLastModified($bool); + } + + /** + * Set the preserve timestamp flag. IntrospectionHelper takes care of * booleans in set* methods so we can assume that the right * value (boolean primitive) is coming in here. * @@ -99,11 +112,10 @@ class CopyTask extends Task { * @return void * @access public */ - function setTstamp($bool) { + function setPreserveLastModified($bool) { $this->preserveLMT = (boolean) $bool; } - /** * Set the include empty dirs flag. IntrospectionHelper takes care of * booleans in set* methods so we can assume that the right @@ -127,7 +139,7 @@ class CopyTask extends Task { * @return void * @access public */ - function setFile(PhingFile $file) { + function setFile(PhingFile $file) { $this->file = $file; } @@ -141,10 +153,21 @@ class CopyTask extends Task { * @return void * @access public */ - function setTofile(PhingFile $file) { + function setTofile(PhingFile $file) { $this->destFile = $file; } + /** + * Sets the mode to create destination directories with (ignored on Windows). + * Default mode is 0755. + * + * @param integer Octal mode + * @return void + * @access public + */ + function setMode($mode) { + $this->mode = (int) base_convert($mode, 8, 10); + } /** * Set the toDir. We have to manually take care of the @@ -155,22 +178,44 @@ class CopyTask extends Task { * @return void * @access public */ - function setTodir(PhingFile $dir) { + function setTodir(PhingFile $dir) { $this->destDir = $dir; } /** + * Set the haltonerror attribute - when true, will + * make the build fail when errors are detected. + * + * @param boolean Flag if the build should be stopped on errors + * @return void + * @access public + */ + function setHaltonerror($haltonerror) { + $this->haltonerror = (boolean) $haltonerror; + } + + /** * Nested creator, creates a FileSet for this task * - * @access public - * @return object The created fileset object + * @param FileSet $fileset Set of files to copy + * + * @return void */ - function createFileSet() { - $num = array_push($this->filesets, new FileSet()); - return $this->filesets[$num-1]; + public function addFileSet(FileSet $fs) { + $this->filesets[] = $fs; } /** + * Nested creator, adds a set of files (nested fileset attribute). + * + * @access public + * @return object The created filelist object + */ + function createFileList() { + $num = array_push($this->filelists, new FileList()); + return $this->filelists[$num-1]; + } + /** * Creates a filterchain * * @access public @@ -204,7 +249,7 @@ class CopyTask extends Task { * @throws BuildException */ function main() { - + $this->validateAttributes(); if ($this->file !== null) { @@ -219,18 +264,38 @@ class CopyTask extends Task { } } else { // terminate build - throw new BuildException("Could not find file " . $this->file->__toString() . " to copy."); + $this->logError("Could not find file " . $this->file->__toString() . " to copy."); } } $project = $this->getProject(); + // process filelists + foreach($this->filelists as $fl) { + $fromDir = $fl->getDir($project); + $srcFiles = $fl->getFiles($project); + $srcDirs = array($fl->getDir($project)); + + if (!$this->flatten && $this->mapperElement === null) + { + $this->completeDirMap[$fromDir->getAbsolutePath()] = $this->destDir->getAbsolutePath(); + } + + $this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs); + } + // process filesets foreach($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($project); $fromDir = $fs->getDir($project); $srcFiles = $ds->getIncludedFiles(); $srcDirs = $ds->getIncludedDirectories(); + + if (!$this->flatten && $this->mapperElement === null) + { + $this->completeDirMap[$fromDir->getAbsolutePath()] = $this->destDir->getAbsolutePath(); + } + $this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs); } @@ -249,10 +314,10 @@ class CopyTask extends Task { * @return void * @throws BuildException */ - private function validateAttributes() { - - if ($this->file === null && count($this->filesets) === 0) { - throw new BuildException("CopyTask. Specify at least one source - a file or a fileset."); + protected function validateAttributes() { + + if ($this->file === null && count($this->filesets) === 0 && count($this->filelists) === 0) { + throw new BuildException("CopyTask. Specify at least one source - a file, fileset or filelist."); } if ($this->destFile !== null && $this->destDir !== null) { @@ -295,7 +360,7 @@ class CopyTask extends Task { $mapper = new IdentityMapper(); } $this->buildMap($fromDir, $toDir, $files, $mapper, $this->fileCopyMap); - $this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap); + $this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap); } /** @@ -336,17 +401,41 @@ class CopyTask extends Task { * @return void * @throws BuildException */ - private function doWork() { + protected function doWork() { + + // These "slots" allow filters to retrieve information about the currently-being-process files + $fromSlot = $this->getRegisterSlot("currentFromFile"); + $fromBasenameSlot = $this->getRegisterSlot("currentFromFile.basename"); + + $toSlot = $this->getRegisterSlot("currentToFile"); + $toBasenameSlot = $this->getRegisterSlot("currentToFile.basename"); + + $mapSize = count($this->fileCopyMap); + $total = $mapSize; - // These "slots" allow filters to retrieve information about the currently-being-process files - $fromSlot = $this->getRegisterSlot("currentFromFile"); - $fromBasenameSlot = $this->getRegisterSlot("currentFromFile.basename"); + // handle empty dirs if appropriate + if ($this->includeEmpty) { + $count = 0; + foreach ($this->dirCopyMap as $srcdir => $destdir) { + $s = new PhingFile((string) $srcdir); + $d = new PhingFile((string) $destdir); + if (!$d->exists()) { + if (!$d->mkdirs()) { + $this->logError("Unable to create directory " . $d->__toString()); + } else { + if ($this->preserveLMT) { + $d->setLastModified($s->lastModified()); + } - $toSlot = $this->getRegisterSlot("currentToFile"); - $toBasenameSlot = $this->getRegisterSlot("currentToFile.basename"); + $count++; + } + } + } + if ($count > 0) { + $this->log("Created ".$count." empty director" . ($count == 1 ? "y" : "ies") . " in " . $this->destDir->getAbsolutePath()); + } + } - $mapSize = count($this->fileCopyMap); - $total = $mapSize; if ($mapSize > 0) { $this->log("Copying ".$mapSize." file".(($mapSize) === 1 ? '' : 's')." to ". $this->destDir->getAbsolutePath()); // walks the map and actually copies the files @@ -359,42 +448,32 @@ class CopyTask extends Task { } $this->log("From ".$from." to ".$to, $this->verbosity); try { // try to copy file - - $fromFile = new PhingFile($from); - $toFile = new PhingFile($to); - + + $fromFile = new PhingFile($from); + $toFile = new PhingFile($to); + $fromSlot->setValue($fromFile->getPath()); - $fromBasenameSlot->setValue($fromFile->getName()); - - $toSlot->setValue($toFile->getPath()); - $toBasenameSlot->setValue($toFile->getName()); - - $this->fileUtils->copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject()); + $fromBasenameSlot->setValue($fromFile->getName()); + $toSlot->setValue($toFile->getPath()); + $toBasenameSlot->setValue($toFile->getName()); + + $this->fileUtils->copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->mode); + $count++; } catch (IOException $ioe) { - $this->log("Failed to copy " . $from . " to " . $to . ": " . $ioe->getMessage(), PROJECT_MSG_ERR); + $this->logError("Failed to copy " . $from . " to " . $to . ": " . $ioe->getMessage()); } } } - - // handle empty dirs if appropriate - if ($this->includeEmpty) { - $e = array_values($this->dirCopyMap); - $count = 0; - foreach ($e as $dir) { - $d = new PhingFile((string) $dir); - if (!$d->exists()) { - if (!$d->mkdirs()) { - $this->log("Unable to create directory " . $d->__toString(), PROJECT_MSG_ERR); - } else { - $count++; - } - } - } - if ($count > 0) { - $this->log("Copied ".$count." empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath()); - } + } + + protected function logError($message, $location = NULL) + { + if ($this->haltonerror) { + throw new BuildException($message, $location); + } else { + $this->log($message, Project::MSG_ERR); } } diff --git a/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php b/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php index 0003c50f..87a9b63c 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: CvsPassTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c1e02a8d43f62c584ba2f1cd5a6f0cc690bceb94 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ include_once 'phing/util/StringHelper.php'; * * @author Hans Lellelid <hans@xmpl.org> (Phing) * @author Jeff Martin <jeff@custommonkey.org> (Ant) - * @version $Revision: 1.7 $ + * @version $Id$ * @package phing.tasks.system */ class CVSPassTask extends Task { @@ -84,9 +84,9 @@ class CVSPassTask extends Task { throw new BuildException("password is required"); } - $this->log("cvsRoot: " . $this->cvsRoot, PROJECT_MSG_DEBUG); - $this->log("password: " . $this->password, PROJECT_MSG_DEBUG); - $this->log("passFile: " . $this->passFile->__toString(), PROJECT_MSG_DEBUG); + $this->log("cvsRoot: " . $this->cvsRoot, Project::MSG_DEBUG); + $this->log("password: " . $this->password, Project::MSG_DEBUG); + $this->log("passFile: " . $this->passFile->__toString(), Project::MSG_DEBUG); $reader = null; $writer = null; @@ -100,14 +100,14 @@ class CVSPassTask extends Task { $line = null; while (($line = $reader->readLine()) !== null) { if (!StringHelper::startsWith($this->cvsRoot, $line)) { - $buf .= $line . Phing::getProperty("line.separator"); + $buf .= $line . PHP_EOL; } } } $pwdfile = $buf . $this->cvsRoot . " A" . $this->mangle($this->password); - $this->log("Writing -> " . $pwdfile , PROJECT_MSG_DEBUG); + $this->log("Writing -> " . $pwdfile , Project::MSG_DEBUG); $writer = new BufferedWriter(new FileWriter($this->passFile)); $writer->write($pwdfile); diff --git a/buildscripts/phing/classes/phing/tasks/system/CvsTask.php b/buildscripts/phing/classes/phing/tasks/system/CvsTask.php index de2950ec..3c12a597 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/CvsTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/CvsTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: CvsTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 642c6947fa58e02a8c7893c8c4dfab2debfdd51d $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,7 +35,7 @@ include_once 'phing/types/Commandline.php'; * @author stefano@apache.org (Ant) * @author Wolfgang Werner <wwerner@picturesafe.de> (Ant) * @author Kevin Ross <kevin.ross@bredex.com> (Ant) - * @version $Revision: 1.14 $ + * @version $Id: 642c6947fa58e02a8c7893c8c4dfab2debfdd51d $ * @package phing.tasks.system */ class CvsTask extends Task { @@ -155,14 +155,14 @@ class CvsTask extends Task { if ($this->passFile !== null) { if ($this->passFile->isFile() && $this->passFile->canRead()) { putenv("CVS_PASSFILE=" . $this->passFile->__toString()); - $this->log("Using cvs passfile: " . $this->passFile->__toString(), PROJECT_MSG_INFO); + $this->log("Using cvs passfile: " . $this->passFile->__toString(), Project::MSG_INFO); } elseif (!$this->passFile->canRead()) { $this->log("cvs passfile: " . $this->passFile->__toString() - . " ignored as it is not readable", PROJECT_MSG_WARN); + . " ignored as it is not readable", Project::MSG_WARN); } else { $this->log("cvs passfile: " . $this->passFile->__toString() . " ignored as it is not a file", - PROJECT_MSG_WARN); + Project::MSG_WARN); } } @@ -201,14 +201,14 @@ class CvsTask extends Task { try { $actualCommandLine = $toExecuteStr; // we converted to string above - $this->log($actualCommandLine, PROJECT_MSG_INFO); - $retCode = $exe->execute(); - $this->log("retCode=" . $retCode, PROJECT_MSG_DEBUG); + $this->log($actualCommandLine, Project::MSG_INFO); + $retCode = $exe->main(); + $this->log("retCode=" . $retCode, Project::MSG_DEBUG); /*Throw an exception if cvs exited with error. (Iulian)*/ if ($this->failOnError && $retCode !== 0) { throw new BuildException("cvs exited with error code " . $retCode - . Phing::getProperty("line.separator") + . PHP_EOL . "Command line was [" . $toExecute->describeCommand() . "]", $this->getLocation()); } @@ -216,7 +216,7 @@ class CvsTask extends Task { if ($this->failOnError) { throw new BuildException($e, $this->getLocation()); } else { - $this->log("Caught exception: " . $e, PROJECT_MSG_WARN); + $this->log("Caught exception: " . $e, Project::MSG_WARN); } } catch (BuildException $e) { if ($this->failOnError) { @@ -226,13 +226,13 @@ class CvsTask extends Task { if ($t === null) { $t = $e; } - $this->log("Caught exception: " . $t, PROJECT_MSG_WARN); + $this->log("Caught exception: " . $t, Project::MSG_WARN); } } catch (Exception $e) { if ($this->failOnError) { throw new BuildException($e, $this->getLocation()); } else { - $this->log("Caught exception: " . $e, PROJECT_MSG_WARN); + $this->log("Caught exception: " . $e, Project::MSG_WARN); } } } diff --git a/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php b/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php index 00e1e7a7..8af8a632 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: DeleteTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: f25fc4c605ead65db9235c9fe328b2d47b7c8299 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,7 +24,7 @@ require_once 'phing/Task.php'; /** * Deletes a file or directory, or set of files defined by a fileset. * - * @version $Revision: 1.13 $ + * @version $Id: f25fc4c605ead65db9235c9fe328b2d47b7c8299 $ * @package phing.tasks.system */ class DeleteTask extends Task { @@ -36,11 +36,11 @@ class DeleteTask extends Task { protected $quiet = false; protected $failonerror = true; - protected $verbosity = PROJECT_MSG_VERBOSE; - - /** Any filelists of files that should be deleted. */ + protected $verbosity = Project::MSG_VERBOSE; + + /** Any filelists of files that should be deleted. */ private $filelists = array(); - + /** * Set the name of a single file to be removed. * @param PhingFile $file @@ -63,9 +63,9 @@ class DeleteTask extends Task { */ function setVerbose($verbosity) { if ($verbosity) { - $this->verbosity = PROJECT_MSG_INFO; + $this->verbosity = Project::MSG_INFO; } else { - $this->verbosity = PROJECT_MSG_VERBOSE; + $this->verbosity = Project::MSG_VERBOSE; } } @@ -96,12 +96,11 @@ class DeleteTask extends Task { } /** Nested creator, adds a set of files (nested fileset attribute). */ - function createFileSet() { - $num = array_push($this->filesets, new FileSet()); - return $this->filesets[$num-1]; + function addFileSet(FileSet $fs) { + $this->filesets[] = $fs; } - - /** Nested creator, adds a set of files (nested fileset attribute). */ + + /** Nested creator, adds a set of files (nested fileset attribute). */ function createFileList() { $num = array_push($this->filelists, new FileList()); return $this->filelists[$num-1]; @@ -131,38 +130,38 @@ class DeleteTask extends Task { if($this->failonerror) { throw new BuildException($message); } else { - $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); + $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); } } } } else { - $this->log("Could not find file " . $this->file->getAbsolutePath() . " to delete.",PROJECT_MSG_VERBOSE); + $this->log("Could not find file " . $this->file->getAbsolutePath() . " to delete.",Project::MSG_VERBOSE); } } // delete the directory if ($this->dir !== null && $this->dir->exists() && $this->dir->isDirectory()) { - if ($this->verbosity === PROJECT_MSG_VERBOSE) { + if ($this->verbosity === Project::MSG_VERBOSE) { $this->log("Deleting directory " . $this->dir->__toString()); } $this->removeDir($this->dir); } - - // delete the files in the filelists - foreach($this->filelists as $fl) { - try { - $files = $fl->getFiles($this->project); - $this->removeFiles($fl->getDir($this->project), $files, $empty=array()); - } catch (BuildException $be) { - // directory doesn't exist or is not readable - if ($this->failonerror) { - throw $be; - } else { - $this->log($be->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); - } - } - } - + + // delete the files in the filelists + foreach($this->filelists as $fl) { + try { + $files = $fl->getFiles($this->project); + $this->removeFiles($fl->getDir($this->project), $files, $empty=array()); + } catch (BuildException $be) { + // directory doesn't exist or is not readable + if ($this->failonerror) { + throw $be; + } else { + $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); + } + } + } + // delete the files in the filesets foreach($this->filesets as $fs) { try { @@ -175,7 +174,7 @@ class DeleteTask extends Task { if ($this->failonerror) { throw $be; } else { - $this->log($be->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); + $this->log($be->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); } } } @@ -204,7 +203,7 @@ class DeleteTask extends Task { if($this->failonerror) { throw new BuildException($message); } else { - $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); + $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); } } } @@ -217,7 +216,7 @@ class DeleteTask extends Task { if($this->failonerror) { throw new BuildException($message); } else { - $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); + $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); } } } @@ -242,7 +241,7 @@ class DeleteTask extends Task { if($this->failonerror) { throw new BuildException($message); } else { - $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); + $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); } } @@ -260,11 +259,11 @@ class DeleteTask extends Task { $dir->delete(); $dirCount++; } catch (Exception $e) { - $message="Unable to delete directory " + $dir; + $message="Unable to delete directory " . $dir->__toString(); if($this->failonerror) { throw new BuildException($message); } else { - $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN); + $this->log($message, $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN); } } } diff --git a/buildscripts/phing/classes/phing/tasks/system/EchoTask.php b/buildscripts/phing/classes/phing/tasks/system/EchoTask.php index 229f5130..edc098c4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/EchoTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/EchoTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: EchoTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c5ebadd12256533d9ca4d6fb6cabd50415bdddbf $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -24,14 +24,14 @@ include_once 'phing/Task.php'; /** * Echos a message to the logging system or to a file * - * @author Michiel Rook <michiel@trendserver.nl> + * @author Michiel Rook <mrook@php.net> * @author Andreas Aderhold, andi@binarycloud.com - * @version $Revision: 1.5 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @version $Id$ * @package phing.tasks.system */ class EchoTask extends Task { - + protected $msg = ""; protected $file = ""; @@ -40,54 +40,87 @@ class EchoTask extends Task { protected $level = "info"; - function main() { - switch ($this->level) - { - case "error": $loglevel = PROJECT_MSG_ERR; break; - case "warning": $loglevel = PROJECT_MSG_WARN; break; - case "info": $loglevel = PROJECT_MSG_INFO; break; - case "verbose": $loglevel = PROJECT_MSG_VERBOSE; break; - case "debug": $loglevel = PROJECT_MSG_DEBUG; break; - } - - if (empty($this->file)) - { - $this->log($this->msg, $loglevel); - } - else - { - if ($this->append) - { - $handle = fopen($this->file, "a"); - } - else - { - $handle = fopen($this->file, "w"); - } - - fwrite($handle, $this->msg); - - fclose($handle); - } + protected $filesets = array(); + + function main() { + switch ($this->level) + { + case "error": $loglevel = Project::MSG_ERR; break; + case "warning": $loglevel = Project::MSG_WARN; break; + case "info": $loglevel = Project::MSG_INFO; break; + case "verbose": $loglevel = Project::MSG_VERBOSE; break; + case "debug": $loglevel = Project::MSG_DEBUG; break; + } + + if (count($this->filesets)) { + if (trim(substr($this->msg, -1)) != '') { + $this->msg .= "\n"; + } + $this->msg .= $this->getFilesetsMsg(); + } + + if (empty($this->file)) + { + $this->log($this->msg, $loglevel); + } + else + { + if ($this->append) + { + $handle = fopen($this->file, "a"); + } + else + { + $handle = fopen($this->file, "w"); + } + + fwrite($handle, $this->msg); + + fclose($handle); + } + } + + /** + * Merges all filesets into a string to be echoed out + * + * @return string String to echo + */ + protected function getFilesetsMsg() + { + $project = $this->getProject(); + $msg = ''; + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($project); + $fromDir = $fs->getDir($project); + $srcFiles = $ds->getIncludedFiles(); + $msg .= 'Directory: ' . $fromDir . ' => ' + . realpath($fromDir) . "\n"; + foreach ($srcFiles as $file) { + $relPath = $fromDir . DIRECTORY_SEPARATOR . $file; + $msg .= $relPath . "\n"; + } + } + + return $msg; } /** setter for file */ function setFile($file) { - $this->file = (string) $file; - } + $this->file = (string) $file; + } /** setter for level */ function setLevel($level) { - $this->level = (string) $level; - } + $this->level = (string) $level; + } /** setter for append */ function setAppend($append) { - $this->append = $append; - } + $this->append = $append; + } /** setter for message */ function setMsg($msg) { @@ -104,4 +137,16 @@ class EchoTask extends Task { { $this->msg = (string) $msg; } + + /** + * Adds a fileset to echo the files of + * + * @param FileSet $fs Set of files to echo + * + * @return void + */ + public function addFileSet(FileSet $fs) + { + $this->filesets[] = $fs; + } } diff --git a/buildscripts/phing/classes/phing/tasks/system/ExecTask.php b/buildscripts/phing/classes/phing/tasks/system/ExecTask.php index 104f7697..f5a57948 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ExecTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ExecTask.php @@ -1,7 +1,7 @@ <?php -/* - * $Id: ExecTask.php 59 2006-04-28 14:49:47Z mrook $ +/** + * $Id: 3101d1403eeb4fe4fe8bae729b7d918b303de1cf $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,119 +25,223 @@ require_once 'phing/Task.php'; /** * Executes a command on the shell. * - * @author Andreas Aderhold <andi@binarycloud.com> - * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.17 $ - * @package phing.tasks.system + * @author Andreas Aderhold <andi@binarycloud.com> + * @author Hans Lellelid <hans@xmpl.org> + * @author Christian Weiske <cweiske@cweiske.de> + * @version $Id: 3101d1403eeb4fe4fe8bae729b7d918b303de1cf $ + * @package phing.tasks.system */ -class ExecTask extends Task { +class ExecTask extends Task +{ /** * Command to execute. * @var string */ protected $command; - + + /** + * Commandline managing object + * + * @var Commandline + */ + protected $commandline; + /** * Working directory. - * @var File + * @var PhingFile */ protected $dir; - + /** * Operating system. * @var string */ protected $os; - + /** * Whether to escape shell command using escapeshellcmd(). * @var boolean */ protected $escape = false; - + /** * Where to direct output. * @var File */ protected $output; - + /** - * Whether to passthru the output + * Whether to use PHP's passthru() function instead of exec() * @var boolean */ protected $passthru = false; + + /** + * Whether to log returned output as MSG_INFO instead of MSG_VERBOSE + * @var boolean + */ + protected $logOutput = false; /** + * Logging level for status messages + * @var integer + */ + protected $logLevel = Project::MSG_VERBOSE; + + /** * Where to direct error output. * @var File */ protected $error; - - /** - * If spawn is set then [unix] programs will redirect stdout and add '&'. - * @var boolean - */ - protected $spawn = false; - + + /** + * If spawn is set then [unix] programs will redirect stdout and add '&'. + * @var boolean + */ + protected $spawn = false; + + /** + * Property name to set with return value from exec call. + * + * @var string + */ + protected $returnProperty; + + /** + * Property name to set with output value from exec call. + * + * @var string + */ + protected $outputProperty; + /** * Whether to check the return code. * @var boolean */ protected $checkreturn = false; - + + + + public function __construct() + { + $this->commandline = new Commandline(); + } + /** * Main method: wraps execute() command. + * * @return void */ - public function main() { - $this->execute(); + public function main() + { + if (!$this->isApplicable()) { + return; + } + + $this->prepare(); + $this->buildCommand(); + list($return, $output) = $this->executeCommand(); + $this->cleanup($return, $output); } - + /** - * Executes a program and returns the return code. - * Output from command is logged at INFO level. - * @return int Return code from execution. + * Checks whether the command shall be executed + * + * @return boolean False if the exec command shall not be run */ - public function execute() { - - // test if os match - $myos = Phing::getProperty("os.name"); - $this->log("Myos = " . $myos, PROJECT_MSG_VERBOSE); - if (($this->os !== null) && (strpos($os, $myos) === false)) { + protected function isApplicable() + { + if ($this->os === null) { + return true; + } + + $myos = Phing::getProperty('os.name'); + $this->log('Myos = ' . $myos, Project::MSG_VERBOSE); + + if (strpos($this->os, $myos) !== false) { // this command will be executed only on the specified OS - $this->log("Not found in " . $os, PROJECT_MSG_VERBOSE); - return 0; + // OS matches + return true; } - - if ($this->dir !== null) { - if ($this->dir->isDirectory()) { - $currdir = getcwd(); - @chdir($this->dir->getPath()); - } else { - throw new BuildException("Can't chdir to:" . $this->dir->__toString()); - } + + $this->log( + sprintf( + 'Operating system %s not found in %s', + $myos, $this->os + ), + Project::MSG_VERBOSE + ); + return false; + } + + /** + * Prepares the command building and execution, i.e. + * changes to the specified directory. + * + * @return void + */ + protected function prepare() + { + if ($this->dir === null) { + return; } + // expand any symbolic links first + if (!$this->dir->getCanonicalFile()->isDirectory()) { + throw new BuildException( + "'" . (string) $this->dir . "' is not a valid directory" + ); + } + $this->currdir = getcwd(); + @chdir($this->dir->getPath()); + } - if ($this->escape == true) { - // FIXME - figure out whether this is correct behavior - $this->command = escapeshellcmd($this->command); + /** + * Builds the full command to execute and stores it in $command. + * + * @return void + * @uses $command + */ + protected function buildCommand() + { + if ($this->command === null && $this->commandline->getExecutable() === null) { + throw new BuildException( + 'ExecTask: Please provide "command" OR "executable"' + ); + } else if ($this->command === null) { + $this->command = Commandline::toString($this->commandline->getCommandline(), $this->escape); + } else if ($this->commandline->getExecutable() === null) { + //we need to escape the command only if it's specified directly + // commandline takes care of "executable" already + if ($this->escape == true) { + $this->command = escapeshellcmd($this->command); + } + } else { + throw new BuildException( + 'ExecTask: Either use "command" OR "executable"' + ); } - + if ($this->error !== null) { $this->command .= ' 2> ' . $this->error->getPath(); - $this->log("Writing error output to: " . $this->error->getPath()); + $this->log( + "Writing error output to: " . $this->error->getPath(), + $this->logLevel + ); } - + if ($this->output !== null) { $this->command .= ' 1> ' . $this->output->getPath(); - $this->log("Writing standard output to: " . $this->output->getPath()); + $this->log( + "Writing standard output to: " . $this->output->getPath(), + $this->logLevel + ); } elseif ($this->spawn) { - $this->command .= ' 1>/dev/null'; - $this->log("Sending ouptut to /dev/null"); - } - + $this->command .= ' 1>/dev/null'; + $this->log("Sending output to /dev/null", $this->logLevel); + } + // If neither output nor error are being written to file // then we'll redirect error to stdout so that we can dump // it to screen below. @@ -145,104 +249,268 @@ class ExecTask extends Task { if ($this->output === null && $this->error === null) { $this->command .= ' 2>&1'; } - - // we ignore the spawn boolean for windows - if ($this->spawn) { - $this->command .= ' &'; - } - $this->log("Executing command: " . $this->command); - + // we ignore the spawn boolean for windows + if ($this->spawn) { + $this->command .= ' &'; + } + } + + /** + * Executes the command and returns return code and output. + * + * @return array array(return code, array with output) + */ + protected function executeCommand() + { + $this->log("Executing command: " . $this->command, $this->logLevel); + $output = array(); $return = null; - exec($this->command, $output, $return); + + if ($this->passthru) { + passthru($this->command, $return); + } else { + exec($this->command, $output, $return); + } + return array($return, $output); + } + + /** + * Runs all tasks after command execution: + * - change working directory back + * - log output + * - verify return value + * + * @param integer $return Return code + * @param array $output Array with command output + * + * @return void + */ + protected function cleanup($return, $output) + { if ($this->dir !== null) { - @chdir($currdir); + @chdir($this->currdir); } - foreach($output as $line) { - $this->log($line, ($this->passthru ? PROJECT_MSG_INFO : PROJECT_MSG_VERBOSE)); + $outloglevel = $this->logOutput ? Project::MSG_INFO : Project::MSG_VERBOSE; + foreach ($output as $line) { + $this->log($line, $outloglevel); } - - if($return != 0 && $this->checkreturn) - { - throw new BuildException("Task exited with code $return"); + + if ($this->returnProperty) { + $this->project->setProperty($this->returnProperty, $return); + } + + if ($this->outputProperty) { + $this->project->setProperty( + $this->outputProperty, implode("\n", $output) + ); + } + + if ($return != 0 && $this->checkreturn) { + throw new BuildException("Task exited with code $return"); } - - return $return; } + /** * The command to use. + * * @param mixed $command String or string-compatible (e.g. w/ __toString()). + * + * @return void */ - function setCommand($command) { + public function setCommand($command) + { $this->command = "" . $command; } - + + /** + * The executable to use. + * + * @param mixed $executable String or string-compatible (e.g. w/ __toString()). + * + * @return void + */ + public function setExecutable($executable) + { + $this->commandline->setExecutable((string)$executable); + } + /** * Whether to use escapeshellcmd() to escape command. - * @param boolean $escape + * + * @param boolean $escape If the command shall be escaped or not + * + * @return void */ - function setEscape($escape) { + public function setEscape($escape) + { $this->escape = (bool) $escape; } - + /** - * Specify the workign directory for executing this command. - * @param PhingFile $dir + * Specify the working directory for executing this command. + * + * @param PhingFile $dir Working directory + * + * @return void */ - function setDir(PhingFile $dir) { + public function setDir(PhingFile $dir) + { $this->dir = $dir; } - + /** * Specify OS (or muliple OS) that must match in order to execute this command. - * @param string $os + * + * @param string $os Operating system string (e.g. "Linux") + * + * @return void */ - function setOs($os) { + public function setOs($os) + { $this->os = (string) $os; } - + /** * File to which output should be written. - * @param PhingFile $output + * + * @param PhingFile $f Output log file + * + * @return void */ - function setOutput(PhingFile $f) { + public function setOutput(PhingFile $f) + { $this->output = $f; } - + /** * File to which error output should be written. - * @param PhingFile $output + * + * @param PhingFile $f Error log file + * + * @return void */ - function setError(PhingFile $f) { + public function setError(PhingFile $f) + { $this->error = $f; } - + /** - * Whether to use passthru the output. - * @param boolean $passthru + * Whether to use PHP's passthru() function instead of exec() + * + * @param boolean $passthru If passthru shall be used + * + * @return void */ - function setPassthru($passthru) { + public function setPassthru($passthru) + { $this->passthru = (bool) $passthru; } - - /** - * Whether to suppress all output and run in the background. - * @param boolean $spawn - */ - function setSpawn($spawn) { - $this->spawn = (bool) $spawn; - } + + /** + * Whether to log returned output as MSG_INFO instead of MSG_VERBOSE + * + * @param boolean $logOutput If output shall be logged visibly + * + * @return void + */ + public function setLogoutput($logOutput) + { + $this->logOutput = (bool) $logOutput; + } + + /** + * Whether to suppress all output and run in the background. + * + * @param boolean $spawn If the command is to be run in the background + * + * @return void + */ + public function setSpawn($spawn) + { + $this->spawn = (bool) $spawn; + } /** * Whether to check the return code. - * @param boolean $checkreturn + * + * @param boolean $checkreturn If the return code shall be checked + * + * @return void + */ + public function setCheckreturn($checkreturn) + { + $this->checkreturn = (bool) $checkreturn; + } + + /** + * The name of property to set to return value from exec() call. + * + * @param string $prop Property name + * + * @return void + */ + public function setReturnProperty($prop) + { + $this->returnProperty = $prop; + } + + /** + * The name of property to set to output value from exec() call. + * + * @param string $prop Property name + * + * @return void + */ + public function setOutputProperty($prop) + { + $this->outputProperty = $prop; + } + + /** + * Set level of log messages generated (default = verbose) + * + * @param string $level Log level + * + * @return void + */ + public function setLevel($level) + { + switch ($level) { + case 'error': + $this->logLevel = Project::MSG_ERR; + break; + case 'warning': + $this->logLevel = Project::MSG_WARN; + break; + case 'info': + $this->logLevel = Project::MSG_INFO; + break; + case 'verbose': + $this->logLevel = Project::MSG_VERBOSE; + break; + case 'debug': + $this->logLevel = Project::MSG_DEBUG; + break; + default: + throw new BuildException( + sprintf('Unknown log level "%s"', $level) + ); + } + } + + /** + * Creates a nested <arg> tag. + * + * @return CommandlineArgument Argument object */ - function setCheckreturn($checkreturn) { - $this->checkreturn = (bool) $checkreturn; + public function createArg() + { + return $this->commandline->createArgument(); } } diff --git a/buildscripts/phing/classes/phing/tasks/system/ExitTask.php b/buildscripts/phing/classes/phing/tasks/system/FailTask.php index 7e08d369..92306842 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ExitTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/FailTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ExitTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 260a7f3caa499a33f0d3982f9a5cc9db222475a6 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,10 +27,10 @@ require_once 'phing/Task.php'; * * @author Hans Lellelid <hans@xmpl.org> (Phing) * @author Nico Seessle <nico@seessle.de> (Ant) - * @version $Revision: 1.7 $ + * @version $Id$ * @package phing.tasks.system */ -class ExitTask extends Task { +class FailTask extends Task { private $message; private $ifCondition; diff --git a/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php b/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php index a2a42665..e9b556d3 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ForeachTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 7acb78ab792426fa7d4edec53496cff8da5923eb $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -20,6 +20,8 @@ */ require_once 'phing/Task.php'; +require_once 'phing/system/io/FileSystem.php'; +include_once 'phing/mappers/FileNameMapper.php'; include_once 'phing/tasks/system/PhingTask.php'; /** @@ -43,7 +45,7 @@ include_once 'phing/tasks/system/PhingTask.php'; * * @author Jason Hines <jason@greenhell.com> * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.9 $ + * @version $Id$ * @package phing.tasks.system */ class ForeachTask extends Task { @@ -54,7 +56,10 @@ class ForeachTask extends Task { /** Name of parameter to pass to callee */ private $param; - /** Delimter that separates items in $list */ + /** Name of absolute path parameter to pass to callee */ + private $absparam; + + /** Delimiter that separates items in $list */ private $delimiter = ','; /** @@ -63,11 +68,36 @@ class ForeachTask extends Task { */ private $callee; + /** Array of filesets */ + private $filesets = array(); + + /** Instance of mapper **/ + private $mapperElement; + + /** + * Array of filelists + * @var array + */ + private $filelists = array(); + /** * Target to execute. * @var string */ private $calleeTarget; + + /** + * Total number of files processed + * @var integer + */ + private $total_files = 0; + + /** + * Total number of directories processed + * @var integer + */ + private $total_dirs = 0; + function init() { $this->callee = $this->project->createTask("phingcall"); @@ -82,11 +112,8 @@ class ForeachTask extends Task { * @return void */ function main() { - if ($this->list === null) { - throw new BuildException("Missing list to iterate through"); - } - if (trim($this->list) === '') { - return; + if ($this->list === null && count($this->filesets) == 0 && count($this->filelists) == 0) { + throw new BuildException("Need either list, nested fileset or nested filelist to iterate through"); } if ($this->param === null) { throw new BuildException("You must supply a property name to set on each iteration in param"); @@ -99,15 +126,135 @@ class ForeachTask extends Task { $callee->setTarget($this->calleeTarget); $callee->setInheritAll(true); $callee->setInheritRefs(true); + $mapper = null; + + if ($this->mapperElement !== null) { + $mapper = $this->mapperElement->getImplementation(); + } + + if (trim($this->list)) { + $arr = explode($this->delimiter, $this->list); + + foreach ($arr as $value) { + $value = trim($value); + $premapped = ''; + if ($mapper !== null) { + $premapped = $value; + $value = $mapper->main($value); + if ($value === null) { + continue; + } + $value = array_shift($value); + } + $this->log("Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''), Project::MSG_VERBOSE); + $prop = $callee->createProperty(); + $prop->setOverride(true); + $prop->setName($this->param); + $prop->setValue($value); + $callee->main(); + } + } + + // filelists + foreach ($this->filelists as $fl) { + $srcFiles = $fl->getFiles($this->project); + + $this->process($callee, $fl->getDir($this->project), $srcFiles, array()); + } + + // filesets + foreach ($this->filesets as $fs) { + $ds = $fs->getDirectoryScanner($this->project); + $srcFiles = $ds->getIncludedFiles(); + $srcDirs = $ds->getIncludedDirectories(); + + $this->process($callee, $fs->getDir($this->project), $srcFiles, $srcDirs); + } + + $this->log("Processed {$this->total_dirs} directories and {$this->total_files} files", Project::MSG_VERBOSE); + } + + /** + * Processes a list of files & directories + * + * @param Task $callee + * @param PhingFile $fromDir + * @param array $srcFiles + * @param array $srcDirs + */ + protected function process(Task $callee, PhingFile $fromDir, $srcFiles, $srcDirs) + { + $mapper = null; - $arr = explode($this->delimiter, $this->list); + if ($this->mapperElement !== null) { + $mapper = $this->mapperElement->getImplementation(); + } + + $filecount = count($srcFiles); + $this->total_files += $filecount; + + for ($j = 0; $j < $filecount; $j++) { + $value = $srcFiles[$j]; + $premapped = ""; + + if ($this->absparam) { + $prop = $callee->createProperty(); + $prop->setOverride(true); + $prop->setName($this->absparam); + $prop->setValue($fromDir . FileSystem::getFileSystem()->getSeparator() . $value); + } + + if ($mapper !== null) { + $premapped = $value; + $value = $mapper->main($value); + if ($value === null) { + continue; + } + $value = array_shift($value); + } + + if ($this->param) { + $this->log("Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''), Project::MSG_VERBOSE); + $prop = $callee->createProperty(); + $prop->setOverride(true); + $prop->setName($this->param); + $prop->setValue($value); + } + + $callee->main(); + } + + $dircount = count($srcDirs); + $this->total_dirs += $dircount; - foreach ($arr as $value) { - $this->log("Setting param '$this->param' to value '$value'", PROJECT_MSG_VERBOSE); - $prop = $callee->createProperty(); - $prop->setOverride(true); - $prop->setName($this->param); - $prop->setValue($value); + for ($j = 0; $j < $dircount; $j++) { + $value = $srcDirs[$j]; + $premapped = ""; + + if ($this->absparam) { + $prop = $callee->createProperty(); + $prop->setOverride(true); + $prop->setName($this->absparam); + $prop->setValue($fromDir . FileSystem::getFileSystem()->getSeparator() . $value); + } + + if ($mapper !== null) { + $premapped = $value; + $value = $mapper->main($value); + if ($value === null) { + continue; + } + $value = array_shift($value); + } + + if ($this->param) { + $this->log("Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''), Project::MSG_VERBOSE); + $prop = $callee->createProperty(); + $prop->setOverride(true); + $prop->setName($this->param); + $prop->setValue($value); + } + $callee->main(); } } @@ -124,15 +271,50 @@ class ForeachTask extends Task { $this->param = (string) $param; } + function setAbsparam($absparam) { + $this->absparam = (string) $absparam; + } + function setDelimiter($delimiter) { $this->delimiter = (string) $delimiter; } /** + * Nested creator, adds a set of files (nested fileset attribute). + */ + function createFileSet() { + $num = array_push($this->filesets, new FileSet()); + return $this->filesets[$num-1]; + } + + /** + * Nested creator, creates one Mapper for this task + * + * @access public + * @return object The created Mapper type object + * @throws BuildException + */ + function createMapper() { + if ($this->mapperElement !== null) { + throw new BuildException("Cannot define more than one mapper", $this->location); + } + $this->mapperElement = new Mapper($this->project); + return $this->mapperElement; + } + + /** * @return Property */ function createProperty() { return $this->callee->createProperty(); } + /** + * Supports embedded <filelist> element. + * @return FileList + */ + public function createFileList() { + $num = array_push($this->filelists, new FileList()); + return $this->filelists[$num-1]; + } } diff --git a/buildscripts/phing/classes/phing/tasks/system/IfTask.php b/buildscripts/phing/classes/phing/tasks/system/IfTask.php index ab773355..cff06ce1 100644 --- a/buildscripts/phing/classes/phing/tasks/system/IfTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/IfTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: IfTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 4452f066ac71d51d3e2521d39cdee2caf4f7e9cc $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -67,7 +67,7 @@ require_once 'phing/tasks/system/SequentialTask.php'; * task before you use it the first time:</p> * * <pre><code> - * <taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" /> + * <taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" /> * </code></pre> * * <h3>Crude Example</h3> @@ -105,6 +105,7 @@ require_once 'phing/tasks/system/SequentialTask.php'; * </code> * * @author <a href="mailto:stefan.bodewig@freenet.de">Stefan Bodewig</a> + * @package phing.tasks.system */ class IfTask extends ConditionBase { @@ -148,16 +149,16 @@ class IfTask extends ConditionBase { } public function main() { - + if ($this->countConditions() > 1) { throw new BuildException("You must not nest more than one condition into <if>"); } if ($this->countConditions() < 1) { throw new BuildException("You must nest a condition into <if>"); } - $conditions = $this->getConditions(); - $c = $conditions[0]; - + $conditions = $this->getConditions(); + $c = $conditions[0]; + if ($c->evaluate()) { if ($this->thenTasks != null) { $this->thenTasks->main(); @@ -165,8 +166,8 @@ class IfTask extends ConditionBase { } else { $done = false; $sz = count($this->elseIfTasks); - for($i=0; $i < $sz && !$done; $i++) { - $ei = $this->elseIfTasks[$i]; + for($i=0; $i < $sz && !$done; $i++) { + $ei = $this->elseIfTasks[$i]; if ($ei->evaluate()) { $done = true; $ei->main(); @@ -183,6 +184,8 @@ class IfTask extends ConditionBase { /** * "Inner" class for IfTask. * This class has same basic structure as the IfTask, although of course it doesn't support <else> tags. + * + * @package phing.tasks.system */ class ElseIfTask extends ConditionBase { @@ -194,31 +197,31 @@ class ElseIfTask extends ConditionBase { } $this->thenTasks = $t; } - - /** - * @return boolean - */ + + /** + * @return boolean + */ public function evaluate() { - + if ($this->countConditions() > 1) { throw new BuildException("You must not nest more than one condition into <elseif>"); } if ($this->countConditions() < 1) { throw new BuildException("You must nest a condition into <elseif>"); } - - $conditions = $this->getConditions(); - $c = $conditions[0]; + + $conditions = $this->getConditions(); + $c = $conditions[0]; return $c->evaluate(); } - - /** - * - */ + + /** + * + */ public function main() { if ($this->thenTasks != null) { $this->thenTasks->main(); } } - }
\ No newline at end of file + } diff --git a/buildscripts/phing/classes/phing/tasks/system/ImportTask.php b/buildscripts/phing/classes/phing/tasks/system/ImportTask.php new file mode 100755 index 00000000..760380eb --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/ImportTask.php @@ -0,0 +1,136 @@ +<?php +/* + * $Id: 88eafadfcd59c0ce28f122926b7d5706b807a8e3 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/FileSystem.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/parser/ProjectConfigurator.php'; + +/** + * Imports another build file into the current project. + * + * Targets and properties of the imported file can be overrridden + * by targets and properties of the same name declared in the importing file. + * + * The imported file will have a new synthetic property of + * "phing.file.<projectname>" declared which gives the full path to the + * imported file. Additionally each target in the imported file will be + * declared twice: once with the normal name and once with "<projectname>." + * prepended. The "<projectname>.<targetname>" synthetic targets allow the + * importing file a mechanism to call the imported files targets as + * dependencies or via the <phing> or <phingcall> task mechanisms. + * + * @author Bryan Davis <bpd@keynetics.com> + * @version $Id: 88eafadfcd59c0ce28f122926b7d5706b807a8e3 $ + * @package phing.tasks.system + */ +class ImportTask extends Task { + + /** + * @var FileSystem + */ + protected $fs; + + /** + * @var PhingFile + */ + protected $file = null; + + /** + * @var bool + */ + protected $optional = false; + + /** + * Initialize task. + * @return void + */ + public function init () { + $this->fs = FileSystem::getFileSystem(); + } //end init + + + /** + * Set the file to import. + * @param string $f Path to file + * @return void + */ + public function setFile ($f) { + $this->file = $f; + } + + /** + * Is this include optional? + * @param bool $opt If true, do not stop the build if the file does not + * exist + * @return void + */ + public function setOptional ($opt) { + $this->optional = $opt; + } + + /** + * Parse a Phing build file and copy the properties, tasks, data types and + * targets it defines into the current project. + * + * @return void + */ + public function main () { + if (!isset($this->file)) { + throw new BuildException("Missing attribute 'file'"); + } + + $file = new PhingFile($this->file); + if (!$file->isAbsolute()) { + $file = new PhingFile($this->project->getBasedir(), $this->file); + } + if (!$file->exists()) { + $msg = "Unable to find build file: {$file->getPath()}"; + if ($this->optional) { + $this->log($msg . '... skipped'); + return; + } else { + throw new BuildException($msg); + } + } + + $ctx = $this->project->getReference("phing.parsing.context"); + $cfg = $ctx->getConfigurator(); + if (null !== $cfg && $cfg->isParsing()) { + // because there isn't a top level implicit target in phing like there is + // in Ant 1.6, we will be called as soon as our xml is parsed. This isn't + // really what we want to have happen. Instead we will register ourself + // with the parse context to be called at the end of the current file's + // parse phase. + $cfg->delayTaskUntilParseEnd($this); + + } else { + // Import xml file into current project scope + // Since this is delayed until after the importing file has been + // processed, the properties and targets of this new file may not take + // effect if they have alreday been defined in the outer scope. + $this->log("Importing configuration from {$file->getName()}", Project::MSG_VERBOSE); + ProjectConfigurator::configureProject($this->project, $file); + $this->log("Configuration imported.", Project::MSG_VERBOSE); + } + } //end main + +} //end ImportTask diff --git a/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php b/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php index ce9beee5..807a3cad 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: IncludePathTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: eaa0d6c5c7fb908d419cd6e22c7eccbf01506da7 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -34,7 +34,7 @@ include_once 'phing/types/Path.php'; * </code> * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.1 $ + * @version $Id$ * @package phing.tasks.system */ class IncludePathTask extends Task { @@ -107,7 +107,7 @@ class IncludePathTask extends Task { $new_parts = array_diff($add_parts, $curr_parts); if ($new_parts) { - $this->log("Prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts), PROJECT_MSG_VERBOSE); + $this->log("Prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts), Project::MSG_VERBOSE); set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts))); } diff --git a/buildscripts/phing/classes/phing/tasks/system/InputTask.php b/buildscripts/phing/classes/phing/tasks/system/InputTask.php index a5e1fdb9..3c7168fd 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/InputTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/InputTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: InputTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: ae986f84ca9d952b0e14f2df9f21657213ef5e47 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/input/MultipleChoiceInputRequest.php'; * @author Hans Lellelid <hans@xmpl.org> (Phing) * @author Ulrich Schmidt <usch@usch.net> (Ant) * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.6 $ + * @version $Id: ae986f84ca9d952b0e14f2df9f21657213ef5e47 $ * @package phing.tasks.system */ class InputTask extends Task { @@ -104,6 +104,10 @@ class InputTask extends Task { throw new BuildException("You must specify a value for propertyName attribute."); } + if ($this->message === "") { + throw new BuildException("You must specify a message for input task."); + } + if ($this->validargs !== null) { $accept = preg_split('/[\s,]+/', $this->validargs); diff --git a/buildscripts/phing/classes/phing/tasks/system/LoadFileTask.php b/buildscripts/phing/classes/phing/tasks/system/LoadFileTask.php new file mode 100644 index 00000000..ff7b7d3b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/LoadFileTask.php @@ -0,0 +1,119 @@ +<?php +/* + * $Id: d4796a6eb57300eca59f8b6f79e3dbcb08d1e346 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ +require_once 'phing/Task.php'; + +/** + * LoadFileTask + * + * Loads a (text) file and stores the contents in a property. + * Supports filterchains. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: d4796a6eb57300eca59f8b6f79e3dbcb08d1e346 $ + * @package phing.tasks.ext + */ +class LoadFileTask extends Task +{ + /** + * File to read + * @var PhingFile file + */ + private $file; + + /** + * Property to be set + * @var string $property + */ + private $property; + + /** + * Array of FilterChain objects + * @var FilterChain[] + */ + private $filterChains = array(); + + /** + * Set file to read + * @param PhingFile $file + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Convenience setter to maintain Ant compatibility (@see setFile()) + * @param PhingFile $file + */ + public function setSrcFile($srcFile) + { + $this->file = $srcFile; + } + + /** + * Set name of property to be set + * @param $property + * @return void + */ + public function setProperty($property) + { + $this->property = $property; + } + + /** + * Creates a filterchain + * + * @return object The created filterchain object + */ + function createFilterChain() { + $num = array_push($this->filterChains, new FilterChain($this->project)); + return $this->filterChains[$num-1]; + } + + /** + * Main method + * + * @return void + * @throws BuildException + */ + public function main() + { + if (empty($this->file)) { + throw new BuildException("Attribute 'file' required", $this->getLocation()); + } + + if (empty($this->property)) { + throw new BuildException("Attribute 'property' required", $this->getLocation()); + } + + // read file (through filterchains) + $contents = ""; + + $reader = FileUtils::getChainedReader(new FileReader($this->file), $this->filterChains, $this->project); + while(-1 !== ($buffer = $reader->read())) { + $contents .= $buffer; + } + $reader->close(); + + // publish as property + $this->project->setProperty($this->property, $contents); + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php b/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php index c5497fbd..b04be2e1 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: MatchingTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 1e1f6274f400b90c2344c8cdb5d3711030b8f44a $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -38,7 +38,7 @@ include_once 'phing/util/DirectoryScanner.php'; * @author Jon S. Stevens <jon@clearink.com> (Ant * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) * @author Bruce Atherton <bruce@callenish.com> (Ant) - * @version $Revision: 1.4 $ + * @version $Id: 1e1f6274f400b90c2344c8cdb5d3711030b8f44a $ * @package phing.tasks.system */ abstract class MatchingTask extends Task implements SelectorContainer { @@ -59,7 +59,7 @@ abstract class MatchingTask extends Task implements SelectorContainer { /** * @see ProjectComponent::setProject() */ - public function setProject(Project $project) { + public function setProject($project) { parent::setProject($project); $this->fileset->setProject($project); } diff --git a/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php b/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php index 9d5c1f31..934b991f 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: MkdirTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: e7e3dbd896d8d46cd8694fca10d1d9a7b3ce54fc $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,13 +26,19 @@ include_once 'phing/system/io/PhingFile.php'; * Task to create a directory. * * @author Andreas Aderhold, andi@binarycloud.com - * @version $Revision: 1.8 $ + * @version $Id$ * @package phing.tasks.system */ class MkdirTask extends Task { /** directory to create*/ private $dir; + + /** + * Mode to create directory with + * @var integer + */ + private $mode = 0755; /** * create the directory and all parents @@ -47,7 +53,7 @@ class MkdirTask extends Task { throw new BuildException("Unable to create directory as a file already exists with that name: " . $this->dir->getAbsolutePath()); } if (!$this->dir->exists()) { - $result = $this->dir->mkdirs(); + $result = $this->dir->mkdirs($this->mode); if (!$result) { $msg = "Directory " . $this->dir->getAbsolutePath() . " creation was not successful for an unknown reason"; throw new BuildException($msg, $this->location); @@ -60,5 +66,14 @@ class MkdirTask extends Task { function setDir(PhingFile $dir) { $this->dir = $dir; } + + /** + * Sets mode to create directory with + * @param mixed $mode + */ + function setMode($mode) + { + $this->mode = base_convert((int) $mode, 8, 10); + } } diff --git a/buildscripts/phing/classes/phing/tasks/system/MoveTask.php b/buildscripts/phing/classes/phing/tasks/system/MoveTask.php index a3e94536..e7041464 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/MoveTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/MoveTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: MoveTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 01e6d627d455729bfed47d603188d8c56f54d9e5 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,7 +35,7 @@ include_once 'phing/system/io/IOException.php'; * Source files and directories are only deleted when the file or * directory has been copied to the destination successfully. * - * @version $Revision: 1.8 $ + * @version $Id$ * @package phing.tasks.system */ class MoveTask extends CopyTask { @@ -45,7 +45,58 @@ class MoveTask extends CopyTask { $this->forceOverwrite = true; } + /** + * Validates attributes coming in from XML + * + * @access private + * @return void + * @throws BuildException + */ + protected function validateAttributes() { + if ($this->file !== null && $this->file->isDirectory()) { + if (($this->destFile !== null && $this->destDir !== null) + || ($this->destFile === null && $this->destDir === null)) { + throw new BuildException("One and only one of tofile and todir must be set."); + } + + if ($this->destFile === null) + { + $this->destFile = new PhingFile($this->destDir, $this->file->getName()); + } + + if ($this->destDir === null) + { + $this->destDir = $this->destFile->getParentFile(); + } + + $this->completeDirMap[$this->file->getAbsolutePath()] = $this->destFile->getAbsolutePath(); + + $this->file = null; + } else { + parent::validateAttributes(); + } + } + protected function doWork() { + if (count($this->completeDirMap) > 0) + { + foreach ($this->completeDirMap as $from => $to) + { + $f = new PhingFile($from); + $d = new PhingFile($to); + + $moved = false; + try { // try to rename + $this->log("Attempting to rename $from to $to", $this->verbosity); + $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->mode); + $f->delete(true); + $moved = true; + } catch (IOException $ioe) { + $moved = false; + $this->logError("Failed to rename $from to $to: " . $ioe->getMessage()); + } + } + } $copyMapSize = count($this->fileCopyMap); if ($copyMapSize > 0) { @@ -58,33 +109,18 @@ class MoveTask extends CopyTask { continue; } - $moved = false; $f = new PhingFile($from); $d = new PhingFile($to); - $moved = false; - try { // try to rename - $this->log("Attempting to rename $from to $to", $this->verbosity); - $this->renameFile($f, $d, $this->forceOverwrite); - $moved = true; - } catch (IOException $ioe) { - $moved = false; - $this->log("Failed to rename $from to $to: " . $ioe->getMessage(), $this->verbosity); - } - - if (!$moved) { - try { // try to move - $this->log("Moving $from to $to", $this->verbosity); + try { // try to move + $this->log("Moving $from to $to", $this->verbosity); - $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject()); + $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->mode); - $f = new PhingFile($fromFile); - $f->delete(); - } catch (IOException $ioe) { - $msg = "Failed to move $from to $to: " . $ioe->getMessage(); - throw new BuildException($msg, $this->location); - } - } // if !moved + $f->delete(); + } catch (IOException $ioe) { + $this->logError("Failed to move $from to $to: " . $ioe->getMessage(), $this->location); + } } // foreach fileCopyMap } // if copyMapSize @@ -96,7 +132,7 @@ class MoveTask extends CopyTask { $d = new PhingFile((string) $dir); if (!$d->exists()) { if (!$d->mkdirs()) { - $this->log("Unable to create directory " . $d->getAbsolutePath(), PROJECT_MSG_ERR); + $this->logError("Unable to create directory " . $d->getAbsolutePath()); } else { $count++; } @@ -160,38 +196,7 @@ class MoveTask extends CopyTask { try { $d->delete(); } catch (Exception $e) { - throw new BuildException("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage()); + $this->logError("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage()); } } - - /** - * Attempts to rename a file from a source to a destination. - * If overwrite is set to true, this method overwrites existing file - * even if the destination file is newer. - * Otherwise, the source f - * ile is renamed only if the destination file # - * is older than it. - */ - private function renameFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite) { - $renamed = true; - - // ensure that parent dir of dest file exists! - $parent = $destFile->getParentFile(); - if ($parent !== null) { - if (!$parent->exists()) { - $parent->mkdirs(); - } - } - if ($destFile->exists()) { - try { - $destFile->delete(); - } catch (Exception $e) { - throw new BuildException("Unable to remove existing file " . $destFile->__toString() . ": " . $e->getMessage()); - } - } - $renamed = $sourceFile->renameTo($destFile); - - return $renamed; - } } -?> diff --git a/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php b/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php index 34d4336d..2aec4db5 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: PhingCallTask.php 59 2006-04-28 14:49:47Z mrook $ - * + * $Id: 5d02fa25dc18b56093884ae756b1720aafb42937 $ + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -24,7 +24,7 @@ require_once 'phing/Task.php'; /** * Call another target in the same project. * - * <pre> + * <samp> * <target name="foo"> * <phingcall target="bar"> * <property name="property1" value="aaaaa" /> @@ -35,24 +35,44 @@ require_once 'phing/Task.php'; * <target name="bar" depends="init"> * <echo message="prop is ${property1} ${foo}" /> * </target> - * </pre> + * </samp> * - * <p>This only works as expected if neither property1 nor foo are - * defined in the project itself. + * This only works as expected if neither property1 nor foo are defined in the project itself. * * @author Andreas Aderhold <andi@binarycloud.com> * @copyright 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.9 $ + * @version $Id: 5d02fa25dc18b56093884ae756b1720aafb42937 $ * @access public * @package phing.tasks.system */ class PhingCallTask extends Task { + /** + * The called Phing task. + * + * @var PhingTask + */ private $callee; + + /** + * The target to call. + * + * @var string + */ private $subTarget; - // must match the default value of PhingTask#inheritAll + + /** + * Whether to inherit all properties from current project. + * + * @var boolean + */ private $inheritAll = true; - // must match the default value of PhingTask#inheritRefs + + /** + * Whether to inherit refs from current project. + * + * @var boolean + */ private $inheritRefs = false; /** @@ -67,7 +87,7 @@ class PhingCallTask extends Task { /** * If true, pass all references to the new Phing project. * Defaults to false. Future use. - * + * * @param boolean new value */ function setInheritRefs($inheritRefs) { @@ -75,6 +95,34 @@ class PhingCallTask extends Task { } /** + * Alias for createProperty + * @see createProperty() + */ + function createParam() { + if ($this->callee === null) { + $this->init(); + } + return $this->callee->createProperty(); + } + + /** + * Property to pass to the invoked target. + */ + function createProperty() { + if ($this->callee === null) { + $this->init(); + } + return $this->callee->createProperty(); + } + + /** + * Target to execute, required. + */ + function setTarget($target) { + $this->subTarget = (string) $target; + } + + /** * init this task by creating new instance of the phing task and * configuring it's by calling its own init method. */ @@ -82,6 +130,7 @@ class PhingCallTask extends Task { $this->callee = $this->project->createTask("phing"); $this->callee->setOwningTarget($this->getOwningTarget()); $this->callee->setTaskName($this->getTaskName()); + $this->callee->setHaltOnFailure(true); $this->callee->setLocation($this->getLocation()); $this->callee->init(); } @@ -91,17 +140,17 @@ class PhingCallTask extends Task { * @throws BuildException on validation failure or if the target didn't * execute */ - function main() { - - $this->log("Running PhingCallTask for target '" . $this->subTarget . "'", PROJECT_MSG_DEBUG); + function main() { + + $this->log("Running PhingCallTask for target '" . $this->subTarget . "'", Project::MSG_DEBUG); if ($this->callee === null) { $this->init(); } if ($this->subTarget === null) { - throw new BuildException("Attribute target is required.", $this->location); + throw new BuildException("Attribute target is required.", $this->getLocation()); } - + $this->callee->setPhingfile($this->project->getProperty("phing.file")); $this->callee->setTarget($this->subTarget); $this->callee->setInheritAll($this->inheritAll); @@ -109,31 +158,4 @@ class PhingCallTask extends Task { $this->callee->main(); } - /** - * Alias for createProperty - * @see createProperty() - */ - function createParam() { - if ($this->callee === null) { - $this->init(); - } - return $this->callee->createProperty(); - } - - /** - * Property to pass to the invoked target. - */ - function createProperty() { - if ($this->callee === null) { - $this->init(); - } - return $this->callee->createProperty(); - } - - /** - * Target to execute, required. - */ - function setTarget($target) { - $this->subTarget = (string) $target; - } } diff --git a/buildscripts/phing/classes/phing/tasks/system/PhingTask.php b/buildscripts/phing/classes/phing/tasks/system/PhingTask.php index e9883dd7..6ac0b5ac 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PhingTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PhingTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: PhingTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 2eec26f6ebaaeceb4eca76644de88bde7515f5dc $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -41,7 +41,7 @@ include_once 'phing/tasks/system/PropertyTask.php'; * </pre> * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.20 $ + * @version $Id: 2eec26f6ebaaeceb4eca76644de88bde7515f5dc $ * @package phing.tasks.system */ class PhingTask extends Task { @@ -151,46 +151,47 @@ class PhingTask extends Task { } // if no filesets are given stop here; else process filesets - if (empty($this->filesets)) { - return; - } - - // preserve old settings - $savedDir = $this->dir; - $savedPhingFile = $this->phingFile; - $savedTarget = $this->newTarget; - $buildFailed = false; - - // set no specific target for files in filesets - // [HL] I'm commenting this out; I don't know why this should not be supported! - // $this->newTarget = null; - - foreach($this->filesets as $fs) { - - $ds = $fs->getDirectoryScanner($this->project); - - $fromDir = $fs->getDir($this->project); - $srcFiles = $ds->getIncludedFiles(); - - foreach($srcFiles as $fname) { - $f = new PhingFile($ds->getbasedir(), $fname); - $f = $f->getAbsoluteFile(); - $this->phingFile = $f->getAbsolutePath(); - $this->dir = $f->getParentFile(); - $this->processFile(); // run Phing! + if (!empty($this->filesets)) { + // preserve old settings + $savedDir = $this->dir; + $savedPhingFile = $this->phingFile; + $savedTarget = $this->newTarget; + + // set no specific target for files in filesets + // [HL] I'm commenting this out; I don't know why this should not be supported! + // $this->newTarget = null; + + foreach($this->filesets as $fs) { + + $ds = $fs->getDirectoryScanner($this->project); + + $fromDir = $fs->getDir($this->project); + $srcFiles = $ds->getIncludedFiles(); + + foreach($srcFiles as $fname) { + $f = new PhingFile($ds->getbasedir(), $fname); + $f = $f->getAbsoluteFile(); + $this->phingFile = $f->getAbsolutePath(); + $this->dir = $f->getParentFile(); + $this->processFile(); // run Phing! + } + } + + // side effect free programming ;-) + $this->dir = $savedDir; + $this->phingFile = $savedPhingFile; + $this->newTarget = $savedTarget; + + // [HL] change back to correct dir + if ($this->dir !== null) { + chdir($this->dir->getAbsolutePath()); } - } - - // side effect free programming ;-) - $this->dir = $savedDir; - $this->phingFile = $savedPhingFile; - $this->newTarget = $savedTarget; - - // [HL] change back to correct dir - if ($this->dir !== null) { - chdir($this->dir->getAbsolutePath()); } + // Remove any dangling references to help the GC + foreach ($this->properties as $property) { + $property->setFallback(null); + } } /** @@ -199,27 +200,49 @@ class PhingTask extends Task { * @return void */ private function processFile() { - + + $buildFailed = false; $savedDir = $this->dir; $savedPhingFile = $this->phingFile; $savedTarget = $this->newTarget; + $savedBasedirAbsPath = null; // this is used to save the basedir *if* we change it + try { + if ($this->newProject === null) { $this->reinit(); } - if (($this->dir === null) && ($this->inheritAll)) { - $this->dir = $this->getProject()->getBaseDir(); - } $this->initializeProject(); + if ($this->dir !== null) { - $this->newProject->setBaseDir($this->dir); + + $dirAbsPath = $this->dir->getAbsolutePath(); + + // BE CAREFUL! -- when the basedir is changed for a project, + // all calls to getAbsolutePath() on a relative-path dir will + // be made relative to the project's basedir! This means + // that subsequent calls to $this->dir->getAbsolutePath() will be WRONG! + + // We need to save the current project's basedir first. + $savedBasedirAbsPath = $this->getProject()->getBasedir()->getAbsolutePath(); + + $this->newProject->setBasedir($this->dir); + + // Now we must reset $this->dir so that it continues to resolve to the same + // path. + $this->dir = new PhingFile($dirAbsPath); + if ($savedDir !== null) { // has been set explicitly $this->newProject->setInheritedProperty("project.basedir", $this->dir->getAbsolutePath()); - } + } + } else { - $this->dir = $this->getProject()->getBaseDir(); + + // Since we're not changing the basedir here (for file resolution), + // we don't need to worry about any side-effects in this scanrio. + $this->dir = $this->getProject()->getBasedir(); } $this->overrideProperties(); @@ -255,31 +278,37 @@ class PhingTask extends Task { } catch (Exception $e) { $buildFailed = true; - $this->log($e->getMessage(), PROJECT_MSG_ERR); - - // important!!! continue on to perform cleanup - // tasks. - } + $this->log($e->getMessage(), Project::MSG_ERR); + if (Phing::getMsgOutputLevel() <= Project::MSG_DEBUG) { + $lines = explode("\n", $e->getTraceAsString()); + foreach($lines as $line) { + $this->log($line, Project::MSG_DEBUG); + } + } + // important!!! continue on to perform cleanup tasks. + } + + + // reset environment values to prevent side-effects. - // } finally { - // restore values (prevent side-effects) - // !this must match code in catch () {} block! $this->newProject = null; $pkeys = array_keys($this->properties); foreach($pkeys as $k) { $this->properties[$k]->setProject(null); - } + } + $this->dir = $savedDir; $this->phingFile = $savedPhingFile; $this->newTarget = $savedTarget; - // [HL] change back to correct dir - if ($this->dir !== null) { - chdir($this->dir->getAbsolutePath()); + // If the basedir for any project was changed, we need to set that back here. + if ($savedBasedirAbsPath !== null) { + chdir($savedBasedirAbsPath); } - if ($this->haltOnFailure == true && $buildFailed == true) + if ($this->haltOnFailure && $buildFailed) { throw new BuildException("Execution of the target buildfile failed. Aborting."); + } } /** @@ -392,7 +421,7 @@ class PhingTask extends Task { if (!isset($projReferences[$refid])) { $this->log("Parent project doesn't contain any reference '" . $refid . "'", - PROJECT_MSG_WARN); + Project::MSG_WARN); continue; } @@ -449,8 +478,8 @@ class PhingTask extends Task { $copy->setProject($this->newProject); } elseif (in_array('setProject', get_class_methods(get_class($copy)))) { $copy->setProject($this->newProject); - } elseif ($copy instanceof Project) { - // don't copy the old "Project" itself + } elseif ($copy instanceof Project) { + // don't copy the old "Project" itself } else { $msg = "Error setting new project instance for " . "reference with id " . $oldKey; @@ -569,6 +598,8 @@ class PhingTask extends Task { /** * Helper class that implements the nested <reference> * element of <phing> and <phingcall>. + * + * @package phing.tasks.system */ class PhingReference extends Reference { diff --git a/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php b/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php index f1b72815..99316f7b 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: PhpEvalTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 8c46403ac685f362e310ffcceff5d4193bf09ef0 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ require_once 'phing/Task.php'; * modify internal Phing classes unless you know what you are doing. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.7 $ + * @version $Id$ * @package phing.tasks.system * * @todo Add support for evaluating expressions @@ -39,9 +39,27 @@ class PhpEvalTask extends Task { protected $expression; // Expression to evaluate protected $function; // Function to execute protected $class; // Class containing function to execute - protected $returnProperty; // name of property to set to return value + protected $returnProperty = null; // name of property to set to return value protected $params = array(); // parameters for function calls + protected $logLevel = Project::MSG_INFO; + + /** + * Set level of log messages generated (default = info) + * @param string $level + */ + public function setLevel($level) + { + switch ($level) + { + case "error": $this->logLevel = Project::MSG_ERR; break; + case "warning": $this->logLevel = Project::MSG_WARN; break; + case "info": $this->logLevel = Project::MSG_INFO; break; + case "verbose": $this->logLevel = Project::MSG_VERBOSE; break; + case "debug": $this->logLevel = Project::MSG_DEBUG; break; + } + } + /** Main entry point. */ function main() { @@ -57,15 +75,10 @@ class PhpEvalTask extends Task { throw new BuildException("You cannot use nested <param> tags when evaluationg a PHP expression.", $this->location); } - $retval = null; if ($this->function !== null) { - $retval = $this->callFunction(); + $this->callFunction(); } elseif ($this->expression !== null) { - $retval = $this->evalExpression(); - } - - if ($this->returnProperty !== null) { - $this->project->setProperty($this->returnProperty, $retval); + $this->evalExpression(); } } @@ -92,13 +105,16 @@ class PhpEvalTask extends Task { $params[] = $p->getValue(); } - $this->log("Calling PHP function: " . $h_func . "()"); + $this->log("Calling PHP function: " . $h_func . "()", $this->logLevel); foreach($params as $p) { - $this->log(" param: " . $p, PROJECT_MSG_VERBOSE); + $this->log(" param: " . $p, Project::MSG_VERBOSE); } $return = call_user_func_array($user_func, $params); - return $return; + + if ($this->returnProperty !== null) { + $this->project->setProperty($this->returnProperty, $return); + } } /** @@ -106,13 +122,18 @@ class PhpEvalTask extends Task { * @return mixed */ protected function evalExpression() { - $this->log("Evaluating PHP expression: " . $this->expression); + $this->log("Evaluating PHP expression: " . $this->expression, $this->logLevel); if (!StringHelper::endsWith(';', trim($this->expression))) { $this->expression .= ';'; } - $retval = null; - eval('$retval = ' . $this->expression); - return $retval; + + if ($this->returnProperty !== null) { + $retval = null; + eval('$retval = ' . $this->expression); + $this->project->setProperty($this->returnProperty, $retval); + } else { + eval($this->expression); + } } /** Set function to execute */ @@ -150,6 +171,8 @@ class PhpEvalTask extends Task { /** * Supports the <param> nested tag for PhpTask. + * + * @package phing.tasks.system */ class FunctionParam { diff --git a/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php b/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php index e7e12f33..7a337764 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: PropertyPromptTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: d2de9371732599b179facb97ef937b2cfbfbead2 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,39 +31,63 @@ include_once 'phing/system/io/ConsoleReader.php'; * * @author Hans Lellelid <hans@xmpl.org> (Phing) * @author Anthony J. Young-Garner <ajyoung@alum.mit.edu> (Ant) - * @version $Revision: 1.4 $ + * @version $Id$ * @package phing.tasks.system * @deprecated - in favor of the more capable InputTask */ class PropertyPromptTask extends Task { - + + /** + * The property name to set with the output. + * @var string + */ private $propertyName; // required + + /** + * The default value to use if no input is entered. + * @var string + */ private $defaultValue; - private $proposedValue; // required - private $promptText; // required + + /** + * The entered value. + * @var string + */ + private $proposedValue; + + /** + * The text to use for the prompt. + * @var string + */ + private $promptText; + + /** + * The character to put after the text. + * @var string + */ private $promptCharacter; - private $useExistingValue; - + /** - * Sets the prompt text that will be presented to the user. - * @param string $prompt - * @return void + * */ - public function addText($prompt) { - $this->setPromptText($prompt); - } + private $useExistingValue; /** * Run the PropertyPrompt task. * @throws BuildException */ public function main() { + $this->proposedValue = $this->project->getProperty($this->propertyName); $currentValue = $this->defaultValue; - if ($currentValue == "" && $this->proposedValue !== null) { $currentValue = $this->proposedValue; } - if (! (($this->useExistingValue === true) && ($this->proposedValue !== null))) { + + if ($currentValue == "" && $this->proposedValue !== null) { + $currentValue = $this->proposedValue; + } + + if ($this->useExistingValue !== true || $this->proposedValue === null) { - $this->log("Prompting user for " . $this->propertyName . ". " . $this->getDefaultMessage(), PROJECT_MSG_VERBOSE); + $this->log("Prompting user for " . $this->propertyName . ". " . $this->getDefaultMessage(), Project::MSG_VERBOSE); print "\n" . $this->promptText . " [" . $currentValue . "] " . $this->promptCharacter . " "; @@ -77,12 +101,12 @@ class PropertyPromptTask extends Task { $this->proposedValue = $this->defaultValue; } - if (empty($this->proposedValue)) { - $this->log("No value specified, using default.", PROJECT_MSG_VERBOSE); + if ($this->proposedValue === "") { + $this->log("No value specified, using default.", Project::MSG_VERBOSE); $this->proposedValue = $this->defaultValue; } - if (!empty($this->proposedValue)) { + if (isset($this->proposedValue)) { $this->project->setProperty($this->propertyName, $this->proposedValue); } @@ -166,7 +190,7 @@ class PropertyPromptTask extends Task { /** * Sets the terminating character used to * punctuate the prompt text (default is "?"). - * @param newPromptcharacter java.lang.String + * @param string $newPromptcharacter */ public function setPromptCharacter($newPromptcharacter) { $this->promptCharacter = $newPromptcharacter; @@ -174,7 +198,7 @@ class PropertyPromptTask extends Task { /** * Sets text of the prompt. - * @param newPrompttext java.lang.String + * @param string $newPrompttext */ public function setPromptText($newPrompttext) { $this->promptText = $newPrompttext; @@ -191,11 +215,20 @@ class PropertyPromptTask extends Task { /** * - * - * @param boolean newUseExistingValue + * @param boolean $newUseExistingValue */ public function setUseExistingValue($newUseExistingValue) { $this->useExistingValue = $newUseExistingValue; } + /** + * Sets the prompt text that will be presented to the user. + * @param string $prompt + * @return void + */ + public function addText($prompt) { + $this->setPromptText($prompt); + } + + } diff --git a/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php b/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php index d6168e44..0d8854c8 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: PropertyTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: e6d7123b6331d5032ad1e67967cf54ef2aae3f7f $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,7 +28,7 @@ include_once 'phing/system/util/Properties.php'; * * @author Andreas Aderhold <andi@binarycloud.com> * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision$ + * @version $Id: e6d7123b6331d5032ad1e67967cf54ef2aae3f7f $ * @package phing.tasks.system */ class PropertyTask extends Task { @@ -71,15 +71,15 @@ class PropertyTask extends Task { function setValue($value) { $this->value = (string) $value; } - - /** - * Sets value of property to CDATA tag contents. - * @param string $values - * @since 2.2.0 - */ - public function addText($value) { - $this->setValue($value); - } + + /** + * Sets value of property to CDATA tag contents. + * @param string $values + * @since 2.2.0 + */ + public function addText($value) { + $this->setValue($value); + } /** Get the value of current property component. */ function getValue() { @@ -182,9 +182,9 @@ class PropertyTask extends Task { return (string) $this->value; } - /** - * @param Project $p - */ + /** + * @param Project $p + */ function setFallback($p) { $this->fallback = $p; } @@ -248,7 +248,7 @@ class PropertyTask extends Task { if ( substr($prefix, strlen($prefix)-1) == '.' ) { $prefix .= "."; } - $this->log("Loading Environment $prefix", PROJECT_MSG_VERBOSE); + $this->log("Loading Environment $prefix", Project::MSG_VERBOSE); foreach($_ENV as $key => $value) { $props->setProperty($prefix . '.' . $key, $value); } @@ -281,7 +281,7 @@ class PropertyTask extends Task { if ($this->project->getUserProperty($name) === null || $this->override) { $this->project->setInheritedProperty($name, $value); } else { - $this->log("Override ignored for " . $name, PROJECT_MSG_VERBOSE); + $this->log("Override ignored for " . $name, Project::MSG_VERBOSE); } } else { if ($this->override) { @@ -298,13 +298,13 @@ class PropertyTask extends Task { */ protected function loadFile(PhingFile $file) { $props = new Properties(); - $this->log("Loading ". $file->getAbsolutePath(), PROJECT_MSG_INFO); + $this->log("Loading ". $file->getAbsolutePath(), Project::MSG_INFO); try { // try to load file if ($file->exists()) { $props->load($file); $this->addProperties($props); } else { - $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", PROJECT_MSG_WARN); + $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", Project::MSG_WARN); } } catch (IOException $ioe) { throw new BuildException("Could not load properties from file.", $ioe); @@ -356,7 +356,7 @@ class PropertyTask extends Task { if ($propertyName === $name) { // Should we maybe just log this as an error & move on? - // $this->log("Property ".$name." was circularly defined.", PROJECT_MSG_ERR); + // $this->log("Property ".$name." was circularly defined.", Project::MSG_ERR); throw new BuildException("Property ".$name." was circularly defined."); } @@ -373,7 +373,7 @@ class PropertyTask extends Task { $sb .= $fragment; } - $this->log("Resolved Property \"$value\" to \"$sb\"", PROJECT_MSG_DEBUG); + $this->log("Resolved Property \"$value\" to \"$sb\"", Project::MSG_DEBUG); $value = $sb; $props->setProperty($name, $value); diff --git a/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php b/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php index dc7cfeb7..d49c47f2 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ReflexiveTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 3dcb1ad6e9fd3b2801c1fe3bcbaf2fcab8ea6018 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -43,7 +43,7 @@ require_once 'phing/Task.php'; * </code> * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.11 $ + * @version $Id$ * @package phing.tasks.system */ class ReflexiveTask extends Task { @@ -105,24 +105,24 @@ class ReflexiveTask extends Task { $files[] = new PhingFile($dir, $fname); } } catch (BuildException $be) { - $this->log($be->getMessage(), PROJECT_MSG_WARN); + $this->log($be->getMessage(), Project::MSG_WARN); } } } $this->log("Applying reflexive processing to " . count($files) . " files."); - // These "slots" allow filters to retrieve information about the currently-being-process files - $slot = $this->getRegisterSlot("currentFile"); - $basenameSlot = $this->getRegisterSlot("currentFile.basename"); + // These "slots" allow filters to retrieve information about the currently-being-process files + $slot = $this->getRegisterSlot("currentFile"); + $basenameSlot = $this->getRegisterSlot("currentFile.basename"); foreach($files as $file) { - // set the register slots - - $slot->setValue($file->getPath()); - $basenameSlot->setValue($file->getName()); - + // set the register slots + + $slot->setValue($file->getPath()); + $basenameSlot->setValue($file->getName()); + // 1) read contents of file, pulling through any filters $in = null; try { @@ -134,7 +134,7 @@ class ReflexiveTask extends Task { $in->close(); } catch (Exception $e) { if ($in) $in->close(); - $this->log("Erorr reading file: " . $e->getMessage(), PROJECT_MSG_WARN); + $this->log("Erorr reading file: " . $e->getMessage(), Project::MSG_WARN); } try { @@ -142,14 +142,14 @@ class ReflexiveTask extends Task { $out = new FileWriter($file); $out->write($contents); $out->close(); - $this->log("Applying reflexive processing to " . $file->getPath(), PROJECT_MSG_VERBOSE); + $this->log("Applying reflexive processing to " . $file->getPath(), Project::MSG_VERBOSE); } catch (Exception $e) { if ($out) $out->close(); - $this->log("Error writing file back: " . $e->getMessage(), PROJECT_MSG_WARN); + $this->log("Error writing file back: " . $e->getMessage(), Project::MSG_WARN); } } } -}
\ No newline at end of file +} diff --git a/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php b/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php index b468afb5..bdd707a2 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ResolvePathTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 9635ed3f6605f5ed64b74e85731dbcd3ad43ce0f $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -39,7 +39,7 @@ require_once 'phing/Task.php'; * - Possibly integrate this with PackageAsPath, for handling/resolving dot-path paths. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.6 $ + * @version $Id$ * @package phing.tasks.system */ class ResolvePathTask extends Task { @@ -54,6 +54,11 @@ class ResolvePathTask extends Task { private $dir; /** + * Log level + */ + private $logLevel = Project::MSG_VERBOSE; + + /** * Set the name of the property to set. * @param string $v Property name * @return void @@ -90,6 +95,38 @@ class ResolvePathTask extends Task { } /** + * Set level of log messages generated (default = verbose) + * + * @param string $level Log level + * + * @return void + */ + public function setLevel($level) + { + switch ($level) { + case 'error': + $this->logLevel = Project::MSG_ERR; + break; + case 'warning': + $this->logLevel = Project::MSG_WARN; + break; + case 'info': + $this->logLevel = Project::MSG_INFO; + break; + case 'verbose': + $this->logLevel = Project::MSG_VERBOSE; + break; + case 'debug': + $this->logLevel = Project::MSG_DEBUG; + break; + default: + throw new BuildException( + sprintf('Unknown log level "%s"', $level) + ); + } + } + + /** * Perform the resolution & set property. */ public function main() { @@ -103,11 +140,11 @@ class ResolvePathTask extends Task { throw new BuildException("You must specify a path to resolve", $this->getLocation()); } - $fs = FileSystem::getFileSystem(); - + $fs = FileSystem::getFileSystem(); + // if dir attribute was specified then we should // use that as basedir to which file was relative. - // -- unless the file specified is an absolute path + // -- unless the file specified is an absolute path if ($this->dir !== null && !$fs->isAbsolute(new PhingFile($this->file))) { $resolved = new PhingFile($this->dir->getPath(), $this->file); } else { @@ -115,7 +152,7 @@ class ResolvePathTask extends Task { $resolved = $this->project->resolveFile($this->file); } - $this->log("Resolved " . $this->file . " to " . $resolved->getAbsolutePath(), PROJECT_MSG_INFO); + $this->log("Resolved " . $this->file . " to " . $resolved->getAbsolutePath(), $this->logLevel); $this->project->setProperty($this->propertyName, $resolved->getAbsolutePath()); } diff --git a/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php b/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php index 50327e3f..d080deda 100644 --- a/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: SequentialTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: e6be0ff54ade0fb900d101759d8788590e769831 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,11 +31,12 @@ require_once 'phing/TaskContainer.php'; * sequential task. * * @since 2.1.2 + * @package phing.tasks.system */ class SequentialTask extends Task implements TaskContainer { /** Optional Vector holding the nested tasks */ - private $nestedTasks = array(); + protected $nestedTasks = array(); /** * Add a nested task to Sequential. @@ -50,8 +51,8 @@ class SequentialTask extends Task implements TaskContainer { * @throws BuildException if one of the nested tasks fails. */ public function main() { - foreach($this->nestedTasks as $task) { - $task->perform(); - } + foreach($this->nestedTasks as $task) { + $task->perform(); + } } } diff --git a/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php b/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php index 4a90e106..84552d69 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php @@ -1,7 +1,7 @@ <?php /* - * $Id: TaskdefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: df52def0bb44ce1b0909f5e8858e79b2ef88ca0f $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,6 +21,7 @@ */ require_once 'phing/Task.php'; +include_once 'phing/system/io/PhingFile.php'; /** * Register a task for use within a buildfile. @@ -42,7 +43,7 @@ require_once 'phing/Task.php'; * (right now these are just too simple to really justify creating an abstract class) * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.11 $ + * @version $Id: df52def0bb44ce1b0909f5e8858e79b2ef88ca0f $ * @package phing.tasks.system */ class TaskdefTask extends Task { @@ -68,11 +69,17 @@ class TaskdefTask extends Task { * Refid to already defined classpath */ private $classpathId; + + /** + * Name of file to load multiple definitions from. + * @var string + */ + private $typeFile; /** * Set the classpath to be used when searching for component being defined * - * @param Path $classpath An Path object containing the classpath. + * @param Path $classpath A Path object containing the classpath. */ public function setClasspath(Path $classpath) { if ($this->classpath === null) { @@ -84,6 +91,8 @@ class TaskdefTask extends Task { /** * Create the classpath to be used when searching for component being defined + * + * @return Path */ public function createClasspath() { if ($this->classpath === null) { @@ -116,12 +125,41 @@ class TaskdefTask extends Task { $this->classname = $class; } + /** + * Sets the file of definitionas to use to use. + * @param string $file + */ + public function setFile($file) { + $this->typeFile = $file; + } + /** Main entry point */ public function main() { - if ($this->name === null || $this->classname === null) { + if ($this->typeFile === null && + ($this->name === null || $this->classname === null)) { throw new BuildException("You must specify name and class attributes for <taskdef>."); } - $this->log("Task " . $this->name . " will be handled by class " . $this->classname, PROJECT_MSG_VERBOSE); - $this->project->addTaskDefinition($this->name, $this->classname, $this->classpath); + if ($this->typeFile == null) { + $this->log("Task " . $this->name . " will be handled by class " . $this->classname, Project::MSG_VERBOSE); + $this->project->addTaskDefinition($this->name, $this->classname, $this->classpath); + } else { + try { // try to load taskdefs given in file + $props = new Properties(); + $in = new PhingFile((string) $this->typeFile); + + if ($in === null) { + throw new BuildException("Can't load task list {$this->typeFile}"); + } + $props->load($in); + + $enum = $props->propertyNames(); + foreach($enum as $key) { + $value = $props->getProperty($key); + $this->project->addTaskDefinition($key, $value, $this->classpath); + } + } catch (IOException $ioe) { + throw new BuildException("Can't load task list {$this->typeFile}"); + } + } } } diff --git a/buildscripts/phing/classes/phing/tasks/system/TouchTask.php b/buildscripts/phing/classes/phing/tasks/system/TouchTask.php index 6c6c4080..3c45d0d3 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TouchTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TouchTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: TouchTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: e581b40ff4e3eac5f62a32b48b4a22285cbc51c1 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/system/io/IOException.php'; * * If the file to touch doesn't exist, an empty one is created. * - * @version $Revision: 1.12 $ + * @version $Id$ * @package phing.tasks.system */ class TouchTask extends Task { @@ -117,7 +117,7 @@ class TouchTask extends Task { function _touch() { if ($this->file !== null) { if (!$this->file->exists()) { - $this->log("Creating " . $this->file->__toString(), PROJECT_MSG_INFO); + $this->log("Creating " . $this->file->__toString(), Project::MSG_INFO); try { // try to create file $this->file->createNewFile(); } catch(IOException $ioe) { diff --git a/buildscripts/phing/classes/phing/tasks/system/TryCatchTask.php b/buildscripts/phing/classes/phing/tasks/system/TryCatchTask.php new file mode 100644 index 00000000..b27d829b --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/TryCatchTask.php @@ -0,0 +1,123 @@ +<?php +/* + * $Id: acc9e5d431141ae13ea43c1ed1d3177a4fb60bf9 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/Task.php'; + +/** + * A wrapper task that lets you run tasks(s) when another set + * of tasks fails. + * + * Inspired by {@link http://ant-contrib.sourceforge.net/tasks/tasks/trycatch.html} + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: acc9e5d431141ae13ea43c1ed1d3177a4fb60bf9 $ + * @package phing.tasks.system + */ +class TryCatchTask extends Task +{ + protected $propertyName = ""; + + protected $tryContainer = null; + protected $catchContainer = null; + protected $finallyContainer = null; + + /** + * Main method + * + * @throws BuildException + * @return void + */ + public function main() + { + $exc = null; + + if (empty($this->tryContainer)) { + throw new BuildException('A nested <try> element is required'); + } + + try { + $this->tryContainer->perform(); + } catch (BuildException $e) { + if (!empty($this->propertyName)) { + $this->project->setProperty($this->propertyName, $e->getMessage()); + } + + if (!empty($this->referenceName)) { + $this->project->addReference($this->referenceName, $e); + } + + if (!empty($this->catchContainer)) { + $this->catchContainer->perform(); + } else { + $exc = $e; + } + } + + if (!empty($this->finallyContainer)) { + $this->finallyContainer->perform(); + } + + if (!empty($exc)) { + throw $exc; + } + } + + /** + * Sets the name of the property that will + * contain the exception message. + * + * @param string $property + */ + public function setProperty($property) + { + $this->propertyName = (string) $property; + } + + /** + * Add nested <try> element + * + * @param SequentialTask $container + */ + public function addTry(SequentialTask $container) + { + $this->tryContainer = $container; + } + + /** + * Add nested <catch> element + * + * @param SequentialTask $container + */ + public function addCatch(SequentialTask $container) + { + $this->catchContainer = $container; + } + + /** + * Add nested <finally> element + * + * @param SequentialTask $container + */ + public function addFinally(SequentialTask $container) + { + $this->finallyContainer = $container; + } +} diff --git a/buildscripts/phing/classes/phing/tasks/system/TstampTask.php b/buildscripts/phing/classes/phing/tasks/system/TstampTask.php index 9341c3dd..44f2c3f0 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TstampTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TstampTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: TstampTask.php 58 2006-04-28 14:41:04Z mrook $ + * $Id: c0693134153e6095ab198edb5cf204f53bb7ba69 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,41 +27,41 @@ require_once 'phing/Task.php'; * * Based on Ant's Tstamp task. * - * @author Michiel Rook <michiel@trendserver.nl> - * @version $Revision: 1.6 $ + * @author Michiel Rook <mrook@php.net> + * @version $Id$ * @package phing.tasks.system * @since 2.2.0 */ class TstampTask extends Task { - private $customFormats = array(); - - private $prefix = ""; - - /** - * Set a prefix for the properties. If the prefix does not end with a "." - * one is automatically added. - * @param prefix the prefix to use. - */ - public function setPrefix($prefix) - { - $this->prefix = $prefix; - - if (!empty($this->prefix)) - { - $this->prefix.= "."; - } - } - + private $customFormats = array(); + + private $prefix = ""; + + /** + * Set a prefix for the properties. If the prefix does not end with a "." + * one is automatically added. + * @param prefix the prefix to use. + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + + if (!empty($this->prefix)) + { + $this->prefix.= "."; + } + } + /** * Adds a custom format * - * @param TstampCustomFormat custom format + * @param TstampCustomFormat custom format */ - public function addFormat(TstampCustomFormat $cf) - { - $this->customFormats[] = $cf; - } + public function addFormat(TstampCustomFormat $cf) + { + $this->customFormats[] = $cf; + } /** * Create the timestamps. Custom ones are done before @@ -71,21 +71,21 @@ class TstampTask extends Task */ public function main() { - foreach ($this->customFormats as $cf) - { - $cf->execute($this); - } - - $dstamp = strftime('%Y%m%d'); - $this->prefixProperty('DSTAMP', $dstamp); - - $tstamp = strftime('%H%M'); - $this->prefixProperty('TSTAMP', $tstamp); - - $today = strftime('%B %d %Y'); - $this->prefixProperty('TODAY', $today); - } - + foreach ($this->customFormats as $cf) + { + $cf->execute($this); + } + + $dstamp = strftime('%Y%m%d'); + $this->prefixProperty('DSTAMP', $dstamp); + + $tstamp = strftime('%H%M'); + $this->prefixProperty('TSTAMP', $tstamp); + + $today = strftime('%B %d %Y'); + $this->prefixProperty('TODAY', $today); + } + /** * helper that encapsulates prefix logic and property setting * policy (i.e. we use setNewProperty instead of setProperty). @@ -96,73 +96,76 @@ class TstampTask extends Task } } +/** + * @package phing.tasks.system + */ class TstampCustomFormat { - private $propertyName = ""; - private $pattern = ""; - private $locale = ""; - - /** - * The property to receive the date/time string in the given pattern - * - * @param propertyName the name of the property. - */ - public function setProperty($propertyName) - { - $this->propertyName = $propertyName; - } + private $propertyName = ""; + private $pattern = ""; + private $locale = ""; + + /** + * The property to receive the date/time string in the given pattern + * + * @param propertyName the name of the property. + */ + public function setProperty($propertyName) + { + $this->propertyName = $propertyName; + } - /** - * The date/time pattern to be used. The values are as - * defined by the PHP strftime() function. - * - * @param pattern - */ - public function setPattern($pattern) - { - $this->pattern = $pattern; - } - - /** - * The locale used to create date/time string. - * - * @param locale - */ - public function setLocale($locale) - { - $this->locale = $locale; - } - - /** - * validate parameter and execute the format. - * - * @param TstampTask reference to task - */ - public function execute(TstampTask $tstamp) - { - if (empty($this->propertyName)) - { - throw new BuildException("property attribute must be provided"); - } + /** + * The date/time pattern to be used. The values are as + * defined by the PHP strftime() function. + * + * @param pattern + */ + public function setPattern($pattern) + { + $this->pattern = $pattern; + } + + /** + * The locale used to create date/time string. + * + * @param locale + */ + public function setLocale($locale) + { + $this->locale = $locale; + } + + /** + * validate parameter and execute the format. + * + * @param TstampTask reference to task + */ + public function execute(TstampTask $tstamp) + { + if (empty($this->propertyName)) + { + throw new BuildException("property attribute must be provided"); + } - if (empty($this->pattern)) - { - throw new BuildException("pattern attribute must be provided"); - } - - if (!empty($this->locale)) - { - setlocale(LC_ALL, $this->locale); - } - - $value = strftime($this->pattern); - $tstamp->prefixProperty($this->propertyName, $value); - - if (!empty($this->locale)) - { - // reset locale - setlocale(LC_ALL, NULL); - } - } + if (empty($this->pattern)) + { + throw new BuildException("pattern attribute must be provided"); + } + + if (!empty($this->locale)) + { + setlocale(LC_ALL, $this->locale); + } + + $value = strftime($this->pattern); + $tstamp->prefixProperty($this->propertyName, $value); + + if (!empty($this->locale)) + { + // reset locale + setlocale(LC_ALL, NULL); + } + } } -?> + diff --git a/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php b/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php index de058c90..c03e716d 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: TypedefTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 6122dcb36b79ffe3c3fb430a0b4586d9d145410b $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -43,7 +43,7 @@ require_once 'phing/Task.php'; * (right now these are just too simple to really justify creating an abstract class) * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.7 $ + * @version $Id$ * @package phing.tasks.system */ class TypedefTask extends Task { @@ -71,7 +71,7 @@ class TypedefTask extends Task { /** * Set the classpath to be used when searching for component being defined * - * @param Path $classpath An Path object containing the classpath. + * @param Path $classpath A Path object containing the classpath. */ public function setClasspath(Path $classpath) { if ($this->classpath === null) { @@ -83,6 +83,8 @@ class TypedefTask extends Task { /** * Create the classpath to be used when searching for component being defined + * + * @return Path */ public function createClasspath() { if ($this->classpath === null) { diff --git a/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php b/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php index 720fae12..1954fe88 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: UpToDateTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 5b0af63dfa9acb85374dcdd2d7fd866ce81391d0 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -21,6 +21,7 @@ require_once 'phing/Task.php'; include_once 'phing/tasks/system/condition/Condition.php'; +include_once 'phing/tasks/system/PropertyTask.php'; include_once 'phing/util/DirectoryScanner.php'; include_once 'phing/util/SourceFileScanner.php'; include_once 'phing/mappers/MergeMapper.php'; @@ -33,7 +34,7 @@ include_once 'phing/mappers/MergeMapper.php'; * @author William Ferguson <williamf@mincom.com> (Ant) * @author Hiroaki Nakamura <hnakamur@mc.neweb.ne.jp> (Ant) * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.6 $ + * @version $Id$ * @package phing.tasks.system */ class UpToDateTask extends Task implements Condition { @@ -43,6 +44,7 @@ class UpToDateTask extends Task implements Condition { private $_sourceFile; private $_targetFile; private $sourceFileSets = array(); + private $_filelists = array(); protected $mapperElement = null; @@ -57,6 +59,14 @@ class UpToDateTask extends Task implements Condition { } /** + * Get property name + * @param property the name of the property to set if Target is up-to-date. + */ + public function getProperty() { + return $this->_property; + } + + /** * The value to set the named property to if the target file is more * up-to-date than (each of) the source file(s). Defaults to 'true'. * @@ -101,6 +111,8 @@ class UpToDateTask extends Task implements Condition { /** * Nested <srcfiles> element. + * + * @deprecated Deprecated since Phing 2.4.0 */ public function createSrcfiles() { $fs = new FileSet(); @@ -109,6 +121,22 @@ class UpToDateTask extends Task implements Condition { } /** + * Nested <fileset> element. + */ + public function addFileset(FileSet $fs) { + $this->sourceFileSets[] = $fs; + } + + /** + * Supports embedded <filelist> element. + * @return FileList + */ + public function createFileList() { + $num = array_push($this->_filelists, new FileList()); + return $this->_filelists[$num-1]; + } + + /** * Defines the FileNameMapper to use (nested mapper element). */ public function createMapper() { @@ -126,15 +154,15 @@ class UpToDateTask extends Task implements Condition { * @return boolean */ public function evaluate() { - if (count($this->sourceFileSets) === 0 && $this->_sourceFile === null) { + if (count($this->sourceFileSets) == 0 && count($this->_filelists) == 0 && $this->_sourceFile === null) { throw new BuildException("At least one srcfile or a nested " - . "<srcfiles> element must be set."); + . "<fileset> or <filelist> element must be set."); } - if (count($this->sourceFileSets) > 0 && $this->_sourceFile !== null) { + if ((count($this->sourceFileSets) > 0 || count($this->_filelists) > 0) && $this->_sourceFile !== null) { throw new BuildException("Cannot specify both the srcfile " - . "attribute and a nested <srcfiles> " - . "element."); + . "attribute and a nested <fileset> " + . "or <filelist> element."); } if ($this->_targetFile === null && $this->mapperElement === null) { @@ -161,6 +189,13 @@ class UpToDateTask extends Task implements Condition { $ds->getIncludedFiles()); } + for($i=0,$size=count($this->_filelists); $i < $size && $upToDate; $i++) { + $fl = $this->_filelists[$i]; + $srcFiles = $fl->getFiles($this->project); + $upToDate = $upToDate && $this->scanDir($fs->getDir($this->project), + $srcFiles); + } + if ($this->_sourceFile !== null) { if ($this->mapperElement === null) { $upToDate = $upToDate && @@ -189,13 +224,18 @@ class UpToDateTask extends Task implements Condition { } $upToDate = $this->evaluate(); if ($upToDate) { - $this->project->setNewProperty($this->_property, $this->getValue()); + $property = $this->project->createTask('property'); + $property->setName($this->getProperty()); + $property->setValue($this->getValue()); + $property->setOverride(true); + $property->main(); // execute + if ($this->mapperElement === null) { $this->log("File \"" . $this->_targetFile->getAbsolutePath() - . "\" is up-to-date.", PROJECT_MSG_VERBOSE); + . "\" is up-to-date.", Project::MSG_VERBOSE); } else { $this->log("All target files are up-to-date.", - PROJECT_MSG_VERBOSE); + Project::MSG_VERBOSE); } } } diff --git a/buildscripts/phing/classes/phing/tasks/system/WaitForTask.php b/buildscripts/phing/classes/phing/tasks/system/WaitForTask.php new file mode 100755 index 00000000..00bcff1e --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/system/WaitForTask.php @@ -0,0 +1,188 @@ +<?php +/* + * $Id: dae67bf2b9c154d4614f30e9ba85c16782550bb3 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; + +/** + * Based on Apache Ant Wait For: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id$ + * @package phing.tasks.system + */ +class WaitForTask extends ConditionBase +{ + const ONE_MILLISECOND = 1; + const ONE_SECOND = 1000; + const ONE_MINUTE = 60000; + const ONE_HOUR = 3600000; + const ONE_DAY = 86400000; + const ONE_WEEK = 604800000; + + const DEFAULT_MAX_WAIT_MILLIS = 180000; + const DEFAULT_CHECK_MILLIS = 500; + + protected $maxWait = self::DEFAULT_MAX_WAIT_MILLIS; + protected $maxWaitMultiplier = self::ONE_MILLISECOND; + + protected $checkEvery = self::DEFAULT_CHECK_MILLIS; + protected $checkEveryMultiplier = self::ONE_MILLISECOND; + + protected $timeoutProperty = null; + + /** + * Set the maximum length of time to wait. + * @param int $maxWait + */ + public function setMaxWait($maxWait) + { + $this->maxWait = (int) $maxWait; + } + + /** + * Set the max wait time unit + * @param string $maxWaitUnit + */ + public function setMaxWaitUnit($maxWaitUnit) + { + $this->maxWaitMultiplier = $this->_convertUnit($maxWaitUnit); + } + + /** + * Set the time between each check + * @param int $checkEvery + */ + public function setCheckEvery($checkEvery) + { + $this->checkEvery = (int) $checkEvery; + } + + /** + * Set the check every time unit + * @param string $checkEveryUnit + */ + public function setCheckEveryUnit($checkEveryUnit) + { + $this->checkEveryMultiplier = $this->_convertUnit($checkEveryUnit); + } + + /** + * Name of the property to set after a timeout. + * @param string $timeoutProperty + */ + public function setTimeoutProperty($timeoutProperty) + { + $this->timeoutProperty = $timeoutProperty; + } + + /** + * Convert the unit to a multipler. + * @param string $unit + */ + protected function _convertUnit($unit) + { + switch ($unit) { + case "week": { + return self::ONE_WEEK; + } + + case "day": { + return self::ONE_DAY; + } + + case "hour": { + return self::ONE_HOUR; + } + + case "minute": { + return self::ONE_MINUTE; + } + + case "second": { + return self::ONE_SECOND; + } + + case "millisecond": { + return self::ONE_MILLISECOND; + } + + default: { + throw new BuildException("Illegal unit '$unit'"); + } + } + } + + /** + * Check repeatedly for the specified conditions until they become + * true or the timeout expires. + * @throws BuildException + */ + public function main() + { + if ($this->countConditions() > 1) { + throw new BuildException("You must not nest more than one condition into <waitfor>"); + } + + if ($this->countConditions() < 1) { + throw new BuildException("You must nest a condition into <waitfor>"); + } + + $cs = $this->getIterator(); + $condition = $cs->current(); + + $maxWaitMillis = $this->maxWait * $this->maxWaitMultiplier; + $checkEveryMillis = $this->checkEvery * $this->checkEveryMultiplier; + + $start = microtime(true) * 1000; + $end = $start + $maxWaitMillis; + + while (microtime(true) * 1000 < $end) { + if ($condition->evaluate()) { + $this->log("waitfor: condition was met", Project::MSG_VERBOSE); + + return; + } + + usleep($checkEveryMillis * 1000); + } + + $this->log("waitfor: timeout", Project::MSG_VERBOSE); + + if ($this->timeoutProperty != null) { + $this->project->setNewProperty($this->timeoutProperty, "true"); + } + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/system/WarnTask.php b/buildscripts/phing/classes/phing/tasks/system/WarnTask.php index 50318e71..28f0ad92 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/WarnTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/WarnTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: WarnTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: a2192433abbea9c5fe4b4ddb518cde8c09a643da $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -22,14 +22,14 @@ require_once 'phing/tasks/system/EchoTask.php'; /** - * Simple task to echo a warning message (PROJECT_MSG_WARN) to all output devices. + * Simple task to echo a warning message (Project::MSG_WARN) to all output devices. * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.1 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @version $Id$ * @package phing.tasks.system */ class WarnTask extends EchoTask { function main() { - $this->log($this->msg, PROJECT_MSG_WARN); + $this->log($this->msg, Project::MSG_WARN); } } diff --git a/buildscripts/phing/classes/phing/tasks/system/XsltTask.php b/buildscripts/phing/classes/phing/tasks/system/XsltTask.php index 0374aa59..7155caf8 100644 --- a/buildscripts/phing/classes/phing/tasks/system/XsltTask.php +++ b/buildscripts/phing/classes/phing/tasks/system/XsltTask.php @@ -1,6 +1,6 @@ <?php /* - * $Id: XsltTask.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 8f87e1c7908c06223382baf628d018c3a0f10824 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -31,7 +31,7 @@ include_once 'phing/filters/XsltFilter.php'; * in the <filterchains> section. * * @author Andreas Aderhold, andi@binarycloud.com - * @version $Revision: 1.8 $ + * @version $Id: 8f87e1c7908c06223382baf628d018c3a0f10824 $ * @package phing.tasks.system */ class XsltTask extends CopyTask { @@ -57,7 +57,7 @@ class XsltTask extends CopyTask { * @see CopyTask::main() */ function main() { - $this->log("Doing XSLT transformation using stylesheet " . $this->xsltFilter->getStyle(), PROJECT_MSG_VERBOSE); + $this->log("Doing XSLT transformation using stylesheet " . $this->xsltFilter->getStyle(), Project::MSG_VERBOSE); $this->xsltFilter->setParams($this->parameters); parent::main(); } @@ -71,6 +71,28 @@ class XsltTask extends CopyTask { } /** + * Whether to resolve entities in the XML document. + * + * @param bool $resolveExternals + * + * @since 2.4 + */ + function setResolveDocumentExternals($resolveExternals) { + $this->xsltFilter->setResolveDocumentExternals((bool)$resolveExternals); + } + + /** + * Whether to resolve entities in the stylesheet. + * + * @param bool $resolveExternals + * + * @since 2.4 + */ + function setResolveStylesheetExternals($resolveExternals) { + $this->xsltFilter->setResolveStylesheetExternals((bool)$resolveExternals); + } + + /** * Support nested <param> tags useing XSLTParam class. * @return XSLTParam */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php index c16ce499..41b57a8e 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: AndCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 69074307e3d1aae5fbfaa03842f5a8fc14b49625 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,8 +29,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php'; * * @author Hans Lellelid <hans@xmpl.org> * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.7 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id$ * @package phing.tasks.system.condition */ class AndCondition extends ConditionBase implements Condition { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php b/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php index 73e0c232..9c9d90e5 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php @@ -1,7 +1,7 @@ <?php /* - * $Id: Condition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: c971532805c4ac4c3d3cbf05a5c53abe7279b336 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,7 +26,7 @@ * Each condition must implement a method applying to this prototye: * * @author Hans Lellelid <hans@xmpl.org> - * @version $Revision: 1.4 $ + * @version $Id$ * @package phing.tasks.system.condition */ interface Condition { @@ -36,4 +36,3 @@ interface Condition { */ public function evaluate(); } -?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php b/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php index 1c09fe49..e21ce4e4 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ConditionBase.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 8721880badf6aee475a8cb87c88ca3dc4299efb8 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,10 +29,10 @@ include_once 'phing/tasks/system/condition/Condition.php'; * conditions - ensures that the types of conditions inside the task * and the "container" conditions are in sync. * - * @author Hans Lellelid <hans@xmpl.org> + * @author Hans Lellelid <hans@xmpl.org> * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.16 $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id$ * @package phing.tasks.system.condition */ abstract class ConditionBase extends ProjectComponent implements IteratorAggregate { @@ -156,6 +156,8 @@ abstract class ConditionBase extends ProjectComponent implements IteratorAggrega /** * "Inner" class for handling enumerations. * Uses build-in PHP5 iterator support. + * + * @package phing.tasks.system.condition */ class ConditionEnumeration implements Iterator { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php index 95849cd8..d7fb80ac 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php @@ -1,7 +1,7 @@ <?php /* - * $Id: ContainsCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 6cdecc53a715fce4601b1ceb64c8ec95d29c1468 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/tasks/system/condition/Condition.php'; * * @author Hans Lellelid <hans@xmpl.org> (Phing) * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.3 $ + * @version $Id: 6cdecc53a715fce4601b1ceb64c8ec95d29c1468 $ * @package phing.tasks.system.condition */ class ContainsCondition implements Condition { @@ -71,6 +71,6 @@ class ContainsCondition implements Condition { return $this->caseSensitive ? strpos($this->string, $this->subString) !== false - : substr(strtolower($this->string), strtolower($this->subString)) !== false; + : strpos(strtolower($this->string), strtolower($this->subString)) !== false; } } diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php index 32d51380..4be4e8fe 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: EqualsCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: faec716501a00cdeb84b8c893b5bbe5c76064dec $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -26,8 +26,8 @@ require_once 'phing/tasks/system/condition/Condition.php'; * binary safe manner. Implements the condition interface specification. * * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.7 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id: faec716501a00cdeb84b8c893b5bbe5c76064dec $ * @access public * @package phing.tasks.system.condition */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php index ebbd1a3d..8a1b3dcf 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: IsFalseCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: f7d355bdf8f7aa539afb572e2fe033ffd3bcd89b $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/tasks/system/condition/Condition.php'; * * @author Hans Lellelid (Phing) * @author Steve Loughran (Ant) - * @version $Revision: 1.4 $ + * @version $Id: f7d355bdf8f7aa539afb572e2fe033ffd3bcd89b $ * @package phing.tasks.system.condition */ class IsFalseCondition extends ProjectComponent implements Condition { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php index 4f81c50f..24f3f609 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: IsSetCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: 5c5924da5cff2626af09b4908703a21eec79c777 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -27,7 +27,7 @@ require_once 'phing/tasks/system/condition/Condition.php'; * * @author Hans Lellelid <hans@xmpl.org> (Phing) * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) - * @version $Revision: 1.4 $ + * @version $Id$ * @package phing.tasks.system.condition */ class IsSetCondition extends ProjectComponent implements Condition { diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php index 4affefc5..8c6d19fc 100644 --- a/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: IsTrueCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: d567f7c477e075a5c06d3f8e07ff8a7412cf31cd $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php index c76ef2b8..081876af 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: NotCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: d8c985da7c759357135cf717b1f4b52a1bd50cb6 $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -28,8 +28,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php'; * and vice versa. * * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.6 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id$ * @access public * @package phing.tasks.system.condition */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php index 778abfd0..d88df271 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: OrCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: adcd6785a85304a0860cc3dd9a0146d965c1cb0c $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -29,7 +29,7 @@ require_once 'phing/tasks/system/condition/ConditionBase.php'; * * @author Andreas Aderhold <andi@binarycloud.com> * @copyright 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.8 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @version $Id$ * @access public * @package phing.tasks.system.condition */ diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php index d80729e7..50a7174f 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: OsCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: d63246e2d25230f5ba6e45a651497e3ba01abe2c $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,8 +25,8 @@ require_once 'phing/tasks/system/condition/ConditionBase.php'; * Condition that tests the OS type. * * @author Andreas Aderhold <andi@binarycloud.com> - * @copyright © 2001,2002 THYRELL. All rights reserved - * @version $Revision: 1.8 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $ + * @copyright 2001,2002 THYRELL. All rights reserved + * @version $Id$ * @access public * @package phing.tasks.system.condition */ @@ -40,20 +40,20 @@ class OsCondition implements Condition { function evaluate() { $osName = strtolower(Phing::getProperty("os.name")); - + if ($this->family !== null) { if ($this->family === "windows") { return StringHelper::startsWith("win", $osName); } elseif ($this->family === "mac") { return (strpos($osName, "mac") !== false || strpos($osName, "darwin") !== false); } elseif ($this->family === ("unix")) { - return ( - StringHelper::endsWith("ix", $osName) || - StringHelper::endsWith("ux", $osName) || - StringHelper::endsWith("bsd", $osName) || - StringHelper::startsWith("sunos", $osName) || - StringHelper::startsWith("darwin", $osName) - ); + return ( + StringHelper::endsWith("ix", $osName) || + StringHelper::endsWith("ux", $osName) || + StringHelper::endsWith("bsd", $osName) || + StringHelper::startsWith("sunos", $osName) || + StringHelper::startsWith("darwin", $osName) + ); } throw new BuildException("Don't know how to detect os family '" . $this->family . "'"); } diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php index 09324fb8..08e291e3 100644..100755 --- a/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php +++ b/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php @@ -1,6 +1,6 @@ <?php /* - * $Id: ReferenceExistsCondition.php 59 2006-04-28 14:49:47Z mrook $ + * $Id: e62ed1e00cc6ed859746760c89bc0f873db4620a $ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +25,7 @@ require_once 'phing/ProjectComponent.php'; require_once 'phing/tasks/system/cond * Condition that tests whether a given reference exists. * * @author Matthias Pigulla <mp@webfactory.de> (Phing) - * @version $Revision: 1.1 $ + * @version $Id$ * @package phing.tasks.system.condition */ class ReferenceExistsCondition extends ProjectComponent implements Condition { |