. */ require_once 'phing/Task.php'; /** * Runs PHP Mess Detector. Checking PHP files for several potential problems * based on rulesets. * * @package phing.tasks.ext.phpmd * @author Benjamin Schultz * @version $Id: PHPMDTask.php 905 2010-10-05 16:28:03Z mrook $ * @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 */ 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 = 5; /** * 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 */ protected $formatters = array(); /** * Load the necessary environment for running PHPMD. * * @throws BuildException - if the phpmd classes can't be loaded. */ public function init() { /** * Determine PHPMD version number */ @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() ); } /*$version = PHP_PMD::VERSION; if (version_compare($version, '0.2.1') < 0) { throw new BuildException( "PHPMDTask requires PHPMD version >= 0.2.1", $this->getLocation() ); }*/ /** * Other dependencies that should only be loaded when class is actually used. */ require_once 'phing/tasks/ext/phpmd/PHPMDFormatterElement.php'; require_once 'PHP/PMD/AbstractRule.php'; $this->minimumPriority = PHP_PMD_AbstractRule::LOWEST_PRIORITY; } /** * 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($this)); return $this->formatters[$num-1]; } /** * Executes PHPMD 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 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(); } } } $inputPath = implode(',', $filesToParse); $this->log('Processing files...'); $phpmd->processFiles( $inputPath, $this->rulesets, $reportRenderers, $ruleSetFactory ); $this->log('Finished processing files'); } }