Passed
Pull Request — master (#520)
by Théo
02:22
created

retrieveGlobalWhitelist()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 10
nc 3
nop 2
dl 0
loc 19
rs 9.9332
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Humbug\PhpScoper;
6
7
use InvalidArgumentException;
8
use function array_key_exists;
9
use function array_keys;
10
use function array_values;
11
use function gettype;
12
use function is_array;
13
use function is_bool;
14
use function is_string;
15
use function Safe\sprintf;
16
17
final class ConfigurationWhitelistFactory
18
{
19
    private RegexChecker $regexChecker;
20
21
    public function __construct(RegexChecker $regexChecker)
22
    {
23
        $this->regexChecker = $regexChecker;
24
    }
25
26
    public function createWhitelist(array $config): Whitelist
27
    {
28
        [
29
            $excludedNamespaceRegexes,
30
            $excludedNamespaceNames,
31
        ] = $this->retrieveExcludedNamespaces($config);
32
33
        $whitelist = self::retrieveWhitelistValues($config);
34
35
        $whitelistGlobalConstants = self::retrieveGlobalWhitelist(
36
            $config,
37
            ConfigurationKeys::WHITELIST_GLOBAL_CONSTANTS_KEYWORD,
0 ignored issues
show
Bug introduced by
The constant Humbug\PhpScoper\Configu...LOBAL_CONSTANTS_KEYWORD was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
38
        );
39
        $whitelistGlobalClasses = self::retrieveGlobalWhitelist(
40
            $config,
41
            ConfigurationKeys::WHITELIST_GLOBAL_CLASSES_KEYWORD,
0 ignored issues
show
Bug introduced by
The constant Humbug\PhpScoper\Configu..._GLOBAL_CLASSES_KEYWORD was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
42
        );
43
        $whitelistGlobalFunctions = self::retrieveGlobalWhitelist(
44
            $config,
45
            ConfigurationKeys::WHITELIST_GLOBAL_FUNCTIONS_KEYWORD,
0 ignored issues
show
Bug introduced by
The constant Humbug\PhpScoper\Configu...LOBAL_FUNCTIONS_KEYWORD was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
46
        );
47
48
        return Whitelist::create(
49
            $whitelistGlobalConstants,
50
            $whitelistGlobalClasses,
51
            $whitelistGlobalFunctions,
52
            $excludedNamespaceRegexes,
53
            $excludedNamespaceNames,
54
            ...$whitelist,
55
        );
56
    }
57
58
    /**
59
     * @return array{string[], string[]}
0 ignored issues
show
Documentation Bug introduced by
The doc comment array{string[], string[]} at position 2 could not be parsed: Expected ':' at position 2, but found 'string'.
Loading history...
60
     */
61
    private function retrieveExcludedNamespaces(array $config): array
62
    {
63
        $key = ConfigurationKeys::EXCLUDE_NAMESPACES_KEYWORD;
64
65
        if (!array_key_exists($key, $config)) {
66
            return [];
67
        }
68
69
        $regexesAndNamespaceNames = $config[$key];
70
71
        if (!is_array($regexesAndNamespaceNames)) {
72
            throw new InvalidArgumentException(
73
                sprintf(
74
                    'Expected "%s" to be an array of strings, got "%s" instead.',
75
                    $key,
76
                    gettype($regexesAndNamespaceNames),
77
                ),
78
            );
79
        }
80
81
        // Store the strings in the keys for avoiding a unique check later on
82
        $regexes = [];
83
        $namespaceNames = [];
84
85
        foreach ($regexesAndNamespaceNames as $index => $regexOrNamespaceName) {
86
            if (!is_string($regexOrNamespaceName)) {
87
                throw new InvalidArgumentException(
88
                    sprintf(
89
                        'Expected "%s" to be an array of strings, got "%s" for the element with the index "%s".',
90
                        $key,
91
                        gettype($regexOrNamespaceName),
92
                        $index,
93
                    ),
94
                );
95
            }
96
97
            if ($this->regexChecker->isRegexLike($regexOrNamespaceName)) {
98
                $namespaceNames[$regexOrNamespaceName] = null;
99
100
                continue;
101
            }
102
103
            $errorMessage = $this->regexChecker->validateRegex($regexOrNamespaceName);
104
105
            if (null !== $errorMessage) {
106
                throw new InvalidArgumentException(
107
                    sprintf(
108
                        'Expected "%s" to be an array of valid regexes. The element "%s" with the index "%s" is not: %s.',
109
                        $key,
110
                        $regexOrNamespaceName,
111
                        $index,
112
                        $errorMessage,
113
                    ),
114
                );
115
            }
116
117
            $regexes[$regexOrNamespaceName] = null;
118
        }
119
120
        return [
121
            array_keys($regexes),
122
            array_keys($namespaceNames),
123
        ];
124
    }
125
126
    /**
127
     * return list<string>
128
     */
129
    private static function retrieveWhitelistValues(array $config): array
130
    {
131
        $key = ConfigurationKeys::WHITELIST_KEYWORD;
132
133
        if (!array_key_exists($key, $config)) {
134
            return [];
135
        }
136
137
        $whitelist = $config[$key];
138
139
        if (!is_array($whitelist)) {
140
            throw new InvalidArgumentException(
141
                sprintf(
142
                    'Expected whitelist to be an array of strings, found "%s" instead.',
143
                    gettype($whitelist),
144
                ),
145
            );
146
        }
147
148
        foreach ($whitelist as $index => $className) {
149
            if (is_string($className)) {
150
                continue;
151
            }
152
153
            throw new InvalidArgumentException(
154
                sprintf(
155
                    'Expected whitelist to be an array of string, the "%d" element is not.',
156
                    $index,
157
                ),
158
            );
159
        }
160
161
        return array_values($whitelist);
162
    }
163
164
    private static function retrieveGlobalWhitelist(array $config, string $key): bool
165
    {
166
        if (!array_key_exists($key, $config)) {
167
            return true;
168
        }
169
170
        $value = $config[$key];
171
172
        if (!is_bool($value)) {
173
            throw new InvalidArgumentException(
174
                sprintf(
175
                    'Expected %s to be a boolean, found "%s" instead.',
176
                    $key,
177
                    gettype($value),
178
                ),
179
            );
180
        }
181
182
        return $value;
183
    }
184
}
185