diff options
Diffstat (limited to 'buildscripts/phing/classes/phing/util')
12 files changed, 2653 insertions, 0 deletions
diff --git a/buildscripts/phing/classes/phing/util/DataStore.php b/buildscripts/phing/classes/phing/util/DataStore.php new file mode 100755 index 00000000..af696697 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/DataStore.php @@ -0,0 +1,151 @@ +<?php + +/* + * $Id: 77f24d8b9d8082b4c23cb4cd5d23a06a3be88e2d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/FileWriter.php'; + +/** + * An abstract representation of file and directory pathnames. + * + * @package phing.util + * @author Michiel Rook <mrook@php.net> + * @version $Id$ + */ +class DataStore +{ + private $data = array(); + private $file = null; + + /** + * Constructs a new data store + * + * @param PhingFile $file object pointing to the data store on disk + */ + function __construct(PhingFile $file) + { + $this->file = $file; + + if ($this->file->exists()) + { + $this->read(); + } + } + + /** + * Destructor + */ + function __destruct() + { + $this->commit(); + } + + /** + * Retrieves a value from the data store + * + * @param string $key the key + * + * @return mixed the value + */ + public function get($key) + { + if (!isset($this->data[$key])) + { + return null; + } + else + { + return $this->data[$key]; + } + } + + /** + * Adds a value to the data store + * + * @param string $key the key + * @param mixed $value the value + * @param boolean $autocommit whether to auto-commit (write) + * the data store to disk + * + * @return none + */ + public function put($key, $value, $autocommit = false) + { + $this->data[$key] = $value; + + if ($autocommit) + { + $this->commit(); + } + } + + /** + * Commits data store to disk + * + * @return none + */ + public function commit() + { + $this->write(); + } + + /** + * Internal function to read data store from file + * + * @return none + */ + private function read() + { + if (!$this->file->canRead()) + { + throw new BuildException("Can't read data store from '" . + $file->getPath() . "'"); + } + else + { + $serializedData = $this->file->contents(); + + $this->data = unserialize($serializedData); + } + } + + /** + * Internal function to write data store to file + * + * @return none + */ + private function write() + { + if (!$this->file->canWrite()) + { + throw new BuildException("Can't write data store to '" . + $file->getPath() . "'"); + } + else + { + $serializedData = serialize($this->data); + + $writer = new FileWriter($this->file); + $writer->write($serializedData); + $writer->close(); + } + } +}; diff --git a/buildscripts/phing/classes/phing/util/DirectoryScanner.php b/buildscripts/phing/classes/phing/util/DirectoryScanner.php new file mode 100755 index 00000000..02d5be88 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/DirectoryScanner.php @@ -0,0 +1,755 @@ +<?php +/* + * $Id: 7aef4b4e372e89055248ab063660dbee92a98cc3 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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/selectors/SelectorScanner.php'; +include_once 'phing/util/StringHelper.php'; +include_once 'phing/types/selectors/SelectorUtils.php'; + +/** + * Class for scanning a directory for files/directories that match a certain + * criteria. + * + * These criteria consist of a set of include and exclude patterns. With these + * patterns, you can select which files you want to have included, and which + * files you want to have excluded. + * + * The idea is simple. A given directory is recursively scanned for all files + * and directories. Each file/directory is matched against a set of include + * and exclude patterns. Only files/directories that match at least one + * pattern of the include pattern list, and don't match a pattern of the + * exclude pattern list will be placed in the list of files/directories found. + * + * When no list of include patterns is supplied, "**" will be used, which + * means that everything will be matched. When no list of exclude patterns is + * supplied, an empty list is used, such that nothing will be excluded. + * + * The pattern matching is done as follows: + * The name to be matched is split up in path segments. A path segment is the + * name of a directory or file, which is bounded by DIRECTORY_SEPARATOR + * ('/' under UNIX, '\' under Windows). + * E.g. "abc/def/ghi/xyz.php" is split up in the segments "abc", "def", "ghi" + * and "xyz.php". + * The same is done for the pattern against which should be matched. + * + * Then the segments of the name and the pattern will be matched against each + * other. When '**' is used for a path segment in the pattern, then it matches + * zero or more path segments of the name. + * + * There are special case regarding the use of DIRECTORY_SEPARATOR at + * the beginning of the pattern and the string to match: + * When a pattern starts with a DIRECTORY_SEPARATOR, the string + * to match must also start with a DIRECTORY_SEPARATOR. + * When a pattern does not start with a DIRECTORY_SEPARATOR, the + * string to match may not start with a DIRECTORY_SEPARATOR. + * When one of these rules is not obeyed, the string will not + * match. + * + * When a name path segment is matched against a pattern path segment, the + * following special characters can be used: + * '*' matches zero or more characters, + * '?' matches one character. + * + * Examples: + * + * "**\*.php" matches all .php files/dirs in a directory tree. + * + * "test\a??.php" matches all files/dirs which start with an 'a', then two + * more characters and then ".php", in a directory called test. + * + * "**" matches everything in a directory tree. + * + * "**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where + * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123"). + * + * Case sensitivity may be turned off if necessary. By default, it is + * turned on. + * + * Example of usage: + * $ds = new DirectroyScanner(); + * $includes = array("**\*.php"); + * $excludes = array("modules\*\**"); + * $ds->SetIncludes($includes); + * $ds->SetExcludes($excludes); + * $ds->SetBasedir("test"); + * $ds->SetCaseSensitive(true); + * $ds->Scan(); + * + * print("FILES:"); + * $files = ds->GetIncludedFiles(); + * for ($i = 0; $i < count($files);$i++) { + * println("$files[$i]\n"); + * } + * + * This will scan a directory called test for .php files, but excludes all + * .php files in all directories under a directory called "modules" + * + * This class is complete preg/ereg free port of the Java class + * org.apache.tools.ant.DirectoryScanner. Even functions that use preg/ereg + * internally (like split()) are not used. Only the _fast_ string functions + * and comparison operators (=== !=== etc) are used for matching and tokenizing. + * + * @author Arnout J. Kuiper, ajkuiper@wxs.nl + * @author Magesh Umasankar, umagesh@rediffmail.com + * @author Andreas Aderhold, andi@binarycloud.com + * + * @version $Id: 7aef4b4e372e89055248ab063660dbee92a98cc3 $ + * @package phing.util + */ +class DirectoryScanner implements SelectorScanner { + + /** default set of excludes */ + protected $DEFAULTEXCLUDES = array( + "**/*~", + "**/#*#", + "**/.#*", + "**/%*%", + "**/CVS", + "**/CVS/**", + "**/.cvsignore", + "**/SCCS", + "**/SCCS/**", + "**/vssver.scc", + "**/.svn", + "**/.svn/**", + "**/._*", + "**/.DS_Store", + "**/.darcs", + "**/.darcs/**", + "**/.git", + "**/.git/**", + "**/.gitattributes", + "**/.gitignore", + "**/.gitmodules", + ); + + /** The base directory which should be scanned. */ + protected $basedir; + + /** The patterns for the files that should be included. */ + protected $includes = null; + + /** The patterns for the files that should be excluded. */ + protected $excludes = null; + + /** Whether to expand/dereference symbolic links, default is false */ + protected $expandSymbolicLinks = false; + + /** + * The files that where found and matched at least one includes, and matched + * no excludes. + */ + protected $filesIncluded; + + /** The files that where found and did not match any includes. Trie */ + protected $filesNotIncluded; + + /** + * The files that where found and matched at least one includes, and also + * matched at least one excludes. Trie object. + */ + protected $filesExcluded; + + /** + * The directories that where found and matched at least one includes, and + * matched no excludes. + */ + protected $dirsIncluded; + + /** The directories that where found and did not match any includes. */ + protected $dirsNotIncluded; + + /** + * The files that where found and matched at least one includes, and also + * matched at least one excludes. + */ + protected $dirsExcluded; + + /** Have the vars holding our results been built by a slow scan? */ + protected $haveSlowResults = false; + + /** Should the file system be treated as a case sensitive one? */ + protected $isCaseSensitive = true; + + /** Selectors */ + protected $selectors = null; + + protected $filesDeselected; + protected $dirsDeselected; + + /** if there are no deselected files */ + protected $everythingIncluded = true; + + /** + * Does the path match the start of this pattern up to the first "**". + * This is a static mehtod and should always be called static + * + * This is not a general purpose test and should only be used if you + * can live with false positives. + * + * pattern=**\a and str=b will yield true. + * + * @param pattern the (non-null) pattern to match against + * @param str the (non-null) string (path) to match + * @param isCaseSensitive must matches be case sensitive? + * @return boolean true if matches, otherwise false + */ + function matchPatternStart($pattern, $str, $isCaseSensitive = true) { + return SelectorUtils::matchPatternStart($pattern, $str, $isCaseSensitive); + } + + /** + * Matches a path against a pattern. Static + * + * @param pattern the (non-null) pattern to match against + * @param str the (non-null) string (path) to match + * @param isCaseSensitive must a case sensitive match be done? + * + * @return true when the pattern matches against the string. + * false otherwise. + */ + function matchPath($pattern, $str, $isCaseSensitive = true) { + return SelectorUtils::matchPath($pattern, $str, $isCaseSensitive); + } + + /** + * Matches a string against a pattern. The pattern contains two special + * characters: + * '*' which means zero or more characters, + * '?' which means one and only one character. + * + * @param pattern the (non-null) pattern to match against + * @param str the (non-null) string that must be matched against the + * pattern + * + * @return boolean true when the string matches against the pattern, + * false otherwise. + * @access public + */ + function match($pattern, $str, $isCaseSensitive = true) { + return SelectorUtils::match($pattern, $str, $isCaseSensitive); + } + + /** + * Sets the basedir for scanning. This is the directory that is scanned + * recursively. All '/' and '\' characters are replaced by + * DIRECTORY_SEPARATOR + * + * @param basedir the (non-null) basedir for scanning + */ + function setBasedir($_basedir) { + $_basedir = str_replace('\\', DIRECTORY_SEPARATOR, $_basedir); + $_basedir = str_replace('/', DIRECTORY_SEPARATOR, $_basedir); + $this->basedir = $_basedir; + } + + /** + * Gets the basedir that is used for scanning. This is the directory that + * is scanned recursively. + * + * @return the basedir that is used for scanning + */ + function getBasedir() { + return $this->basedir; + } + + /** + * Sets the case sensitivity of the file system + * + * @param specifies if the filesystem is case sensitive + */ + function setCaseSensitive($_isCaseSensitive) { + $this->isCaseSensitive = ($_isCaseSensitive) ? true : false; + } + + /** + * Sets the set of include patterns to use. All '/' and '\' characters are + * replaced by DIRECTORY_SEPARATOR. So the separator used need + * not match DIRECTORY_SEPARATOR. + * + * When a pattern ends with a '/' or '\', "**" is appended. + * + * @param includes list of include patterns + */ + function setIncludes($_includes = array()) { + if (empty($_includes) || is_null($_includes)) { + $this->includes = null; + } else { + for ($i = 0; $i < count($_includes); $i++) { + $pattern = null; + $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $_includes[$i]); + $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern); + if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $pattern)) { + $pattern .= "**"; + } + $this->includes[] = $pattern; + } + } + } + + /** + * Sets the set of exclude patterns to use. All '/' and '\' characters are + * replaced by <code>File.separatorChar</code>. So the separator used need + * not match <code>File.separatorChar</code>. + * + * When a pattern ends with a '/' or '\', "**" is appended. + * + * @param excludes list of exclude patterns + */ + + function setExcludes($_excludes = array()) { + if (empty($_excludes) || is_null($_excludes)) { + $this->excludes = null; + } else { + for ($i = 0; $i < count($_excludes); $i++) { + $pattern = null; + $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $_excludes[$i]); + $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern); + if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $pattern)) { + $pattern .= "**"; + } + $this->excludes[] = $pattern; + } + } + } + + /** + * Sets whether to expand/dereference symbolic links + * + * @param expandSymbolicLinks boolean value + */ + function setExpandSymbolicLinks($expandSymbolicLinks) + { + $this->expandSymbolicLinks = $expandSymbolicLinks; + } + + /** + * Scans the base directory for files that match at least one include + * pattern, and don't match any exclude patterns. + * + */ + function scan() { + + if ((empty($this->basedir)) || (!@is_dir($this->basedir))) { + return false; + } + + if ($this->includes === null) { + // No includes supplied, so set it to 'matches all' + $this->includes = array("**"); + } + if (is_null($this->excludes)) { + $this->excludes = array(); + } + + $this->filesIncluded = array(); + $this->filesNotIncluded = array(); + $this->filesExcluded = array(); + $this->dirsIncluded = array(); + $this->dirsNotIncluded = array(); + $this->dirsExcluded = array(); + $this->dirsDeselected = array(); + $this->filesDeselected = array(); + + if ($this->isIncluded("")) { + if (!$this->isExcluded("")) { + if ($this->isSelected("", $this->basedir)) { + $this->dirsIncluded[] = ""; + } else { + $this->dirsDeselected[] = ""; + } + } else { + $this->dirsExcluded[] = ""; + } + } else { + $this->dirsNotIncluded[] = ""; + } + + $this->scandir($this->basedir, "", true); + return true; + } + + /** + * Toplevel invocation for the scan. + * + * Returns immediately if a slow scan has already been requested. + */ + protected function slowScan() { + + if ($this->haveSlowResults) { + return; + } + + // copy trie object add CopyInto() method + $excl = $this->dirsExcluded; + $notIncl = $this->dirsNotIncluded; + + for ($i=0, $_i=count($excl); $i < $_i; $i++) { + if (!$this->couldHoldIncluded($excl[$i])) { + $this->scandir($this->basedir.$excl[$i], $excl[$i].DIRECTORY_SEPARATOR, false); + } + } + + for ($i=0, $_i=count($notIncl); $i < $_i; $i++) { + if (!$this->couldHoldIncluded($notIncl[$i])) { + $this->scandir($this->basedir.$notIncl[$i], $notIncl[$i].DIRECTORY_SEPARATOR, false); + } + } + + $this->haveSlowResults = true; + } + + /** + * Lists contens of a given directory and returns array with entries + * + * @param src String. Source path and name file to copy. + * + * @access public + * @return array directory entries + * @author Albert Lash, alash@plateauinnovation.com + */ + + function listDir($_dir) { + $d = dir($_dir); + $list = array(); + while(($entry = $d->read()) !== false) { + if ($entry != "." && $entry != "..") { + $list[] = $entry; + } + } + $d->close(); + return $list; + } + + /** + * Scans the passed dir for files and directories. Found files and + * directories are placed in their respective collections, based on the + * matching of includes and excludes. When a directory is found, it is + * scanned recursively. + * + * @param dir the directory to scan + * @param vpath the path relative to the basedir (needed to prevent + * problems with an absolute path when using dir) + * + * @access private + * @see #filesIncluded + * @see #filesNotIncluded + * @see #filesExcluded + * @see #dirsIncluded + * @see #dirsNotIncluded + * @see #dirsExcluded + */ + private function scandir($_rootdir, $_vpath, $_fast) { + + if (!is_readable($_rootdir)) { + return; + } + + $newfiles = self::listDir($_rootdir); + + for ($i=0,$_i=count($newfiles); $i < $_i; $i++) { + + $file = $_rootdir . DIRECTORY_SEPARATOR . $newfiles[$i]; + $name = $_vpath . $newfiles[$i]; + + if (@is_link($file) && !$this->expandSymbolicLinks) + { + if ($this->isIncluded($name)) { + if (!$this->isExcluded($name)) { + if ($this->isSelected($name, $file)) { + $this->filesIncluded[] = $name; + } else { + $this->everythingIncluded = false; + $this->filesDeselected[] = $name; + } + } else { + $this->everythingIncluded = false; + $this->filesExcluded[] = $name; + } + } else { + $this->everythingIncluded = false; + $this->filesNotIncluded[] = $name; + } + } + else + if (@is_dir($file)) { + if ($this->isIncluded($name)) { + if (!$this->isExcluded($name)) { + if ($this->isSelected($name, $file)) { + $this->dirsIncluded[] = $name; + if ($_fast) { + $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast); + } + } else { + $this->everythingIncluded = false; + $this->dirsDeselected[] = $name; + if ($_fast && $this->couldHoldIncluded($name)) { + $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast); + } + } + } else { + $this->everythingIncluded = false; + $this->dirsExcluded[] = $name; + if ($_fast && $this->couldHoldIncluded($name)) { + $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast); + } + } + } else { + $this->everythingIncluded = false; + $this->dirsNotIncluded[] = $name; + if ($_fast && $this->couldHoldIncluded($name)) { + $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast); + } + } + + if (!$_fast) { + $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast); + } + + } elseif (@is_file($file)) { + if ($this->isIncluded($name)) { + if (!$this->isExcluded($name)) { + if ($this->isSelected($name, $file)) { + $this->filesIncluded[] = $name; + } else { + $this->everythingIncluded = false; + $this->filesDeselected[] = $name; + } + } else { + $this->everythingIncluded = false; + $this->filesExcluded[] = $name; + } + } else { + $this->everythingIncluded = false; + $this->filesNotIncluded[] = $name; + } + } + } + } + + /** + * Tests whether a name matches against at least one include pattern. + * + * @param name the name to match + * @return <code>true</code> when the name matches against at least one + * include pattern, <code>false</code> otherwise. + */ + protected function isIncluded($_name) { + for ($i=0, $_i=count($this->includes); $i < $_i; $i++) { + if (DirectoryScanner::matchPath($this->includes[$i], $_name, $this->isCaseSensitive)) { + return true; + } + } + return false; + } + + /** + * Tests whether a name matches the start of at least one include pattern. + * + * @param name the name to match + * @return <code>true</code> when the name matches against at least one + * include pattern, <code>false</code> otherwise. + */ + protected function couldHoldIncluded($_name) { + for ($i = 0; $i < count($this->includes); $i++) { + if (DirectoryScanner::matchPatternStart($this->includes[$i], $_name, $this->isCaseSensitive)) { + return true; + } + } + return false; + } + + /** + * Tests whether a name matches against at least one exclude pattern. + * + * @param name the name to match + * @return <code>true</code> when the name matches against at least one + * exclude pattern, <code>false</code> otherwise. + */ + protected function isExcluded($_name) { + for ($i = 0; $i < count($this->excludes); $i++) { + if (DirectoryScanner::matchPath($this->excludes[$i], $_name, $this->isCaseSensitive)) { + return true; + } + } + return false; + } + + /** + * Get the names of the files that matched at least one of the include + * patterns, and matched none of the exclude patterns. + * The names are relative to the basedir. + * + * @return the names of the files + */ + function getIncludedFiles() { + return $this->filesIncluded; + } + + /** + * Get the names of the files that matched at none of the include patterns. + * The names are relative to the basedir. + * + * @return the names of the files + */ + function getNotIncludedFiles() { + $this->slowScan(); + return $this->filesNotIncluded; + } + + /** + * Get the names of the files that matched at least one of the include + * patterns, an matched also at least one of the exclude patterns. + * The names are relative to the basedir. + * + * @return the names of the files + */ + + function getExcludedFiles() { + $this->slowScan(); + return $this->filesExcluded; + } + + /** + * <p>Returns the names of the files which were selected out and + * therefore not ultimately included.</p> + * + * <p>The names are relative to the base directory. This involves + * performing a slow scan if one has not already been completed.</p> + * + * @return the names of the files which were deselected. + * + * @see #slowScan + */ + public function getDeselectedFiles() { + $this->slowScan(); + return $this->filesDeselected; + } + + /** + * Get the names of the directories that matched at least one of the include + * patterns, an matched none of the exclude patterns. + * The names are relative to the basedir. + * + * @return the names of the directories + */ + + function getIncludedDirectories() { + return $this->dirsIncluded; + } + + /** + * Get the names of the directories that matched at none of the include + * patterns. + * The names are relative to the basedir. + * + * @return the names of the directories + */ + function getNotIncludedDirectories() { + $this->slowScan(); + return $this->dirsNotIncluded; + } + + /** + * <p>Returns the names of the directories which were selected out and + * therefore not ultimately included.</p> + * + * <p>The names are relative to the base directory. This involves + * performing a slow scan if one has not already been completed.</p> + * + * @return the names of the directories which were deselected. + * + * @see #slowScan + */ + public function getDeselectedDirectories() { + $this->slowScan(); + return $this->dirsDeselected; + } + + /** + * Get the names of the directories that matched at least one of the include + * patterns, an matched also at least one of the exclude patterns. + * The names are relative to the basedir. + * + * @return the names of the directories + */ + function getExcludedDirectories() { + $this->slowScan(); + return $this->dirsExcluded; + } + + /** + * Adds the array with default exclusions to the current exclusions set. + * + */ + function addDefaultExcludes() { + //$excludesLength = ($this->excludes == null) ? 0 : count($this->excludes); + foreach($this->DEFAULTEXCLUDES as $pattern) { + $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $pattern); + $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern); + $this->excludes[] = $pattern; + } + } + + /** + * Sets the selectors that will select the filelist. + * + * @param selectors specifies the selectors to be invoked on a scan + */ + public function setSelectors($selectors) { + $this->selectors = $selectors; + } + + /** + * Returns whether or not the scanner has included all the files or + * directories it has come across so far. + * + * @return <code>true</code> if all files and directories which have + * been found so far have been included. + */ + public function isEverythingIncluded() { + return $this->everythingIncluded; + } + + /** + * Tests whether a name should be selected. + * + * @param string $name The filename to check for selecting. + * @param string $file The full file path. + * @return boolean False when the selectors says that the file + * should not be selected, True otherwise. + */ + protected function isSelected($name, $file) { + if ($this->selectors !== null) { + $basedir = new PhingFile($this->basedir); + $file = new PhingFile($file); + if (!$file->canRead()) + return false; + + foreach($this->selectors as $selector) { + if (!$selector->isSelected($basedir, $name, $file)) { + return false; + } + } + } + return true; + } + +} diff --git a/buildscripts/phing/classes/phing/util/ExtendedFileStream.php b/buildscripts/phing/classes/phing/util/ExtendedFileStream.php new file mode 100755 index 00000000..9c09b56f --- /dev/null +++ b/buildscripts/phing/classes/phing/util/ExtendedFileStream.php @@ -0,0 +1,129 @@ +<?php + + include_once 'phing/system/io/PhingFile.php'; + + /** + * $Id: f7e4641c758d5e781ad209d3eaf653a20404bf56 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + /** + * Extended file stream wrapper class which auto-creates directories + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: f7e4641c758d5e781ad209d3eaf653a20404bf56 $ + * @package phing.util + */ + class ExtendedFileStream + { + private $fp = NULL; + + static function registerStream() + { + if (!in_array("efile", stream_get_wrappers())) + { + stream_wrapper_register("efile", "ExtendedFileStream"); + } + } + + static function unregisterStream() + { + stream_wrapper_unregister("efile"); + } + + private function createDirectories($path) + { + $f = new PhingFile($path); + if (!$f->exists()) { + $f->mkdirs(); + } + } + + function stream_open($path, $mode, $options, &$opened_path) + { + $filepath = substr($path, 8); + + $this->createDirectories(dirname($filepath)); + + $this->fp = fopen($filepath, $mode); + + return true; + } + + function stream_close() + { + fclose($this->fp); + $this->fp = NULL; + } + + function stream_read($count) + { + return fread($this->fp, $count); + } + + function stream_write($data) + { + return fwrite($this->fp, $data); + } + + function stream_eof() + { + return feof($this->fp); + } + + function stream_tell() + { + return ftell($this->fp); + } + + function stream_seek($offset, $whence) + { + return fseek($this->fp, $offset, $whence); + } + + function stream_flush() + { + return fflush($this->fp); + } + + function stream_stat() + { + return fstat($this->fp); + } + + function unlink($path) + { + return FALSE; + } + + function rename($path_from, $path_to) + { + return FALSE; + } + + function mkdir($path, $mode, $options) + { + return FALSE; + } + + function rmdir($path, $options) + { + return FALSE; + } + }; + diff --git a/buildscripts/phing/classes/phing/util/FileUtils.php b/buildscripts/phing/classes/phing/util/FileUtils.php new file mode 100755 index 00000000..c98bbdd3 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/FileUtils.php @@ -0,0 +1,298 @@ +<?php +/* + * $Id: fe077b4174763861e773f5e5e55bbfc5030cac4d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/system/lang/Character.php'; +include_once 'phing/util/StringHelper.php'; +include_once 'phing/system/io/BufferedReader.php'; +include_once 'phing/system/io/BufferedWriter.php'; +include_once 'phing/filters/util/ChainReaderHelper.php'; +include_once 'phing/system/io/PhingFile.php'; + +/** + * File utility class. + * - handles os independent stuff etc + * - mapper stuff + * - filter stuff + * + * @package phing.util + * @version $Id$ + */ +class FileUtils { + + /** + * Returns a new Reader with filterchains applied. If filterchains are empty, + * simply returns passed reader. + * + * @param Reader $in Reader to modify (if appropriate). + * @param array &$filterChains filter chains to apply. + * @param Project $project + * @return Reader Assembled Reader (w/ filter chains). + */ + public static function getChainedReader(Reader $in, &$filterChains, Project $project) { + if (!empty($filterChains)) { + $crh = new ChainReaderHelper(); + $crh->setBufferSize(65536); // 64k buffer, but isn't being used (yet?) + $crh->setPrimaryReader($in); + $crh->setFilterChains($filterChains); + $crh->setProject($project); + $rdr = $crh->getAssembledReader(); + return $rdr; + } else { + return $in; + } + } + + /** + * Copies a file using filter chains. + * + * @param PhingFile $sourceFile + * @param PhingFile $destFile + * @param boolean $overwrite + * @param boolean $preserveLastModified + * @param array $filterChains + * @param Project $project + * @param integer $mode + * @return void + */ + function copyFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite = false, $preserveLastModified = true, &$filterChains = null, Project $project, $mode = 0755) { + + if ($overwrite || !$destFile->exists() || $destFile->lastModified() < $sourceFile->lastModified()) { + if ($destFile->exists() && $destFile->isFile()) { + $destFile->delete(); + } + + // ensure that parent dir of dest file exists! + $parent = $destFile->getParentFile(); + if ($parent !== null && !$parent->exists()) { + $parent->mkdirs($mode); + } + + if ((is_array($filterChains)) && (!empty($filterChains))) { + + $in = self::getChainedReader(new BufferedReader(new FileReader($sourceFile)), $filterChains, $project); + $out = new BufferedWriter(new FileWriter($destFile)); + + // New read() methods returns a big buffer. + while(-1 !== ($buffer = $in->read())) { // -1 indicates EOF + $out->write($buffer); + } + + if ( $in !== null ) + $in->close(); + if ( $out !== null ) + $out->close(); + + $destFile->setMode($sourceFile->getMode()); + + } else { + // simple copy (no filtering) + $sourceFile->copyTo($destFile); + } + + if ($preserveLastModified) { + $destFile->setLastModified($sourceFile->lastModified()); + } + + } + } + + /** + * Interpret the filename as a file relative to the given file - + * unless the filename already represents an absolute filename. + * + * @param $file the "reference" file for relative paths. This + * instance must be an absolute file and must not contain + * ./ or ../ sequences (same for \ instead of /). + * @param $filename a file name + * + * @return PhingFile A PhingFile object pointing to an absolute file that doesn't contain ./ or ../ sequences + * and uses the correct separator for the current platform. + */ + function resolveFile($file, $filename) { + // remove this and use the static class constant File::seperator + // as soon as ZE2 is ready + $fs = FileSystem::getFileSystem(); + + $filename = str_replace('/', $fs->getSeparator(), str_replace('\\', $fs->getSeparator(), $filename)); + + // deal with absolute files + if (StringHelper::startsWith($fs->getSeparator(), $filename) || + (strlen($filename) >= 2 && Character::isLetter($filename{0}) && $filename{1} === ':')) { + return new PhingFile($this->normalize($filename)); + } + + if (strlen($filename) >= 2 && Character::isLetter($filename{0}) && $filename{1} === ':') { + return new PhingFile($this->normalize($filename)); + } + + $helpFile = new PhingFile($file->getAbsolutePath()); + + $tok = strtok($filename, $fs->getSeparator()); + while ($tok !== false) { + $part = $tok; + if ($part === '..') { + $parentFile = $helpFile->getParent(); + if ($parentFile === null) { + $msg = "The file or path you specified ($filename) is invalid relative to ".$file->getPath(); + throw new IOException($msg); + } + $helpFile = new PhingFile($parentFile); + } else if ($part === '.') { + // Do nothing here + } else { + $helpFile = new PhingFile($helpFile, $part); + } + $tok = strtok($fs->getSeparator()); + } + return new PhingFile($helpFile->getAbsolutePath()); + } + + /** + * Normalize the given absolute path. + * + * This includes: + * - Uppercase the drive letter if there is one. + * - Remove redundant slashes after the drive spec. + * - resolve all ./, .\, ../ and ..\ sequences. + * - DOS style paths that start with a drive letter will have + * \ as the separator. + * @param string $path Path to normalize. + * @return string + */ + function normalize($path) { + + $path = (string) $path; + $orig = $path; + + $path = str_replace('/', DIRECTORY_SEPARATOR, str_replace('\\', DIRECTORY_SEPARATOR, $path)); + + // make sure we are dealing with an absolute path + if (!StringHelper::startsWith(DIRECTORY_SEPARATOR, $path) + && !(strlen($path) >= 2 && Character::isLetter($path{0}) && $path{1} === ':')) { + throw new IOException("$path is not an absolute path"); + } + + $dosWithDrive = false; + $root = null; + + // Eliminate consecutive slashes after the drive spec + + if (strlen($path) >= 2 && Character::isLetter($path{0}) && $path{1} === ':') { + $dosWithDrive = true; + + $ca = str_replace('/', '\\', $path); + $ca = StringHelper::toCharArray($ca); + + $path = strtoupper($ca[0]).':'; + + for ($i=2, $_i=count($ca); $i < $_i; $i++) { + if (($ca[$i] !== '\\') || + ($ca[$i] === '\\' && $ca[$i - 1] !== '\\') + ) { + $path .= $ca[$i]; + } + } + + $path = str_replace('\\', DIRECTORY_SEPARATOR, $path); + + if (strlen($path) == 2) { + $root = $path; + $path = ""; + } else { + $root = substr($path, 0, 3); + $path = substr($path, 3); + } + + } else { + if (strlen($path) == 1) { + $root = DIRECTORY_SEPARATOR; + $path = ""; + } else if ($path{1} == DIRECTORY_SEPARATOR) { + // UNC drive + $root = DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR; + $path = substr($path, 2); + } + else { + $root = DIRECTORY_SEPARATOR; + $path = substr($path, 1); + } + } + + $s = array(); + array_push($s, $root); + $tok = strtok($path, DIRECTORY_SEPARATOR); + while ($tok !== false) { + $thisToken = $tok; + if ("." === $thisToken) { + $tok = strtok(DIRECTORY_SEPARATOR); + continue; + } elseif (".." === $thisToken) { + if (count($s) < 2) { + // using '..' in path that is too short + throw new IOException("Cannot resolve path: $orig"); + } else { + array_pop($s); + } + } else { // plain component + array_push($s, $thisToken); + } + $tok = strtok(DIRECTORY_SEPARATOR); + } + + $sb = ""; + for ($i=0,$_i=count($s); $i < $_i; $i++) { + if ($i > 1) { + // not before the filesystem root and not after it, since root + // already contains one + $sb .= DIRECTORY_SEPARATOR; + } + $sb .= (string) $s[$i]; + } + + + $path = (string) $sb; + if ($dosWithDrive === true) { + $path = str_replace('/', '\\', $path); + } + return $path; + } + + /** + * @return boolean Whether contents of two files is the same. + */ + public function contentEquals(PhingFile $file1, PhingFile $file2) { + + if (!($file1->exists() || $file2->exists())) { + return false; + } + + if (!($file1->canRead() || $file2->canRead())) { + return false; + } + + $c1 = file_get_contents($file1->getAbsolutePath()); + $c2 = file_get_contents($file2->getAbsolutePath()); + + return trim($c1) == trim($c2); + } + +} + diff --git a/buildscripts/phing/classes/phing/util/LogWriter.php b/buildscripts/phing/classes/phing/util/LogWriter.php new file mode 100755 index 00000000..ae97705e --- /dev/null +++ b/buildscripts/phing/classes/phing/util/LogWriter.php @@ -0,0 +1,95 @@ +<?php + + /** + * $Id: ccb6c8b930bb3f293074969323467edeaf40bd02 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + require_once 'phing/system/io/Writer.php'; + require_once 'phing/Task.php'; + + /** + * Extends the Writer class to output messages to Phing's log + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: ccb6c8b930bb3f293074969323467edeaf40bd02 $ + * @package phing.util + */ + class LogWriter extends Writer + { + private $task = NULL; + + private $level = NULL; + + /** + * Constructs a new LogWriter object + */ + function __construct(Task $task, $level = Project::MSG_INFO) + { + $this->task = $task; + $this->level = $level; + } + + /** + * @see Writer::write() + */ + function write($buf, $off = null, $len = null) + { + $lines = explode("\n", $buf); + + foreach ($lines as $line) + { + if ($line == "") + { + continue; + } + + $this->task->log($line, $this->level); + } + } + + /** + * @see Writer::reset() + */ + function reset() + { + } + + /** + * @see Writer::close() + */ + function close() + { + } + + /** + * @see Writer::open() + */ + function open() + { + } + + /** + * @see Writer::getResource() + */ + function getResource() + { + return $this->task; + } + } + diff --git a/buildscripts/phing/classes/phing/util/PathTokenizer.php b/buildscripts/phing/classes/phing/util/PathTokenizer.php new file mode 100644 index 00000000..0a469acf --- /dev/null +++ b/buildscripts/phing/classes/phing/util/PathTokenizer.php @@ -0,0 +1,245 @@ +<?php +/* + * $Id: 0ca7f2a419b5cc4285a8f84695c4b680b0aa190b $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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/util/StringHelper.php'; + + + +/** + + * A Path tokenizer takes a path and returns the components that make up + + * that path. + + * + + * The path can use path separators of either ':' or ';' and file separators + + * of either '/' or '\'. + + * + + * @author Hans Lellelid <hans@xmpl.org> (Phing) + + * @author Conor MacNeill (Ant) + + * @author Jeff Tulley <jtulley@novell.com> (Ant) + + * @package phing.util + + */ + +class PathTokenizer { + + + + /** + + * A array of tokens, created by preg_split(). + + */ + + private $tokens = array(); + + + + /** + + * A string which stores any path components which have been read ahead + + * due to DOS filesystem compensation. + + * @var string + + */ + + private $lookahead; + + + + /** + + * Flag to indicate whether or not we are running on a platform with a + + * DOS style filesystem + + * @var boolean + + */ + + private $dosStyleFilesystem; + + + + /** + + * Constructs a path tokenizer for the specified path. + + * + + * @param path The path to tokenize. Must not be <code>null</code>. + + */ + + public function __construct($path) { + + // on Windows and Unix, we can ignore delimiters and still have + + // enough information to tokenize correctly. + + $this->tokens = preg_split("/[;:]/", $path, -1, PREG_SPLIT_NO_EMPTY); + + $this->dosStyleFilesystem = ( PATH_SEPARATOR == ';'); + + } + + + + /** + + * Tests if there are more path elements available from this tokenizer's + + * path. If this method returns <code>true</code>, then a subsequent call + + * to nextToken will successfully return a token. + + * + + * @return <code>true</code> if and only if there is at least one token + + * in the string after the current position; <code>false</code> otherwise. + + */ + + public function hasMoreTokens() { + + if ($this->lookahead !== null) { + + return true; + + } + + return !empty($this->tokens); + + } + + + + /** + + * Returns the next path element from this tokenizer. + + * + + * @return the next path element from this tokenizer. + + * + + * @throws Exception if there are no more elements in this tokenizer's path. + + */ + + public function nextToken() { + + + + if ($this->lookahead !== null) { + + $token = $this->lookahead; + + $this->lookahead = null; + + } else { + + $token = trim(array_shift($this->tokens)); + + } + + + + + + if (strlen($token) === 1 && Character::isLetter($token{0}) + + && $this->dosStyleFilesystem + + && !empty($this->tokens)) { + + // we are on a dos style system so this path could be a drive + + // spec. We look at the next token + + $nextToken = trim(array_shift($this->tokens)); + + if (StringHelper::startsWith('\\', $nextToken) || StringHelper::startsWith('/', $nextToken)) { + + // we know we are on a DOS style platform and the next path + + // starts with a slash or backslash, so we know this is a + + // drive spec + + $token .= ':' . $nextToken; + + } else { + + // store the token just read for next time + + $this->lookahead = $nextToken; + + } + + } + + + + return $token; + + } + + + + /** + + * Non StringTokenizer function, that indicates whether the specified path is contained in loaded tokens. + + * We can do this easily because in PHP implimentation we're using arrays. + + * @param string $path path to search for. + + * @return boolean + + */ + + public function contains($path) { + + return in_array($path, $this->tokens, true); + + } + + + +} + + + diff --git a/buildscripts/phing/classes/phing/util/PearPackageScanner.php b/buildscripts/phing/classes/phing/util/PearPackageScanner.php new file mode 100644 index 00000000..9071ed37 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/PearPackageScanner.php @@ -0,0 +1,170 @@ +<?php +/** + * Part of phing, the PHP build tool + * + * PHP version 5 + * + * @category Util + * @package phing.util + * @author Christian Weiske <cweiske@cweiske.de> + * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @version SVN: $Id: e549026313edf53c67f495489f671cf0b71df80d $ + * @link http://www.phing.info/ + */ +require_once 'phing/util/DirectoryScanner.php'; +require_once 'PEAR/Config.php'; + +/** + * Scans for files in a PEAR package. + * + * @category Util + * @package phing.util + * @author Christian Weiske <cweiske@cweiske.de> + * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link http://www.phing.info/ + */ +class PearPackageScanner extends DirectoryScanner +{ + protected $packageInfo; + protected $role = 'php'; + protected $config; + protected $package; + protected $channel = 'pear.php.net'; + + /** + * Sets the name of the PEAR package to get the files from + * + * @param string $package Package name without channel + * + * @return void + */ + public function setPackage($package) + { + $this->package = $package; + } + + /** + * Sets the name of the package channel name + * + * @param string $channel package channel name or alias + * + * @return void + */ + public function setChannel($channel) + { + $this->channel = $channel; + } + + /** + * Sets the full path to the PEAR configuration file + * + * @param string $config Configuration file + * + * @return void + */ + public function setConfig($config) + { + if ($config != '' && !file_exists($config)) { + throw new BuildException( + 'PEAR configuration file "' . $config . '" does not exist' + ); + } + + $this->config = $config; + } + + /** + * Sets the role of files that should be included. + * Examples are php,doc,script + * + * @param string $role PEAR file role + * + * @return void + * + * @internal + * We do not verify the role against a hardcoded list since that + * would break packages with additional roles. + */ + public function setRole($role) + { + if ($role == '') { + throw new BuildException('A non-empty role is required'); + } + + $this->role = $role; + } + + /** + * Loads the package information. + * + * @return void + * + * @uses $packageInfo + */ + protected function init() + { + if (!$this->packageInfo) { + $this->packageInfo = $this->loadPackageInfo(); + } + } + + /** + * Loads and returns the PEAR package information. + * + * @return PEAR_PackageFile_v2 Package information object + * + * @throws BuildException When the package does not exist + */ + protected function loadPackageInfo() + { + $cfg = PEAR_Config::singleton($this->config); + $reg = $cfg->getRegistry(); + if (!$reg->packageExists($this->package, $this->channel)) { + throw new BuildException( + sprintf( + 'PEAR package %s/%s does not exist', + $this->channel, $this->package + ) + ); + } + + $packageInfo = $reg->getPackage($this->package, $this->channel); + return $packageInfo; + } + + /** + * Generates the list of included files and directories + * + * @return boolean True if all went well, false if something was wrong + * + * @uses $filesIncluded + * @uses $filesDeselected + * @uses $filesNotIncluded + * @uses $filesExcluded + * @uses $everythingIncluded + * @uses $dirsIncluded + * @uses $dirsDeselected + * @uses $dirsNotIncluded + * @uses $dirsExcluded + */ + public function scan() + { + $this->init(); + $list = $this->packageInfo->getFilelist(); + $found = null; + foreach ($list as $file => $att) { + if ($att['role'] != $this->role) { + continue; + } + $this->filesIncluded[] = $file; + $found = array($file, $att); + } + if ($found !== null) { + list($file, $att) = $found; + $this->setBaseDir(substr($att['installed_as'], 0, -strlen($file))); + } + + return true; + } + +} diff --git a/buildscripts/phing/classes/phing/util/SourceFileScanner.php b/buildscripts/phing/classes/phing/util/SourceFileScanner.php new file mode 100644 index 00000000..d958a15f --- /dev/null +++ b/buildscripts/phing/classes/phing/util/SourceFileScanner.php @@ -0,0 +1,159 @@ +<?php +/* + * $Id: 0555ae8b4e7418c211bd69a066877ab8cf95fbb8 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 that collects the functionality of the various + * scanDir methods that have been scattered in several tasks before. + * + * The only method returns an array of source files. The array is a + * subset of the files given as a parameter and holds only those that + * are newer than their corresponding target files. + * @package phing.util + */ +class SourceFileScanner { + + /** Instance of FileUtils */ + private $fileUtils; + + /** Task this class is working for -- for logging purposes. */ + private $task; + + /** + * @param task The task we should log messages through + */ + function __construct($task) { + $this->task = $task; + $this->fileUtils = new FileUtils(); + } + + /** + * Restrict the given set of files to those that are newer than + * their corresponding target files. + * + * @param files the original set of files + * @param srcDir all files are relative to this directory + * @param destDir target files live here. if null file names + * returned by the mapper are assumed to be absolute. + * @param FilenameMapper knows how to construct a target file names from + * source file names. + * @param force Boolean that determines if the files should be + * forced to be copied. + */ + function restrict(&$files, $srcDir, $destDir, $mapper, $force = false) { + $now = time(); + $targetList = ""; + + /* + If we're on Windows, we have to munge the time up to 2 secs to + be able to check file modification times. + (Windows has a max resolution of two secs for modification times) + */ + $osname = strtolower(Phing::getProperty('os.name')); + + // indexOf() + $index = ((($res = strpos($osname, 'win')) === false) ? -1 : $res); + if ($index >= 0 ) { + $now += 2000; + } + + $v = array(); + + for ($i=0, $size=count($files); $i < $size; $i++) { + + $targets = $mapper->main($files[$i]); + if (empty($targets)) { + $this->task->log($files[$i]." skipped - don't know how to handle it", Project::MSG_VERBOSE); + continue; + } + + $src = null; + try { + if ($srcDir === null) { + $src = new PhingFile($files[$i]); + } else { + $src = $this->fileUtils->resolveFile($srcDir, $files[$i]); + } + + if ($src->lastModified() > $now) { + $this->task->log("Warning: ".$files[$i]." modified in the future (".$src->lastModified()." > ".$now.")", Project::MSG_WARN); + } + } catch (IOException $ioe) { + $this->task->log("Unable to read file ".$files[$i]." (skipping): " . $ioe->getMessage()); + continue; + } + + $added = false; + $targetList = ""; + + for ($j=0,$_j=count($targets); (!$added && $j < $_j); $j++) { + + $dest = null; + if ($destDir === null) { + $dest = new PhingFile($targets[$j]); + } else { + $dest = $this->fileUtils->resolveFile($destDir, $targets[$j]); + } + + if (!$dest->exists()) { + $this->task->log($files[$i]." added as " . $dest->__toString() . " doesn't exist.", Project::MSG_VERBOSE); + $v[] =$files[$i]; + $added = true; + } elseif ($src->lastModified() > $dest->lastModified()) { + $this->task->log($files[$i]." added as " . $dest->__toString() . " is outdated.", Project::MSG_VERBOSE ); + $v[]=$files[$i]; + $added = true; + } elseif ($force === true) { + $this->task->log($files[$i]." added as " . $dest->__toString() . " is forced to be overwritten.", Project::MSG_VERBOSE ); + $v[]=$files[$i]; + $added = true; + } else { + if (strlen($targetList) > 0) { + $targetList .= ", "; + } + $targetList .= $dest->getAbsolutePath(); + } + } + + if (!$added) { + $this->task->log($files[$i]." omitted as ".$targetList." ".(count($targets) === 1 ? " is " : " are ")."up to date.", Project::MSG_VERBOSE); + } + + } + $result = array(); + $result = $v; + return $result; + } + + /** + * Convenience layer on top of restrict that returns the source + * files as PhingFile objects (containing absolute paths if srcDir is + * absolute). + */ + function restrictAsFiles(&$files, &$srcDir, &$destDir, &$mapper) { + $res = $this->restrict($files, $srcDir, $destDir, $mapper); + $result = array(); + for ($i=0; $i<count($res); $i++) { + $result[$i] = new PhingFile($srcDir, $res[$i]); + } + return $result; + } +} + diff --git a/buildscripts/phing/classes/phing/util/StringHelper.php b/buildscripts/phing/classes/phing/util/StringHelper.php new file mode 100644 index 00000000..31d0b0e9 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/StringHelper.php @@ -0,0 +1,208 @@ +<?php + +/** + * String helper utility class. + * + * This class includes some Java-like functions for parsing strings, + * as well as some functions for getting qualifiers / unqualifying phing-style + * classpaths. (e.g. "phing.util.StringHelper"). + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.system.util + */ +class StringHelper { + + private static $TRUE_VALUES = array("on", "true", "t", "yes"); + private static $FALSE_VALUES = array("off", "false", "f", "no"); + + /** + * Replaces identifier tokens with corresponding text values in passed string. + * + * @param array $strings Array of strings to multiply. (If string is passed, will convert to array) + * @param array $tokens The tokens to search for. + * @param array $replacements The values with which to replace found tokens. + * @return string + */ + public static function multiply($strings, $tokens, $replacements) { + $strings = (array) $strings; + $results = array(); + foreach ($strings as $string) { + $results[] = str_replace($tokens, $replacements, $string); + } + return $results; + } + + /** + * Remove qualification to name. + * E.g. eg.Cat -> Cat + * @param string $qualifiedName + * @param string $separator Character used to separate. + */ + public static function unqualify($qualifiedName, $separator = '.') { + // if false, then will be 0 + $pos = strrpos($qualifiedName, $separator); + if ($pos === false) { + return $qualifiedName; // there is no '.' in the qualifed name + } else { + return substr($qualifiedName, $pos + 1); // start just after '.' + } + } + + /** + * Converts a string to an indexed array of chars + * There's really no reason for this to be used in PHP, since strings + * are all accessible using the $string{0} notation. + * @param string $string + * @return array + * @deprecated + */ + public static function toCharArray($str) { + $ret=array(); + $len=strlen($str); + for ($i=0; $i < $len; $i++) { + $ret[] = $str{$i}; + } + return $ret; + } + + /** + * Get the qualifier part of a qualified name. + * E.g. eg.Cat -> eg + * @return string + */ + public static function qualifier($qualifiedName, $seperator = '.') { + $pos = strrchr($qualifiedName, $seperator); + if ($pos === false) { + return ''; + } else { + return substr($qualifiedName, 0, $pos); + } + } + + /** + * @param array $columns String[] + * @param string $prefix + * @return array String[] + */ + public static function prefix( $columns, $prefix) { + if ($prefix == null) return $columns; + $qualified = array(); + foreach($columns as $key => $column) { + $qualified[$key] = $prefix . $column; + } + return $qualified; + } + + /** + * + * @return string + */ + public static function root($qualifiedName, $separator = '.') { + $loc = strpos($qualifiedName, $separator); + return ($loc === false) ? $qualifiedName : substr($qualifiedName, 0, $loc); + } + + /** + * @return int + */ + public static function hashCode($string) { + return crc32($string); + } + + /** + * @return boolean + */ + public static function booleanValue($s) { + if (is_bool($s)) { + return $s; // it's already boolean (not a string) + } + // otherwise assume it's something like "true" or "t" + $trimmed = strtolower(trim($s)); + return (boolean) in_array($trimmed, self::$TRUE_VALUES); + } + + /** tests if a string is a representative of a boolean */ + public static function isBoolean($s) { + + if (is_bool($s)) { + return true; // it already is boolean + } + + if ($s === "" || $s === null || !is_string($s)) { + return false; // not a valid string for testing + } + + $test = trim(strtolower($s)); + return (boolean) in_array($test, array_merge(self::$FALSE_VALUES, self::$TRUE_VALUES)); + } + + /** + * Creates a key based on any number of passed params. + * @return string + */ + public static function key() { + $args = func_get_args(); + return serialize($args); + } + + /** tests if a string starts with a given string */ + public static function startsWith($check, $string) { + if ($check === "" || $check === $string) { + return true; + } else { + return (strpos($string, $check) === 0) ? true : false; + } + } + + /** tests if a string ends with a given string */ + public static function endsWith($check, $string) { + if ($check === "" || $check === $string) { + return true; + } else { + return (strpos(strrev($string), strrev($check)) === 0) ? true : false; + } + } + + /** + * a natural way of getting a subtring, php's circular string buffer and strange + * return values suck if you want to program strict as of C or friends + */ + public static function substring($string, $startpos, $endpos = -1) { + $len = strlen($string); + $endpos = (int) (($endpos === -1) ? $len-1 : $endpos); + if ($startpos > $len-1 || $startpos < 0) { + trigger_error("substring(), Startindex out of bounds must be 0<n<$len", E_USER_ERROR); + } + if ($endpos > $len-1 || $endpos < $startpos) { + trigger_error("substring(), Endindex out of bounds must be $startpos<n<".($len-1), E_USER_ERROR); + } + if ($startpos === $endpos) { + return (string) $string{$startpos}; + } else { + $len = $endpos-$startpos; + } + return substr($string, $startpos, $len+1); + } + + /** + * Does the value correspond to a slot variable? + * @param string $value + */ + public static function isSlotVar($value) { + $value = trim($value); + if ($value === "") return false; + return preg_match('/^%\{([\w\.\-]+)\}$/', $value); + } + + /** + * Extracts the variable name for a slot var in the format %{task.current_file} + * @param string $var The var from build file. + * @return string Extracted name part. + */ + public static function slotVar($var) { + return trim($var, '%{} '); + } + +} + + diff --git a/buildscripts/phing/classes/phing/util/regexp/PregEngine.php b/buildscripts/phing/classes/phing/util/regexp/PregEngine.php new file mode 100644 index 00000000..76cf56b3 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/regexp/PregEngine.php @@ -0,0 +1,167 @@ +<?php +/* + * $Id: 94607411e16d4c9091369ff4a65ea8f44bde8781 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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/util/regexp/RegexpEngine.php'; + +/** + * PREG Regexp Engine. + * Implements a regexp engine using PHP's preg_match(), preg_match_all(), and preg_replace() functions. + * + * @author hans lellelid, hans@velum.net + * @package phing.util.regexp + */ +class PregEngine implements RegexpEngine { + + /** + * Set to null by default to distinguish between false and not set + * @var boolean + */ + private $ignoreCase = null; + + /** + * Set to null by default to distinguish between false and not set + * @var boolean + */ + private $multiline = null; + + /** + * Pattern modifiers + * @link http://php.net/manual/en/reference.pcre.pattern.modifiers.php + * @var string + */ + private $modifiers = null; + + /** + * Sets pattern modifiers for regex engine + * + * @param string $mods Modifiers to be applied to a given regex + * @return void + */ + public function setModifiers($mods) { + $this->modifiers = (string)$mods; + } + + /** + * Gets pattern modifiers. + * @return string + */ + public function getModifiers() { + $mods = $this->modifiers; + if($this->getIgnoreCase()) { + $mods .= 'i'; + } elseif($this->getIgnoreCase() === false) { + $mods = str_replace('i', '', $mods); + } + if($this->getMultiline()) { + $mods .= 's'; + } elseif($this->getMultiline() === false) { + $mods = str_replace('s', '', $mods); + } + // filter out duplicates + $mods = preg_split('//', $mods, -1, PREG_SPLIT_NO_EMPTY); + $mods = implode('', array_unique($mods)); + return $mods; + } + + /** + * Sets whether or not regex operation is case sensitive. + * @param boolean $bit + * @return void + */ + function setIgnoreCase($bit) { + $this->ignoreCase = (boolean) $bit; + } + + /** + * Gets whether or not regex operation is case sensitive. + * @return boolean + */ + function getIgnoreCase() { + return $this->ignoreCase; + } + + /** + * Sets whether regexp should be applied in multiline mode. + * @param boolean $bit + */ + function setMultiline($bit) { + $this->multiline = $bit; + } + + /** + * Gets whether regexp is to be applied in multiline mode. + * @return boolean + */ + function getMultiline() { + return $this->multiline; + } + + /** + * The pattern needs to be converted into PREG style -- which includes adding expression delims & any flags, etc. + * @param string $pattern + * @return string prepared pattern. + */ + private function preparePattern($pattern) + { + // Use backquotes since hardly ever found in a regexp pattern, avoids using preg_quote + return '`'.$pattern.'`' . $this->getModifiers(); + } + + /** + * Matches pattern against source string and sets the matches array. + * @param string $pattern The regex pattern to match. + * @param string $source The source string. + * @param array $matches The array in which to store matches. + * @return boolean Success of matching operation. + */ + function match($pattern, $source, &$matches) { + return preg_match($this->preparePattern($pattern), $source, $matches); + } + + /** + * Matches all patterns in source string and sets the matches array. + * @param string $pattern The regex pattern to match. + * @param string $source The source string. + * @param array $matches The array in which to store matches. + * @return boolean Success of matching operation. + */ + function matchAll($pattern, $source, &$matches) { + return preg_match_all($this->preparePattern($pattern), $source, $matches); + } + + /** + * Replaces $pattern with $replace in $source string. + * References to \1 group matches will be replaced with more preg-friendly + * $1. + * @param string $pattern The regex pattern to match. + * @param string $replace The string with which to replace matches. + * @param string $source The source string. + * @return string The replaced source string. + */ + function replace($pattern, $replace, $source) { + // convert \1 -> $1, because we want to use the more generic \1 in the XML + // but PREG prefers $1 syntax. + $replace = preg_replace('/\\\(\d+)/', '\$$1', $replace); + return preg_replace($this->preparePattern($pattern), $replace, $source); + } + +} + diff --git a/buildscripts/phing/classes/phing/util/regexp/Regexp.php b/buildscripts/phing/classes/phing/util/regexp/Regexp.php new file mode 100755 index 00000000..7188997e --- /dev/null +++ b/buildscripts/phing/classes/phing/util/regexp/Regexp.php @@ -0,0 +1,203 @@ +<?php +/* + * $Id: b669eb9f2dd8533cba67b2058b7cbc2f558bdeae $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * A factory class for regex functions. + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.util.regexp + * @version $Id$ + */ +class Regexp { + + /** + * Matching groups found. + * @var array + */ + private $groups = array(); + + /** + * Pattern to match. + * @var string + */ + private $pattern; + + /** + * Replacement pattern. + * @var string + */ + private $replace; + + /** + * The regex engine -- e.g. 'preg' or 'ereg'; + * @var RegexpEngine + */ + private $engine; + + /** + * Constructor sets the regex engine to use (preg by default). + * @param string $_engineType The regex engine to use. + */ + function __construct($engineType='preg') { + if ($engineType == 'preg') { + include_once 'phing/util/regexp/PregEngine.php'; + $this->engine = new PregEngine(); + } elseif ($engineType == 'ereg') { + include_once 'phing/util/regexp/EregEngine.php'; + $this->engine = new EregEngine(); + } else { + throw new BuildException("Invalid engine type for Regexp: " . $engineType); + } + } + + /** + * Sets pattern to use for matching. + * @param string $pat The pattern to match on. + * @return void + */ + public function setPattern($pat) { + $this->pattern = (string) $pat; + } + + + /** + * Gets pattern to use for matching. + * @return string The pattern to match on. + */ + public function getPattern() { + return $this->pattern; + } + + /** + * Sets replacement string. + * @param string $rep The pattern to replace matches with. + * @return void + */ + public function setReplace($rep) { + $this->replace = (string) $rep; + } + + /** + * Gets replacement string. + * @return string The pattern to replace matches with. + */ + public function getReplace() { + return $this->replace; + } + + /** + * Performs match of specified pattern against $subject. + * @param string $subject The subject, on which to perform matches. + * @return boolean Whether or not pattern matches subject string passed. + */ + public function matches($subject) { + if($this->pattern === null) { + throw new Exception("No pattern specified for regexp match()."); + } + return $this->engine->match($this->pattern, $subject, $this->groups); + } + + /** + * Performs replacement of specified pattern and replacement strings. + * @param string $subject Text on which to perform replacement. + * @return string subject after replacement has been performed. + */ + public function replace($subject) { + if ($this->pattern === null || $this->replace === null) { + throw new Exception("Missing pattern or replacement string regexp replace()."); + } + return $this->engine->replace($this->pattern, $this->replace, $subject); + } + + /** + * Get array of matched groups. + * @return array Matched groups + */ + function getGroups() { + return $this->groups; + } + + /** + * Get specific matched group. + * @param integer $idx + * @return string specified group or NULL if group is not set. + */ + function getGroup($idx) { + if (!isset($this->groups[$idx])) { + return null; + } + return $this->groups[$idx]; + } + + /** + * Sets pattern modifiers for regex engine + * + * @param string $mods Modifiers to be applied to a given regex + * @return void + */ + public function setModifiers($mods) { + $this->engine->setModifiers($mods); + } + + /** + * Gets pattern modifiers. + * Subsequent call to engines getModifiers() filters out duplicates + * i.e. if i is provided in $mods, and setIgnoreCase(true), "i" + * modifier would be included only once + * @return string + */ + public function getModifiers() { + return $this->engine->getModifiers(); + } + + /** + * Sets whether the regexp matching is case insensitive. + * (default is false -- i.e. case sensisitive) + * @param boolean $bit + */ + function setIgnoreCase($bit) { + $this->engine->setIgnoreCase($bit); + } + + /** + * Gets whether the regexp matching is case insensitive. + * @return boolean + */ + function getIgnoreCase() { + return $this->engine->getIgnoreCase(); + } + + /** + * Sets whether regexp should be applied in multiline mode. + * @param boolean $bit + */ + function setMultiline($bit) { + $this->engine->setMultiline($bit); + } + + /** + * Gets whether regexp is to be applied in multiline mode. + * @return boolean + */ + function getMultiline() { + return $this->engine->getMultiline(); + } +} + diff --git a/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php b/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php new file mode 100755 index 00000000..3eb8c408 --- /dev/null +++ b/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php @@ -0,0 +1,73 @@ +<?php +/* + * $Id: 5e2886f3fae60fff1fd142e79717a3a7a4555772 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Contains some shared attributes and methods -- and some abstract methods with + * engine-specific implementations that sub-classes must override. + * + * @author Hans Lellelid <hans@velum.net> + * @package phing.util.regexp + * @version $Id$ + */ +interface RegexpEngine { + + /** + * Sets whether or not regex operation should ingore case. + * @param boolean $bit + * @return void + */ + public function setIgnoreCase($bit); + + /** + * Returns status of ignore case flag. + * @return boolean + */ + public function getIgnoreCase(); + + /** + * Matches pattern against source string and sets the matches array. + * @param string $pattern The regex pattern to match. + * @param string $source The source string. + * @param array $matches The array in which to store matches. + * @return boolean Success of matching operation. + */ + function match($pattern, $source, &$matches); + + /** + * Matches all patterns in source string and sets the matches array. + * @param string $pattern The regex pattern to match. + * @param string $source The source string. + * @param array $matches The array in which to store matches. + * @return boolean Success of matching operation. + */ + function matchAll($pattern, $source, &$matches); + + /** + * Replaces $pattern with $replace in $source string. + * @param string $pattern The regex pattern to match. + * @param string $replace The string with which to replace matches. + * @param string $source The source string. + * @return string The replaced source string. + */ + function replace($pattern, $replace, $source); + +} + |