Test Setup Failed
Push — master ( 38b715...21bd50 )
by Théo
02:18
created

Whitelist::lowerConstantName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 12
rs 9.4285
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;
16
17
use Countable;
18
use InvalidArgumentException;
19
use function array_filter;
20
use function array_map;
21
use function array_pop;
22
use function array_unique;
23
use function count;
24
use function explode;
25
use function implode;
26
use function in_array;
27
use function sprintf;
28
use function strtolower;
29
use function substr;
30
use function trim;
31
32
final class Whitelist implements Countable
33
{
34
    private $original;
35
    private $classes;
36
    private $constants;
37
    private $namespaces;
38
    private $whitelistGlobalConstants;
39
40
    public static function create(bool $whitelistGlobalConstants, string ...$elements): self
41
    {
42
        $classes = [];
43
        $constants = [];
44
        $namespaces = [];
45
        $original = [];
46
47
        foreach ($elements as $element) {
48
            if (isset($element[0]) && '\\' === $element[0]) {
49
                $element = substr($element, 1);
50
            }
51
52
            if ('' === trim($element)) {
53
                throw new InvalidArgumentException(
54
                    sprintf(
55
                        'Invalid whitelist element "%s": cannot accept an empty string',
56
                        $element
57
                    )
58
                );
59
            }
60
61
            $original[] = $element;
62
63
            if ('\*' === substr($element, -2)) {
64
                $namespaces[] = strtolower(substr($element, 0, -2));
65
            } elseif ('*' === $element) {
66
                $namespaces[] = '';
67
            } else {
68
                $classes[] = strtolower($element);
69
                $constants[] = self::lowerConstantName($element);
70
            }
71
        }
72
73
        return new self(
74
            $whitelistGlobalConstants,
75
            array_unique($original),
76
            array_unique($classes),
77
            array_unique($constants),
78
            array_unique($namespaces)
79
        );
80
    }
81
82
    /**
83
     * @param string[] $original
84
     * @param string[] $classes
85
     * @param string[] $constants
86
     * @param string[] $namespaces
87
     */
88
    private function __construct(
89
        bool $whitelistGlobalConstants,
90
        array $original,
91
        array $classes,
92
        array $constants,
93
        array $namespaces
94
    ) {
95
        $this->whitelistGlobalConstants = $whitelistGlobalConstants;
96
        $this->original = $original;
97
        $this->classes = $classes;
98
        $this->constants = $constants;
99
        $this->namespaces = $namespaces;
100
    }
101
102
    public function whitelistGlobalConstants(): bool
103
    {
104
        return $this->whitelistGlobalConstants;
105
    }
106
107
    public function isClassWhitelisted(string $name): bool
108
    {
109
        return in_array(strtolower($name), $this->classes, true);
110
    }
111
112
    public function isConstantWhitelisted(string $name): bool
113
    {
114
        return in_array(self::lowerConstantName($name), $this->constants, true);
115
    }
116
117
    /**
118
     * @return string[]
119
     */
120
    public function getClassWhitelistArray(): array
121
    {
122
        return array_filter(
123
            $this->original,
124
            function (string $name): bool {
125
                return '*' !== $name && '\*' !== substr($name, -2);
126
            }
127
        );
128
    }
129
130
    public function isNamespaceWhitelisted(string $name): bool
131
    {
132
        $name = strtolower($name);
133
134
        foreach ($this->namespaces as $namespace) {
135
            if ('' === $namespace || 0 === strpos($name, $namespace)) {
136
                return true;
137
            }
138
        }
139
140
        return false;
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public function count(): int
147
    {
148
        return count($this->classes) + count($this->namespaces);
149
    }
150
151
    public function toArray(): array
152
    {
153
        return $this->original;
154
    }
155
156
    private static function lowerConstantName(string $name): string
157
    {
158
        $parts = explode('\\', $name);
159
160
        $lastPart = array_pop($parts);
161
162
        $parts = array_map('strtolower', $parts);
163
164
        $parts[] = $lastPart;
165
166
        return implode('\\', $parts);
167
    }
168
}
169