Passed
Push — master ( fedd27...f10ad5 )
by Michiel
11:13
created

PHPLocTask   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 299
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 103
dl 0
loc 299
ccs 0
cts 110
cp 0
rs 8.8798
c 0
b 0
f 0
wmc 44

15 Methods

Rating   Name   Duplication   Size   Complexity  
A setCountTests() 0 3 1
A setPharLocation() 0 3 1
A setFile() 0 3 1
A setSuffixes() 0 7 2
A setReportName() 0 3 1
A loadDependencies() 0 22 4
A setReportType() 0 3 1
A setReportDirectory() 0 3 1
A runPhpLocCheck() 0 16 3
A getFilesToCheck() 0 13 4
A main() 0 23 5
A isFileSuffixSet() 0 3 1
A addFormatter() 0 3 1
C validateProperties() 0 57 17
A getCountForFiles() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like PHPLocTask often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PHPLocTask, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * Runs phploc a tool for quickly measuring the size of PHP projects.
22
 *
23
 * @package phing.tasks.ext.phploc
24
 * @author  Raphael Stolt <[email protected]>
25
 */
26
class PHPLocTask extends Task
27
{
28
    use FileSetAware;
29
30
    /**
31
     * @var array
32
     */
33
    protected $suffixesToCheck = ['php'];
34
35
    /**
36
     * @var array
37
     */
38
    protected $acceptedReportTypes = ['cli', 'txt', 'xml', 'csv'];
39
40
    /**
41
     * @var null
42
     */
43
    protected $reportDirectory = null;
44
45
    /**
46
     * @var string
47
     */
48
    protected $reportType = 'cli';
49
50
    /**
51
     * @var string
52
     */
53
    protected $reportFileName = 'phploc-report';
54
55
    /**
56
     * @var bool
57
     */
58
    protected $countTests = false;
59
60
    /**
61
     * @var null|PhingFile
62
     */
63
    protected $fileToCheck = null;
64
65
    /**
66
     * @var array
67
     */
68
    protected $filesToCheck = [];
69
70
    /**
71
     * @var PHPLocFormatterElement[]
72
     */
73
    protected $formatterElements = [];
74
75
    /**
76
     * @var string
77
     */
78
    private $pharLocation = "";
79
80
    /**
81
     * @param string $suffixListOrSingleSuffix
82
     */
83
    public function setSuffixes($suffixListOrSingleSuffix)
84
    {
85
        if (strpos($suffixListOrSingleSuffix, ',')) {
86
            $suffixes = explode(',', $suffixListOrSingleSuffix);
87
            $this->suffixesToCheck = array_map('trim', $suffixes);
88
        } else {
89
            $this->suffixesToCheck[] = trim($suffixListOrSingleSuffix);
90
        }
91
    }
92
93
    /**
94
     * @param PhingFile $file
95
     */
96
    public function setFile(PhingFile $file)
97
    {
98
        $this->fileToCheck = trim($file);
0 ignored issues
show
Documentation Bug introduced by
It seems like trim($file) of type string is incompatible with the declared type PhingFile|null of property $fileToCheck.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
99
    }
100
101
    /**
102
     * @param boolean $countTests
103
     */
104
    public function setCountTests($countTests)
105
    {
106
        $this->countTests = StringHelper::booleanValue($countTests);
107
    }
108
109
    /**
110
     * @param string $type
111
     */
112
    public function setReportType($type)
113
    {
114
        $this->reportType = trim($type);
115
    }
116
117
    /**
118
     * @param string $name
119
     */
120
    public function setReportName($name)
121
    {
122
        $this->reportFileName = trim($name);
123
    }
124
125
    /**
126
     * @param string $directory
127
     */
128
    public function setReportDirectory($directory)
129
    {
130
        $this->reportDirectory = trim($directory);
0 ignored issues
show
Documentation Bug introduced by
It seems like trim($directory) of type string is incompatible with the declared type null of property $reportDirectory.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
131
    }
132
133
    /**
134
     * @param string $pharLocation
135
     */
136
    public function setPharLocation($pharLocation)
137
    {
138
        $this->pharLocation = $pharLocation;
139
    }
140
141
    /**
142
     * @param PHPLocFormatterElement $formatterElement
143
     */
144
    public function addFormatter(PHPLocFormatterElement $formatterElement)
145
    {
146
        $this->formatterElements[] = $formatterElement;
147
    }
148
149
    /**
150
     * @throws BuildException
151
     */
152
    protected function loadDependencies()
153
    {
154
        if (!empty($this->pharLocation)) {
155
            // hack to prevent PHPLOC from starting in CLI mode and halting Phing
156
            eval(
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
157
                "namespace SebastianBergmann\PHPLOC\CLI;
158
class Application
159
{
160
    public function run() {}
161
}"
162
            );
163
164
            ob_start();
165
            include $this->pharLocation;
166
            ob_end_clean();
167
        }
168
169
        if (!class_exists('\SebastianBergmann\PHPLOC\Analyser')) {
170
            if (!@include_once 'SebastianBergmann/PHPLOC/autoload.php') {
171
                throw new BuildException(
172
                    'PHPLocTask depends on PHPLoc being installed and on include_path.',
173
                    $this->getLocation()
174
                );
175
            }
176
        }
177
    }
178
179
    public function main()
180
    {
181
        $this->loadDependencies();
182
183
        $this->validateProperties();
184
185
        if (count($this->filesets) > 0) {
186
            foreach ($this->filesets as $fileSet) {
187
                $directoryScanner = $fileSet->getDirectoryScanner($this->project);
188
                $files = $directoryScanner->getIncludedFiles();
189
                $directory = $fileSet->getDir($this->project)->getPath();
190
191
                foreach ($files as $file) {
192
                    if ($this->isFileSuffixSet($file)) {
193
                        $this->filesToCheck[] = $directory . DIRECTORY_SEPARATOR . $file;
194
                    }
195
                }
196
            }
197
198
            $this->filesToCheck = array_unique($this->filesToCheck);
199
        }
200
201
        $this->runPhpLocCheck();
202
    }
203
204
    /**
205
     * @throws BuildException
206
     */
207
    private function validateProperties()
208
    {
209
        if ($this->fileToCheck === null && count($this->filesets) === 0) {
210
            throw new BuildException('Missing either a nested fileset or the attribute "file" set.');
211
        }
212
213
        if ($this->fileToCheck !== null) {
214
            if (!file_exists($this->fileToCheck)) {
215
                throw new BuildException("File to check doesn't exist.");
216
            }
217
218
            if (!$this->isFileSuffixSet($this->fileToCheck)) {
219
                throw new BuildException('Suffix of file to check is not defined in "suffixes" attribute.');
220
            }
221
222
            if (count($this->filesets) > 0) {
223
                throw new BuildException('Either use a nested fileset or "file" attribute; not both.');
224
            }
225
        }
226
227
        if (count($this->suffixesToCheck) === 0) {
228
            throw new BuildException('No file suffix defined.');
229
        }
230
231
        if (count($this->formatterElements) == 0) {
232
            if ($this->reportType === null) {
233
                throw new BuildException('No report type or formatters defined.');
234
            }
235
236
            if ($this->reportType !== null && !in_array($this->reportType, $this->acceptedReportTypes)) {
237
                throw new BuildException('Unaccepted report type defined.');
238
            }
239
240
            if ($this->reportType !== 'cli' && $this->reportDirectory === null) {
241
                throw new BuildException('No report output directory defined.');
242
            }
243
244
            if ($this->reportDirectory !== null && !is_dir($this->reportDirectory)) {
245
                $reportOutputDir = new PhingFile($this->reportDirectory);
246
247
                $logMessage = "Report output directory doesn't exist, creating: "
248
                    . $reportOutputDir->getAbsolutePath() . '.';
249
250
                $this->log($logMessage);
251
                $reportOutputDir->mkdirs();
252
            }
253
254
            if ($this->reportType !== 'cli') {
255
                $this->reportFileName .= '.' . $this->reportType;
256
            }
257
258
            $formatterElement = new PHPLocFormatterElement();
259
            $formatterElement->setType($this->reportType);
260
            $formatterElement->setUseFile($this->reportDirectory !== null);
261
            $formatterElement->setToDir($this->reportDirectory);
262
            $formatterElement->setOutfile($this->reportFileName);
263
            $this->formatterElements[] = $formatterElement;
264
        }
265
    }
266
267
    /**
268
     * @param string $filename
269
     *
270
     * @return boolean
271
     */
272
    protected function isFileSuffixSet($filename)
273
    {
274
        return in_array(pathinfo($filename, PATHINFO_EXTENSION), $this->suffixesToCheck);
275
    }
276
277
    protected function runPhpLocCheck()
278
    {
279
        $files = $this->getFilesToCheck();
280
        $count = $this->getCountForFiles($files);
281
282
        foreach ($this->formatterElements as $formatterElement) {
283
            $formatter = PHPLocFormatterFactory::createFormatter($formatterElement);
284
285
            if ($formatterElement->getType() != 'cli') {
286
                $logMessage = 'Writing report to: '
287
                    . $formatterElement->getToDir() . DIRECTORY_SEPARATOR . $formatterElement->getOutfile();
288
289
                $this->log($logMessage);
290
            }
291
292
            $formatter->printResult($count, $this->countTests);
293
        }
294
    }
295
296
    /**
297
     * @return SplFileInfo[]
298
     */
299
    protected function getFilesToCheck()
300
    {
301
        $files = [];
302
303
        if (count($this->filesToCheck) > 0) {
304
            foreach ($this->filesToCheck as $file) {
305
                $files[] = new SplFileInfo($file);
306
            }
307
        } elseif ($this->fileToCheck !== null) {
308
            $files = [new SplFileInfo($this->fileToCheck)];
309
        }
310
311
        return $files;
312
    }
313
314
    /**
315
     * @param SplFileInfo[] $files
316
     *
317
     * @return array
318
     */
319
    protected function getCountForFiles(array $files)
320
    {
321
        $analyserClass = '\\SebastianBergmann\\PHPLOC\\Analyser';
322
        $analyser = new $analyserClass();
323
324
        return $analyser->countFiles($files, $this->countTests);
325
    }
326
}
327