Passed
Pull Request — master (#117)
by Andrii
14:28
created

PhpReader.php$0 ➔ enterNode()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 2
ccs 0
cts 0
cp 0
rs 10
cc 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Composer\Config\Reader;
6
7
use PhpParser\Node;
8
use PhpParser\Node\Expr\ArrayDimFetch;
9
use PhpParser\Node\Expr\Variable;
10
use PhpParser\Node\Scalar\String_;
11
use PhpParser\NodeTraverser;
12
use PhpParser\NodeVisitorAbstract;
13
use PhpParser\ParserFactory;
14
use Yiisoft\Composer\Config\Env;
15
use PhpParser\Node\Expr\FuncCall;
16
17
/**
18
 * PhpReader - reads PHP files.
19
 */
20
class PhpReader extends AbstractReader
21
{
22
    protected function readRaw(string $path)
23
    {
24
        $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
25
        $saves = [];
26
        try {
27
            $names = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $names is dead and can be removed.
Loading history...
28
            $ast = $parser->parse(file_get_contents($path));
29
30
            $traverser = new NodeTraverser;
31
            $visitor = new class extends NodeVisitorAbstract {
32
                public static $names;
33
                private $stack;
34
35
                public function beginTraverse(array $nodes) {
0 ignored issues
show
Unused Code introduced by
The parameter $nodes is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

35
                public function beginTraverse(/** @scrutinizer ignore-unused */ array $nodes) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
36
                    $this->stack = [];
37
                }
38
39
                public function enterNode(Node $node) {
40
                    $this->stack[] = $node;
41
                }
42
43
                public function leaveNode(Node $node)
44
                {
45
                    $this->processNode($node);
46
                    array_pop($this->stack);
47
48
                    return $node;
49
                }
50
51
                private function processNode(Node $node)
52
                {
53
                    if (! $node instanceof ArrayDimFetch) {
54
                        return;
55
                    }
56
                    if (! $node->var instanceof Variable) {
57
                        return;
58
                    }
59
                    if (! $node->var->name === '_ENV') {
0 ignored issues
show
introduced by
The condition ! $node->var->name === '_ENV' is always false.
Loading history...
60
                        return;
61
                    }
62
                    if (! $node->dim instanceof String_) {
63
                        return;
64
                    }
65
                    if ($this->inDefine($node)) {
0 ignored issues
show
Unused Code introduced by
The call to anonymous//src/Reader/PhpReader.php$0::inDefine() has too many arguments starting with $node. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
                    if ($this->/** @scrutinizer ignore-call */ inDefine($node)) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
66
                        return;
67
                    }
68
                    $name = $node->dim->value;
69
                    self::$names[$name] = $name;
70
                }
71
72
                private function inDefine(): bool
73
                {
74
                    foreach ($this->stack as $node) {
75
                        if ($node instanceof FuncCall) {
76
                            return true;
77
                        }
78
                    }
79
80
                    return false;
81
                }
82
            };
83
            $traverser->addVisitor($visitor);
84
            $ast = $traverser->traverse($ast);
0 ignored issues
show
Unused Code introduced by
The assignment to $ast is dead and can be removed.
Loading history...
Bug introduced by
It seems like $ast can also be of type null; however, parameter $nodes of PhpParser\NodeTraverser::traverse() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

84
            $ast = $traverser->traverse(/** @scrutinizer ignore-type */ $ast);
Loading history...
85
            foreach ($visitor::$names as $name) {
86
                $saves[$name] = $_ENV[$name];
87
                $_ENV[$name] = Env::get($name);
88
            }
89
        } catch (\Exception $e) {
90
            // do nothing
91
        }
92
93
        $params = $this->builder->getVars()['params'] ?? [];
94
95
        $result = static function (array $params) {
96
            return require func_get_arg(1);
97
        };
98
99
        $res = $result($params, $path);
100
        foreach ($saves as $key => $value) {
101
            $_ENV[$key] = $value;
102
        }
103
104
        return $res;
105
    }
106
}
107