diff options
Diffstat (limited to 'buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php')
-rw-r--r-- | buildscripts/phing/classes/phing/tasks/ext/phpcpd/PHPCPDTask.php | 312 |
1 files changed, 312 insertions, 0 deletions
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 |