Passed
Pull Request — master (#14)
by
unknown
03:34
created

SymbolExtractor::extract()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 47
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7.2944

Importance

Changes 0
Metric Value
cc 7
eloc 23
nc 7
nop 2
dl 0
loc 47
ccs 18
cts 22
cp 0.8182
crap 7.2944
rs 8.6186
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright MediaCT. All rights reserved.
4
 * https://www.mediact.nl
5
 */
6
7
namespace Mediact\DependencyGuard\Php;
8
9
use Mediact\DependencyGuard\Iterator\FileIteratorInterface;
10
use Mediact\DependencyGuard\Php\Filter\SymbolFilterInterface;
11
use PhpParser\Error;
12
use PhpParser\NodeTraverser;
13
use PhpParser\Parser;
14
use PhpParser\ParserFactory;
15
16
class SymbolExtractor implements SymbolExtractorInterface
17
{
18
    /** @var Parser */
19
    private $parser;
20
21
    /**
22
     * Constructor.
23
     *
24
     * @param Parser|null $parser
25
     */
26 1
    public function __construct(Parser $parser = null)
27
    {
28 1
        if ($parser === null) {
29 1
            $factory = new ParserFactory();
30 1
            $parser  = $factory->create(ParserFactory::PREFER_PHP7);
31
        }
32
33 1
        $this->parser = $parser;
34 1
    }
35
36
    /**
37
     * Extract the PHP symbols from the given files.
38
     *
39
     * @param FileIteratorInterface $files
40
     * @param SymbolFilterInterface $filter
41
     *
42
     * @return SymbolIteratorInterface
43
     */
44 3
    public function extract(
45
        FileIteratorInterface $files,
46
        SymbolFilterInterface $filter
47
    ): SymbolIteratorInterface {
48 3
        $symbols = [];
49
50 3
        foreach ($files as $file) {
51
            try {
52 2
                $handle = $file->openFile('rb');
53
            } catch (\RuntimeException $e) {
54
                /*
55
                 * File cannot be opened, e.g. not a file, not readable etc.
56
                 */
57
                continue;
58
            }
59
60 2
            $fileSize = $file->getSize();
61
62 2
            if (0 === $fileSize) {
63
                continue;
64
            }
65
66 2
            $contents = $handle->fread($fileSize);
67
68 2
            if (!$contents) { // phpstan thinks this can only return string.
69
                continue;
70
            }
71
72
            try {
73 2
                $statements = $this->parser->parse($contents);
74 1
            } catch (Error $e) {
75
                // Either not a file, file is not readable, not a PHP file or
76
                // the broken file should be detected by other tooling entirely.
77 1
                continue;
78
            }
79
80 1
            $tracker   = new SymbolTracker($filter);
81 1
            $traverser = new NodeTraverser();
82 1
            $traverser->addVisitor($tracker);
83 1
            $traverser->traverse($statements);
84
85 1
            foreach ($tracker->getSymbols() as $node) {
86 1
                $symbols[] = new Symbol($file, $node);
87
            }
88
        }
89
90 3
        return new SymbolIterator(...$symbols);
91
    }
92
}
93