2015-02-18 15:07:26 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* PHPCI - Continuous Integration for PHP
|
|
|
|
*
|
|
|
|
* @copyright Copyright 2014, Block 8 Limited.
|
|
|
|
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
|
|
|
* @link https://www.phptesting.org/
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace PHPCI\Plugin;
|
|
|
|
|
|
|
|
use PHPCI;
|
|
|
|
use PHPCI\Builder;
|
|
|
|
use PHPCI\Model\Build;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Technical Debt Plugin - Checks for existence of "TODO", "FIXME", etc.
|
|
|
|
*
|
|
|
|
* @author James Inman <james@jamesinman.co.uk>
|
|
|
|
* @package PHPCI
|
|
|
|
* @subpackage Plugins
|
|
|
|
*/
|
|
|
|
class TechnicalDebt implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var \PHPCI\Builder
|
|
|
|
*/
|
|
|
|
protected $phpci;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $suffixes;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $directory;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
protected $allowed_errors;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string, based on the assumption the root may not hold the code to be
|
|
|
|
* tested, extends the base path
|
|
|
|
*/
|
|
|
|
protected $path;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array - paths to ignore
|
|
|
|
*/
|
|
|
|
protected $ignore;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array - terms to search for
|
|
|
|
*/
|
|
|
|
protected $searches;
|
|
|
|
|
2015-02-18 15:15:59 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if this plugin can be executed.
|
|
|
|
*
|
|
|
|
* @param $stage
|
|
|
|
* @param Builder $builder
|
|
|
|
* @param Build $build
|
|
|
|
* @return bool
|
|
|
|
*/
|
2015-02-18 15:07:26 +01:00
|
|
|
public static function canExecute($stage, Builder $builder, Build $build)
|
|
|
|
{
|
|
|
|
if ($stage == 'test') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param \PHPCI\Builder $phpci
|
|
|
|
* @param \PHPCI\Model\Build $build
|
|
|
|
* @param array $options
|
|
|
|
*/
|
|
|
|
public function __construct(Builder $phpci, Build $build, array $options = array())
|
|
|
|
{
|
|
|
|
$this->phpci = $phpci;
|
|
|
|
$this->build = $build;
|
|
|
|
$this->suffixes = array('php');
|
|
|
|
$this->directory = $phpci->buildPath;
|
|
|
|
$this->path = '';
|
|
|
|
$this->ignore = $this->phpci->ignore;
|
|
|
|
$this->allowed_errors = 0;
|
|
|
|
$this->searches = array('TODO', 'FIXME', 'TO DO', 'FIX ME');
|
|
|
|
|
|
|
|
if (isset($options['searches']) && is_array($options['searches'])) {
|
|
|
|
$this->searches = $options['searches'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['zero_config']) && $options['zero_config']) {
|
|
|
|
$this->allowed_errors = -1;
|
|
|
|
}
|
2015-05-14 14:19:55 +02:00
|
|
|
|
|
|
|
$this->setOptions($options);
|
2015-02-18 15:07:26 +01:00
|
|
|
}
|
|
|
|
|
2015-02-18 15:15:59 +01:00
|
|
|
/**
|
|
|
|
* Handle this plugin's options.
|
|
|
|
* @param $options
|
|
|
|
*/
|
2015-02-18 15:07:26 +01:00
|
|
|
protected function setOptions($options)
|
|
|
|
{
|
2015-05-14 14:19:55 +02:00
|
|
|
foreach (array('directory', 'path', 'ignore', 'allowed_errors') as $key) {
|
2015-02-18 15:07:26 +01:00
|
|
|
if (array_key_exists($key, $options)) {
|
|
|
|
$this->{$key} = $options[$key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-02-18 15:26:21 +01:00
|
|
|
* Runs the plugin
|
2015-02-18 15:07:26 +01:00
|
|
|
*/
|
|
|
|
public function execute()
|
|
|
|
{
|
2015-02-18 15:56:04 +01:00
|
|
|
$success = true;
|
2015-02-18 15:07:26 +01:00
|
|
|
$this->phpci->logExecOutput(false);
|
|
|
|
|
2015-02-18 15:26:21 +01:00
|
|
|
list($errorCount, $data) = $this->getErrorList();
|
|
|
|
|
|
|
|
$this->phpci->log("Found $errorCount instances of " . implode(', ', $this->searches));
|
|
|
|
|
|
|
|
$this->build->storeMeta('technical_debt-warnings', $errorCount);
|
|
|
|
$this->build->storeMeta('technical_debt-data', $data);
|
|
|
|
|
|
|
|
if ($this->allowed_errors != -1 && $errorCount > $this->allowed_errors) {
|
|
|
|
$success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $success;
|
|
|
|
}
|
2015-02-18 15:07:26 +01:00
|
|
|
|
2015-02-18 15:26:21 +01:00
|
|
|
/**
|
|
|
|
* Gets the number and list of errors returned from the search
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getErrorList()
|
|
|
|
{
|
2015-02-18 15:07:26 +01:00
|
|
|
$dirIterator = new \RecursiveDirectoryIterator($this->directory);
|
|
|
|
$iterator = new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::SELF_FIRST);
|
2015-03-06 17:44:22 +01:00
|
|
|
$files = array();
|
2015-02-18 15:07:26 +01:00
|
|
|
|
2015-02-18 15:26:21 +01:00
|
|
|
$ignores = $this->ignore;
|
|
|
|
$ignores[] = 'phpci.yml';
|
|
|
|
|
2015-02-18 15:07:26 +01:00
|
|
|
foreach ($iterator as $file) {
|
2015-02-18 15:26:21 +01:00
|
|
|
$filePath = $file->getRealPath();
|
2015-02-18 15:07:26 +01:00
|
|
|
$skipFile = false;
|
|
|
|
foreach ($ignores as $ignore) {
|
|
|
|
if (stripos($filePath, $ignore) !== false) {
|
|
|
|
$skipFile = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore hidden files, else .git, .sass_cache, etc. all get looped over
|
|
|
|
if (stripos($filePath, '/.') !== false) {
|
|
|
|
$skipFile = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($skipFile == false) {
|
|
|
|
$files[] = $file->getRealPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$files = array_filter(array_unique($files));
|
|
|
|
$errorCount = 0;
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
foreach ($files as $file) {
|
|
|
|
foreach ($this->searches as $search) {
|
|
|
|
$fileContent = file_get_contents($file);
|
|
|
|
$allLines = explode(PHP_EOL, $fileContent);
|
|
|
|
$beforeString = strstr($fileContent, $search, true);
|
|
|
|
|
|
|
|
if (false !== $beforeString) {
|
|
|
|
$lines = explode(PHP_EOL, $beforeString);
|
|
|
|
$lineNumber = count($lines);
|
|
|
|
$content = trim($allLines[$lineNumber - 1]);
|
|
|
|
|
|
|
|
$errorCount++;
|
|
|
|
$this->phpci->log("Found $search on line $lineNumber of $file:\n$content");
|
2015-02-20 14:37:36 +01:00
|
|
|
|
|
|
|
$fileName = str_replace($this->directory, '', $file);
|
2015-02-18 15:07:26 +01:00
|
|
|
$data[] = array(
|
2015-02-20 14:37:36 +01:00
|
|
|
'file' => $fileName,
|
2015-02-18 15:07:26 +01:00
|
|
|
'line' => $lineNumber,
|
|
|
|
'message' => $content
|
|
|
|
);
|
2015-02-20 14:37:36 +01:00
|
|
|
|
|
|
|
$this->build->reportError($this->phpci, $fileName, $lineNumber, $content);
|
|
|
|
|
2015-02-18 15:07:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-06 17:44:22 +01:00
|
|
|
|
2015-03-05 09:12:42 +01:00
|
|
|
return array( $errorCount, $data );
|
2015-02-18 15:07:26 +01:00
|
|
|
}
|
|
|
|
}
|