Completed
Push — master ( 72182d...f36c81 )
by Théo
02:00
created

Configuration::retrieveFinders()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 34
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 19
nc 5
nop 1
dl 0
loc 34
rs 8.439
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\Console;
16
17
use InvalidArgumentException;
18
use Symfony\Component\Finder\Finder;
19
20
final class Configuration
21
{
22
    /** @internal */
23
    const FINDER_KEYWORD = 'finders';
24
25
    /** @internal */
26
    const PATCHERS_KEYWORD = 'patchers';
27
28
    /** @internal */
29
    const GLOBAL_NAMESPACE_KEYWORD = 'global_namespace_whitelist';
30
31
    /** @internal */
32
    const KEYWORDS = [
33
        self::FINDER_KEYWORD,
34
        self::PATCHERS_KEYWORD,
35
        self::GLOBAL_NAMESPACE_KEYWORD,
36
    ];
37
38
    private $path;
39
    private $patchers;
40
    private $finders;
41
    private $globalNamespaceWhitelisters;
42
43
    /**
44
     * @param string|null         $path            Absolute path to the configuration file loaded
45
     * @param Finder[]            $finders
46
     * @param callable[]          $patchers        List of closures which can alter the content of the files being
47
     *                                             scoped
48
     * @param callable[]|string[] $globalNamespace List of class names from the global namespace that should be scoped
49
     *                                             or closures filtering if the class should be scoped or not
50
     */
51
    private function __construct(string $path = null, array $finders, array $patchers, array $globalNamespace)
52
    {
53
        $this->path = $path;
54
        $this->patchers = $patchers;
55
        $this->finders = $finders;
56
        $this->globalNamespaceWhitelisters = $globalNamespace;
57
    }
58
59
    /**
60
     * @param string|null $path Absolute path to the configuration file.
61
     *
62
     * @return self
63
     */
64
    public static function load(string $path = null): self
65
    {
66
        if (null === $path) {
67
            return new self(null, [], [], []);
68
        }
69
70
        $config = include $path;
71
72
        if (false === is_array($config)) {
73
            throw new InvalidArgumentException(
74
                sprintf(
75
                    'Expected configuration to be an array, found "%s" instead.',
76
                    gettype($config)
77
                )
78
            );
79
        }
80
81
        self::validateConfigKeys($config);
82
83
        $finders = self::retrieveFinders($config);
84
        $patchers = self::retrievePatchers($config);
85
        $globalNamespace = self::retrieveGlobalNamespaceWhitelisters($config);
86
87
        return new self($path, $finders, $patchers, $globalNamespace);
88
    }
89
90
    public function getPath(): string
91
    {
92
        return $this->path;
93
    }
94
95
    /**
96
     * @return Finder[]
97
     */
98
    public function getFinders(): array
99
    {
100
        return $this->finders;
101
    }
102
103
    /**
104
     * @return callable[]
105
     */
106
    public function getPatchers()
107
    {
108
        return $this->patchers;
109
    }
110
111
    /**
112
     * @return callable[]|string[]
113
     */
114
    public function getGlobalNamespaceWhitelisters()
115
    {
116
        return $this->globalNamespaceWhitelisters;
117
    }
118
119
    private static function validateConfigKeys(array $config)
120
    {
121
        array_map(
122
            ['self', 'validateConfigKey'],
123
            array_keys($config)
124
        );
125
    }
126
127
    private static function validateConfigKey(string $key)
128
    {
129
        if (false === in_array($key, self::KEYWORDS)) {
130
            throw new InvalidArgumentException(
131
                sprintf(
132
                    'Invalid configuration key value "%s" found.',
133
                    $key
134
                )
135
            );
136
        }
137
    }
138
139
    private static function retrieveFinders(array $config): array
140
    {
141
        if (false === array_key_exists(self::FINDER_KEYWORD, $config)) {
142
            return [];
143
        }
144
145
        $finders = $config[self::FINDER_KEYWORD];
146
147
        if (false === is_array($finders)) {
148
            throw new InvalidArgumentException(
149
                sprintf(
150
                    'Expected finders to be an array of "%s", found "%s" instead.',
151
                    Finder::class,
152
                    gettype($finders)
153
                )
154
            );
155
        }
156
157
        foreach ($finders as $index => $finder) {
158
            if ($finder instanceof Finder) {
159
                continue;
160
            }
161
162
            throw new InvalidArgumentException(
163
                sprintf(
164
                    'Expected finders to be an array of "%s", the "%d" element is not.',
165
                    Finder::class,
166
                    $index
167
                )
168
            );
169
        }
170
171
        return $finders;
172
    }
173
174 View Code Duplication
    private static function retrievePatchers(array $config): array
175
    {
176
        if (false === array_key_exists(self::PATCHERS_KEYWORD, $config)) {
177
            return [];
178
        }
179
180
        $patchers = $config[self::PATCHERS_KEYWORD];
181
182
        if (false === is_array($patchers)) {
183
            throw new InvalidArgumentException(
184
                sprintf(
185
                    'Expected patchers to be an array of callables, found "%s" instead.',
186
                    gettype($patchers)
187
                )
188
            );
189
        }
190
191
        foreach ($patchers as $index => $patcher) {
192
            if (is_callable($patcher)) {
193
                continue;
194
            }
195
196
            throw new InvalidArgumentException(
197
                sprintf(
198
                    'Expected patchers to be an array of callables, the "%d" element is not.',
199
                    $index
200
                )
201
            );
202
        }
203
204
        return $patchers;
205
    }
206
207 View Code Duplication
    private static function retrieveGlobalNamespaceWhitelisters(array $config): array
208
    {
209
        if (false === array_key_exists(self::GLOBAL_NAMESPACE_KEYWORD, $config)) {
210
            return [];
211
        }
212
213
        $globalNamespace = $config[self::GLOBAL_NAMESPACE_KEYWORD];
214
215
        if (false === is_array($globalNamespace)) {
216
            throw new InvalidArgumentException(
217
                sprintf(
218
                    'Expected "global_namespace" to be an array, found "%s" instead.',
219
                    gettype($globalNamespace)
220
                )
221
            );
222
        }
223
224
        foreach ($globalNamespace as $index => $className) {
225
            if (is_string($className) || is_callable($className)) {
226
                continue;
227
            }
228
229
            throw new InvalidArgumentException(
230
                sprintf(
231
                    'Expected "global_namespace" to be an array of callables or strings, the "%d" element '
232
                    .'is not.',
233
                    $index
234
                )
235
            );
236
        }
237
238
        return $globalNamespace;
239
    }
240
}
241