Test Failed
Push — master ( 53494e...bc3061 )
by Théo
02:45
created

ClassAliasStmtAppender::createAliasStmt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the humbug/php-scoper package.
7
 *
8
 * Copyright (c) 2017 Théo FIDRY <[email protected]>,
9
 *                    Pádraic Brady <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Humbug\PhpScoper\PhpParser\NodeVisitor;
16
17
use Humbug\PhpScoper\PhpParser\Node\ClassAliasFuncCall;
18
use Humbug\PhpScoper\PhpParser\NodeVisitor\Resolver\FullyQualifiedNameResolver;
19
use Humbug\PhpScoper\Whitelist;
20
use PhpParser\Node;
21
use PhpParser\Node\Name\FullyQualified;
22
use PhpParser\Node\Stmt;
23
use PhpParser\Node\Stmt\Class_;
24
use PhpParser\Node\Stmt\Expression;
25
use PhpParser\Node\Stmt\Interface_;
26
use PhpParser\Node\Stmt\Namespace_;
27
use PhpParser\NodeVisitorAbstract;
28
use function array_reduce;
29
30
/**
31
 * Appends a `class_alias` to the whitelisted classes.
32
 *
33
 * ```
34
 * namespace A;
35
 *
36
 * class Foo
37
 * {
38
 * }
39
 * ```
40
 *
41
 * =>
42
 *
43
 * ```
44
 * namespace Humbug\A;
45
 *
46
 * class Foo
47
 * {
48
 * }
49
 *
50
 * class_alias('Humbug\A\Foo', 'A\Foo', false);
51
 * ```
52
 *
53
 * @internal
54
 */
55
final class ClassAliasStmtAppender extends NodeVisitorAbstract
56
{
57
    private $prefix;
58
    private $whitelist;
59
    private $nameResolver;
60
61
    public function __construct(string $prefix, Whitelist $whitelist, FullyQualifiedNameResolver $nameResolver)
62
    {
63
        $this->prefix = $prefix;
64
        $this->whitelist = $whitelist;
65
        $this->nameResolver = $nameResolver;
66
    }
67
68
    /**
69
     * @inheritdoc
70
     */
71
    public function afterTraverse(array $nodes): array
72
    {
73
        $newNodes = [];
74
75
        foreach ($nodes as $node) {
76
            if ($node instanceof Namespace_) {
77
                $node = $this->appendToNamespaceStmt($node);
78
            }
79
80
            $newNodes[] = $node;
81
        }
82
83
        return $newNodes;
84
    }
85
86
    private function appendToNamespaceStmt(Namespace_ $namespace): Namespace_
87
    {
88
        $namespace->stmts = array_reduce(
1 ignored issue
show
Documentation Bug introduced by
It seems like \array_reduce($namespace...espaceStmts'), array()) of type * is incompatible with the declared type array<integer,object<PhpParser\Node\Stmt>> of property $stmts.

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...
89
            $namespace->stmts,
90
            [$this, 'createNamespaceStmts'],
91
            []
92
        );
93
94
        return $namespace;
95
    }
96
97
    /**
98
     * @return Stmt[]
99
     */
100
    private function createNamespaceStmts(array $stmts, Stmt $stmt): array
101
    {
102
        $stmts[] = $stmt;
103
104
        if (false === ($stmt instanceof Class_ || $stmt instanceof Interface_)) {
105
            return $stmts;
106
        }
107
        /** @var Class_|Interface_ $stmt */
108
        if (null === $stmt->name) {
109
            return $stmts;
110
        }
111
112
        $originalName = $this->nameResolver->resolveName($stmt->name)->getName();
113
114
        if (false === ($originalName instanceof FullyQualified)
115
            || $this->whitelist->belongsToWhitelistedNamespace((string) $originalName)
116
            || false === $this->whitelist->isSymbolWhitelisted((string) $originalName)
117
        ) {
118
            return $stmts;
119
        }
120
        /* @var FullyQualified $originalName */
121
122
        $stmts[] = $this->createAliasStmt($originalName, $stmt);
123
124
        return $stmts;
125
    }
126
127
    private function createAliasStmt(FullyQualified $originalName, Node $stmt): Expression
128
    {
129
        $call = new ClassAliasFuncCall(
130
            FullyQualified::concat($this->prefix, $originalName),
131
            $originalName,
132
            $stmt->getAttributes()
133
        );
134
135
        $expression = new Expression(
136
            $call,
137
            $stmt->getAttributes()
138
        );
139
140
        $call->setAttribute(ParentNodeAppender::PARENT_ATTRIBUTE, $expression);
141
142
        return $expression;
143
    }
144
}
145