Passed
Push — main ( f5700b...aaf4f3 )
by Michiel
32:12 queued 25:00
created

src/Phing/Task/Ext/Analyzer/Phploc/PHPLocTask.php (3 issues)

1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Task\Ext\Analyzer\Phploc;
22
23
use Phing\Exception\BuildException;
24
use Phing\Io\File;
25
use Phing\Task;
26
use Phing\Type\Element\FileSetAware;
27
use Phing\Util\StringHelper;
28
use SplFileInfo;
29
30
/**
31
 * Runs phploc a tool for quickly measuring the size of PHP projects.
32
 *
33
 * @package phing.tasks.ext.phploc
34
 * @author  Raphael Stolt <[email protected]>
35
 */
36
class PHPLocTask extends Task
37
{
38
    use FileSetAware;
39
40
    /**
41
     * @var array
42
     */
43
    protected $suffixesToCheck = ['php'];
44
45
    /**
46
     * @var array
47
     */
48
    protected $acceptedReportTypes = ['cli', 'txt', 'xml', 'csv', 'json'];
49
50
    /**
51
     * @var null
52
     */
53
    protected $reportDirectory = null;
54
55
    /**
56
     * @var string
57
     */
58
    protected $reportType = 'cli';
59
60
    /**
61
     * @var string
62
     */
63
    protected $reportFileName = 'phploc-report';
64
65
    /**
66
     * @var bool
67
     */
68
    protected $countTests = false;
69
70
    /**
71
     * @var null|File
72
     */
73
    protected $fileToCheck = null;
74
75
    /**
76
     * @var array
77
     */
78
    protected $filesToCheck = [];
79
80
    /**
81
     * @var PHPLocFormatterElement[]
82
     */
83
    protected $formatterElements = [];
84
85
    /**
86
     * @var string
87
     */
88
    private $pharLocation = "";
89
90
    /**
91
     * @param string $suffixListOrSingleSuffix
92
     */
93
    public function setSuffixes($suffixListOrSingleSuffix)
94
    {
95
        if (strpos($suffixListOrSingleSuffix, ',')) {
96
            $suffixes = explode(',', $suffixListOrSingleSuffix);
97
            $this->suffixesToCheck = array_map('trim', $suffixes);
98
        } else {
99
            $this->suffixesToCheck[] = trim($suffixListOrSingleSuffix);
100
        }
101
    }
102
103
    /**
104
     * @param File $file
105
     */
106
    public function setFile(File $file)
107
    {
108
        $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 Phing\Io\File|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...
109
    }
110
111
    /**
112
     * @param boolean $countTests
113
     */
114
    public function setCountTests($countTests)
115
    {
116
        $this->countTests = StringHelper::booleanValue($countTests);
117
    }
118
119
    /**
120
     * @param string $type
121
     */
122 4
    public function setReportType($type)
123
    {
124 4
        $this->reportType = trim($type);
125
    }
126
127
    /**
128
     * @param string $name
129
     */
130
    public function setReportName($name)
131
    {
132
        $this->reportFileName = trim($name);
133
    }
134
135
    /**
136
     * @param string $directory
137
     */
138 4
    public function setReportDirectory($directory)
139
    {
140 4
        $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...
141
    }
142
143
    /**
144
     * @param string $pharLocation
145
     */
146
    public function setPharLocation($pharLocation)
147
    {
148
        $this->pharLocation = $pharLocation;
149
    }
150
151
    /**
152
     * @param PHPLocFormatterElement $formatterElement
153
     */
154 1
    public function addFormatter(PHPLocFormatterElement $formatterElement)
155
    {
156 1
        $this->formatterElements[] = $formatterElement;
157
    }
158
159
    /**
160
     * @throws BuildException
161
     */
162 5
    protected function loadDependencies()
163
    {
164 5
        if (!empty($this->pharLocation)) {
165
            // hack to prevent PHPLOC from starting in CLI mode and halting Phing
166
            eval(
0 ignored issues
show
The use of eval() is discouraged.
Loading history...
167
                "namespace SebastianBergmann\PHPLOC\CLI;
168
class Application
169
{
170
    public function run() {}
171
}"
172
            );
173
174
            ob_start();
175
            include $this->pharLocation;
176
            ob_end_clean();
177
        }
178
179 5
        if (!class_exists('\SebastianBergmann\PHPLOC\Analyser')) {
180
            if (!@include_once 'SebastianBergmann/PHPLOC/autoload.php') {
181
                throw new BuildException(
182
                    'PHPLocTask depends on PHPLoc being installed and on include_path.',
183
                    $this->getLocation()
184
                );
185
            }
186
        }
187
    }
188
189 5
    public function main()
190
    {
191 5
        $this->loadDependencies();
192
193 5
        $this->validateProperties();
194
195 5
        if (count($this->filesets) > 0) {
196 5
            foreach ($this->filesets as $fileSet) {
197 5
                $directoryScanner = $fileSet->getDirectoryScanner($this->project);
198 5
                $files = $directoryScanner->getIncludedFiles();
199 5
                $directory = $fileSet->getDir($this->project)->getPath();
200
201 5
                foreach ($files as $file) {
202 5
                    if ($this->isFileSuffixSet($file)) {
203 5
                        $this->filesToCheck[] = $directory . DIRECTORY_SEPARATOR . $file;
204
                    }
205
                }
206
            }
207
208 5
            $this->filesToCheck = array_unique($this->filesToCheck);
209
        }
210
211 5
        $this->runPhpLocCheck();
212
    }
213
214
    /**
215
     * @throws BuildException
216
     */
217 5
    private function validateProperties()
218
    {
219 5
        if ($this->fileToCheck === null && count($this->filesets) === 0) {
220
            throw new BuildException('Missing either a nested fileset or the attribute "file" set.');
221
        }
222
223 5
        if ($this->fileToCheck !== null) {
224
            if (!file_exists($this->fileToCheck)) {
225
                throw new BuildException("File to check doesn't exist.");
226
            }
227
228
            if (!$this->isFileSuffixSet($this->fileToCheck)) {
229
                throw new BuildException('Suffix of file to check is not defined in "suffixes" attribute.');
230
            }
231
232
            if (count($this->filesets) > 0) {
233
                throw new BuildException('Either use a nested fileset or "file" attribute; not both.');
234
            }
235
        }
236
237 5
        if (count($this->suffixesToCheck) === 0) {
238
            throw new BuildException('No file suffix defined.');
239
        }
240
241 5
        if (count($this->formatterElements) == 0) {
242 4
            if ($this->reportType === null) {
243
                throw new BuildException('No report type or formatters defined.');
244
            }
245
246 4
            if ($this->reportType !== null && !in_array($this->reportType, $this->acceptedReportTypes)) {
247
                throw new BuildException('Unaccepted report type defined.');
248
            }
249
250 4
            if ($this->reportType !== 'cli' && $this->reportDirectory === null) {
251
                throw new BuildException('No report output directory defined.');
252
            }
253
254 4
            if ($this->reportDirectory !== null && !is_dir($this->reportDirectory)) {
255
                $reportOutputDir = new File($this->reportDirectory);
256
257
                $logMessage = "Report output directory doesn't exist, creating: "
258
                    . $reportOutputDir->getAbsolutePath() . '.';
259
260
                $this->log($logMessage);
261
                $reportOutputDir->mkdirs();
262
            }
263
264 4
            if ($this->reportType !== 'cli') {
265 4
                $this->reportFileName .= '.' . $this->reportType;
266
            }
267
268 4
            $formatterElement = new PHPLocFormatterElement();
269 4
            $formatterElement->setType($this->reportType);
270 4
            $formatterElement->setUseFile($this->reportDirectory !== null);
271 4
            $formatterElement->setToDir($this->reportDirectory);
272 4
            $formatterElement->setOutfile($this->reportFileName);
273 4
            $this->formatterElements[] = $formatterElement;
274
        }
275
    }
276
277
    /**
278
     * @param string $filename
279
     *
280
     * @return boolean
281
     */
282 5
    protected function isFileSuffixSet($filename)
283
    {
284 5
        return in_array(pathinfo($filename, PATHINFO_EXTENSION), $this->suffixesToCheck);
285
    }
286
287 5
    protected function runPhpLocCheck()
288
    {
289 5
        $files = $this->getFilesToCheck();
290 5
        $count = $this->getCountForFiles($files);
291
292 5
        foreach ($this->formatterElements as $formatterElement) {
293 5
            $formatter = PHPLocFormatterFactory::createFormatter($formatterElement);
294
295 5
            if ($formatterElement->getType() != 'cli') {
296 5
                $logMessage = 'Writing report to: '
297 5
                    . $formatterElement->getToDir() . DIRECTORY_SEPARATOR . $formatterElement->getOutfile();
298
299 5
                $this->log($logMessage);
300
            }
301
302 5
            $formatter->printResult($count, $this->countTests);
303
        }
304
    }
305
306
    /**
307
     * @return SplFileInfo[]
308
     */
309 5
    protected function getFilesToCheck()
310
    {
311 5
        $files = [];
312
313 5
        if (count($this->filesToCheck) > 0) {
314 5
            foreach ($this->filesToCheck as $file) {
315 5
                $files[] = (new SplFileInfo($file))->getRealPath();
316
            }
317
        } elseif ($this->fileToCheck !== null) {
318
            $files = [(new SplFileInfo($this->fileToCheck))->getRealPath()];
319
        }
320
321 5
        return $files;
322
    }
323
324
    /**
325
     * @param SplFileInfo[] $files
326
     *
327
     * @return array
328
     */
329 5
    protected function getCountForFiles(array $files)
330
    {
331 5
        $analyserClass = '\\SebastianBergmann\\PHPLOC\\Analyser';
332 5
        $analyser = new $analyserClass();
333
334 5
        return $analyser->countFiles($files, $this->countTests);
335
    }
336
}
337