Completed
Pull Request — master (#97)
by Théo
03:28 queued 01:25
created

NamespaceStmtPrefixer   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 66
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 66
rs 10
c 0
b 0
f 0
wmc 11
lcom 1
cbo 5

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A enterNode() 0 6 2
A prefixNamespaceStmt() 0 14 2
B shouldPrefixStmt() 0 22 6
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\NodeVisitor;
16
17
use Humbug\PhpScoper\NodeVisitor\Collection\NamespaceStmtCollection;
18
use PhpParser\Node;
19
use PhpParser\Node\Name;
20
use PhpParser\Node\Stmt\Class_;
21
use PhpParser\Node\Stmt\Interface_;
22
use PhpParser\Node\Stmt\Namespace_;
23
use PhpParser\NodeVisitorAbstract;
24
use function Humbug\PhpScoper\clone_node;
25
26
/**
27
 * Prefixes the relevant namespaces.
28
 *
29
 * ```
30
 * namespace Foo;
31
 * ```
32
 *
33
 * =>
34
 *
35
 * ```
36
 * namespace Humbug\Foo;
37
 * ```
38
 */
39
final class NamespaceStmtPrefixer extends NodeVisitorAbstract
40
{
41
    private $prefix;
42
    private $namespaceStatements;
43
    private $whitelist;
44
45
    /**
46
     * @param string                  $prefix
47
     * @param NamespaceStmtCollection $namespaceStatements
48
     * @param string[]                $whitelist
49
     */
50
    public function __construct(string $prefix, NamespaceStmtCollection $namespaceStatements, array $whitelist)
51
    {
52
        $this->prefix = $prefix;
53
        $this->namespaceStatements = $namespaceStatements;
54
        $this->whitelist = $whitelist;
55
    }
56
57
    /**
58
     * @inheritdoc
59
     */
60
    public function enterNode(Node $node): Node
61
    {
62
        return ($node instanceof Namespace_)
63
            ? $this->prefixNamespaceStmt($node)
64
            : $node;
65
    }
66
67
    private function prefixNamespaceStmt(Namespace_ $namespace): Node
68
    {
69
        $originalNamespace = $namespace;
70
71
        if ($this->shouldPrefixStmt($namespace)) {
72
            $originalNamespace = clone_node($namespace);
73
74
            $namespace->name = Name::concat($this->prefix, $namespace->name);
75
        }
76
77
        $this->namespaceStatements->add($namespace, $originalNamespace);
78
79
        return $namespace;
80
    }
81
82
    private function shouldPrefixStmt(Namespace_ $namespace): bool
83
    {
84
        if (null === $namespace->name || $this->prefix === $namespace->name->getFirst()) {
85
            return false;
86
        }
87
88
        $firstStmt = current($namespace->stmts);
89
90
        if (
91
            false === $firstStmt
92
            || false === (
93
                $firstStmt instanceof Class_
94
                || $firstStmt instanceof Interface_
95
            )
96
        ) {
97
            return true;
98
        }
99
        /** @var Class_ $firstStmt */
100
        $className = (string) $namespace->name.'\\'.$firstStmt->name;
101
102
        return false === in_array($className, $this->whitelist);
103
    }
104
}
105