TechnicalDebt::getErrorList()   C
last analyzed

Complexity

Conditions 9
Paths 52

Size

Total Lines 62
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 3
Bugs 2 Features 0
Metric Value
c 3
b 2
f 0
dl 0
loc 62
ccs 0
cts 46
cp 0
rs 6.6867
cc 9
eloc 39
nc 52
nop 0
crap 90

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PHPCI - Continuous Integration for PHP.
4
 *
5
 * @copyright    Copyright 2014, Block 8 Limited.
6
 * @license      https://github.com/Block8/PHPCI/blob/master/LICENSE.md
7
 *
8
 * @link         https://www.phptesting.org/
9
 */
10
11
namespace PHPCI\Plugin;
12
13
use PHPCI;
14
use PHPCI\Builder;
15
use PHPCI\Model\Build;
16
17
/**
18
 * Technical Debt Plugin - Checks for existence of "TODO", "FIXME", etc.
19
 *
20
 * @author       James Inman <[email protected]>
21
 */
22
class TechnicalDebt implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
23
{
24
    /**
25
     * @var \PHPCI\Builder
26
     */
27
    protected $phpci;
28
29
    /**
30
     * @var array
31
     */
32
    protected $suffixes;
33
34
    /**
35
     * @var string
36
     */
37
    protected $directory;
38
39
    /**
40
     * @var int
41
     */
42
    protected $allowed_errors;
43
44
    /**
45
     * @var string, based on the assumption the root may not hold the code to be
46
     *              tested, extends the base path
47
     */
48
    protected $path;
49
50
    /**
51
     * @var array - paths to ignore
52
     */
53
    protected $ignore;
54
55
    /**
56
     * @var array - terms to search for
57
     */
58
    protected $searches;
59
60
    /**
61
     * @var Build
62
     */
63
    protected $build;
64
65
    /**
66
     * Check if this plugin can be executed.
67
     *
68
     * @param $stage
69
     * @param Builder $builder
70
     * @param Build   $build
71
     *
72
     * @return bool
73
     */
74
    public static function canExecute($stage, Builder $builder, Build $build)
75
    {
76
        if ($stage == 'test') {
77
            return true;
78
        }
79
80
        return false;
81
    }
82
83
    /**
84
     * @param \PHPCI\Builder     $phpci
85
     * @param \PHPCI\Model\Build $build
86
     * @param array              $options
87
     */
88
    public function __construct(Builder $phpci, Build $build, array $options = array())
89
    {
90
        $this->phpci = $phpci;
91
        $this->build = $build;
92
        $this->suffixes = array('php');
93
        $this->directory = $phpci->buildPath;
94
        $this->path = '';
95
        $this->ignore = $this->phpci->ignore;
96
        $this->allowed_errors = 0;
97
        $this->searches = array('TODO', 'FIXME', 'TO DO', 'FIX ME');
98
99
        if (isset($options['searches']) && is_array($options['searches'])) {
100
            $this->searches = $options['searches'];
101
        }
102
103
        if (isset($options['zero_config']) && $options['zero_config']) {
104
            $this->allowed_errors = -1;
105
        }
106
107
        $this->setOptions($options);
108
    }
109
110
    /**
111
     * Handle this plugin's options.
112
     *
113
     * @param $options
114
     */
115
    protected function setOptions($options)
116
    {
117
        foreach (array('directory', 'path', 'ignore', 'allowed_errors') as $key) {
118
            if (array_key_exists($key, $options)) {
119
                $this->{$key} = $options[$key];
120
            }
121
        }
122
    }
123
124
    /**
125
     * Runs the plugin.
126
     */
127
    public function execute()
128
    {
129
        $success = true;
130
        $this->phpci->logExecOutput(false);
131
132
        $errorCount = $this->getErrorList();
133
134
        $this->phpci->log("Found $errorCount instances of ".implode(', ', $this->searches));
135
136
        $this->build->storeMeta('technical_debt-warnings', $errorCount);
137
138
        if ($this->allowed_errors != -1 && $errorCount > $this->allowed_errors) {
139
            $success = false;
140
        }
141
142
        return $success;
143
    }
144
145
    /**
146
     * Gets the number and list of errors returned from the search.
147
     *
148
     * @return array
149
     */
150
    public function getErrorList()
151
    {
152
        $dirIterator = new \RecursiveDirectoryIterator($this->directory);
153
        $iterator = new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::SELF_FIRST);
154
        $files = array();
155
156
        $ignores = $this->ignore;
157
        $ignores[] = 'phpci.yml';
158
        $ignores[] = '.phpci.yml';
159
160
        foreach ($iterator as $file) {
161
            $filePath = $file->getRealPath();
162
            $skipFile = false;
163
            foreach ($ignores as $ignore) {
164
                if (stripos($filePath, $ignore) !== false) {
165
                    $skipFile = true;
166
                    break;
167
                }
168
            }
169
170
            // Ignore hidden files, else .git, .sass_cache, etc. all get looped over
171
            if (stripos($filePath, DIRECTORY_SEPARATOR.'.') !== false) {
172
                $skipFile = true;
173
            }
174
175
            if ($skipFile == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
176
                $files[] = $file->getRealPath();
177
            }
178
        }
179
180
        $files = array_filter(array_unique($files));
181
        $errorCount = 0;
182
183
        foreach ($files as $file) {
184
            foreach ($this->searches as $search) {
185
                $fileContent = file_get_contents($file);
186
                $allLines = explode(PHP_EOL, $fileContent);
187
                $beforeString = strstr($fileContent, $search, true);
188
189
                if (false !== $beforeString) {
190
                    $lines = explode(PHP_EOL, $beforeString);
191
                    $lineNumber = count($lines);
192
                    $content = trim($allLines[$lineNumber - 1]);
193
194
                    ++$errorCount;
195
196
                    $fileName = str_replace($this->directory, '', $file);
197
198
                    $this->build->reportError(
199
                        $this->phpci,
200
                        'technical_debt',
201
                        $content,
202
                        PHPCI\Model\BuildError::SEVERITY_LOW,
203
                        $fileName,
204
                        $lineNumber
205
                    );
206
                }
207
            }
208
        }
209
210
        return $errorCount;
211
    }
212
}
213