2020use RuntimeException ;
2121use SplFileInfo ;
2222use Symfony \Component \Finder \Finder ;
23+ use const DIRECTORY_SEPARATOR ;
24+ use function dirname ;
25+ use function gettype ;
26+ use function is_array ;
2327use function is_bool ;
28+ use function is_string ;
29+ use function realpath ;
2430
2531/**
2632 * @final
2733 * TODO: make this class as final as soon as the underlying deprecated class is removed.
2834 */
2935class Configuration
3036{
31- private const PREFIX = 'prefix ' ;
37+ private const PREFIX_KEYWORD = 'prefix ' ;
38+ private const WHITELISTED_FILES_KEYWORD = 'files-whitelist ' ;
3239 private const FINDER_KEYWORD = 'finders ' ;
3340 private const PATCHERS_KEYWORD = 'patchers ' ;
3441 private const WHITELIST_KEYWORD = 'whitelist ' ;
@@ -37,10 +44,13 @@ class Configuration
3744 private const WHITELIST_GLOBAL_FUNCTIONS_KEYWORD = 'whitelist-global-functions ' ;
3845
3946 private const KEYWORDS = [
40- self ::PREFIX ,
47+ self ::PREFIX_KEYWORD ,
48+ self ::WHITELISTED_FILES_KEYWORD ,
4149 self ::FINDER_KEYWORD ,
4250 self ::PATCHERS_KEYWORD ,
4351 self ::WHITELIST_KEYWORD ,
52+ self ::WHITELIST_GLOBAL_CONSTANTS_KEYWORD ,
53+ self ::WHITELIST_GLOBAL_FUNCTIONS_KEYWORD ,
4454 self ::WHITELIST_GLOBAL_FUNCTIONS_KEYWORD ,
4555 ];
4656
@@ -49,6 +59,7 @@ class Configuration
4959 private $ filesWithContents ;
5060 private $ patchers ;
5161 private $ whitelist ;
62+ private $ whitelistedFiles ;
5263
5364 /**
5465 * @param string|null $path Absolute path to the configuration file.
@@ -77,14 +88,16 @@ public static function load(string $path = null, array $paths = []): self
7788
7889 $ prefix = self ::retrievePrefix ($ config );
7990
91+ $ whitelistedFiles = null === $ path ? [] : self ::retrieveWhitelistedFiles (dirname ($ path ), $ config );
92+
8093 $ patchers = self ::retrievePatchers ($ config );
8194 $ whitelist = self ::retrieveWhitelist ($ config );
8295
8396 $ finders = self ::retrieveFinders ($ config );
8497 $ filesFromPaths = self ::retrieveFilesFromPaths ($ paths );
8598 $ filesWithContents = self ::retrieveFilesWithContents (chain ($ filesFromPaths , ...$ finders ));
8699
87- return new self ($ path , $ prefix , $ filesWithContents , $ patchers , $ whitelist );
100+ return new self ($ path , $ prefix , $ filesWithContents , $ patchers , $ whitelist, $ whitelistedFiles );
88101 }
89102
90103 /**
@@ -97,19 +110,22 @@ public static function load(string $path = null, array $paths = []): self
97110 * @param Closure $globalNamespaceWhitelisters Closure taking a class name from the global namespace as an argument and
98111 * returning a boolean which if `true` means the class should be scoped
99112 * (i.e. is ignored) or scoped otherwise.
113+ * @param string[] $whitelistedFiles List of absolute paths of files to completely ignore
100114 */
101115 private function __construct (
102116 ?string $ path ,
103117 ?string $ prefix ,
104118 array $ filesWithContents ,
105119 array $ patchers ,
106- Whitelist $ whitelist
120+ Whitelist $ whitelist ,
121+ array $ whitelistedFiles
107122 ) {
108123 $ this ->path = $ path ;
109124 $ this ->prefix = $ prefix ;
110125 $ this ->filesWithContents = $ filesWithContents ;
111126 $ this ->patchers = $ patchers ;
112127 $ this ->whitelist = $ whitelist ;
128+ $ this ->whitelistedFiles = $ whitelistedFiles ;
113129 }
114130
115131 public function withPaths (array $ paths ): self
@@ -127,20 +143,22 @@ public function withPaths(array $paths): self
127143 $ this ->prefix ,
128144 array_merge ($ this ->filesWithContents , $ filesWithContents ),
129145 $ this ->patchers ,
130- $ this ->whitelist
146+ $ this ->whitelist ,
147+ $ this ->whitelistedFiles
131148 );
132149 }
133150
134151 public function withPrefix (?string $ prefix ): self
135152 {
136- $ prefix = self ::retrievePrefix ([self ::PREFIX => $ prefix ]);
153+ $ prefix = self ::retrievePrefix ([self ::PREFIX_KEYWORD => $ prefix ]);
137154
138155 return new self (
139156 $ this ->path ,
140157 $ prefix ,
141158 $ this ->filesWithContents ,
142159 $ this ->patchers ,
143- $ this ->whitelist
160+ $ this ->whitelist ,
161+ $ this ->whitelistedFiles
144162 );
145163 }
146164
@@ -172,6 +190,14 @@ public function getWhitelist(): Whitelist
172190 return $ this ->whitelist ;
173191 }
174192
193+ /**
194+ * @return string[]
195+ */
196+ public function getWhitelistedFiles (): array
197+ {
198+ return $ this ->whitelistedFiles ;
199+ }
200+
175201 private static function validateConfigKeys (array $ config ): void
176202 {
177203 array_map (
@@ -200,7 +226,7 @@ private static function validateConfigKey(string $key): void
200226 */
201227 private static function retrievePrefix (array $ config ): ?string
202228 {
203- $ prefix = array_key_exists (self ::PREFIX , $ config ) ? $ config [self ::PREFIX ] : null ;
229+ $ prefix = array_key_exists (self ::PREFIX_KEYWORD , $ config ) ? $ config [self ::PREFIX_KEYWORD ] : null ;
204230
205231 if (null === $ prefix ) {
206232 return null ;
@@ -325,6 +351,46 @@ private static function retrieveWhitelist(array $config): Whitelist
325351 return Whitelist::create ($ whitelistGlobalConstants , $ whitelistGlobalClasses , $ whitelistGlobalFunctions , ...$ whitelist );
326352 }
327353
354+ /**
355+ * @return string[] Absolute paths
356+ */
357+ private static function retrieveWhitelistedFiles (string $ dirPath , array $ config ): array
358+ {
359+ if (false === array_key_exists (self ::WHITELISTED_FILES_KEYWORD , $ config )) {
360+ return [];
361+ }
362+
363+ $ whitelistedFiles = $ config [self ::WHITELIST_KEYWORD ];
364+
365+ if (false === is_array ($ whitelistedFiles )) {
366+ throw new InvalidArgumentException (
367+ sprintf (
368+ 'Expected whitelisted files to be an array of strings, found "%s" instead. ' ,
369+ gettype ($ whitelistedFiles )
370+ )
371+ );
372+ }
373+
374+ foreach ($ whitelistedFiles as $ index => $ file ) {
375+ if (is_string ($ file )) {
376+ throw new InvalidArgumentException (
377+ sprintf (
378+ 'Expected whitelisted files to be an array of string, the "%d" element is not. ' ,
379+ $ index
380+ )
381+ );
382+ }
383+
384+ if ('' !== $ file && DIRECTORY_SEPARATOR !== $ file [0 ]) {
385+ $ file = $ dirPath .DIRECTORY_SEPARATOR .$ file ;
386+ }
387+
388+ $ whitelistedFiles [$ index ] = realpath ($ file );
389+ }
390+
391+ return array_filter ($ whitelistedFiles );
392+ }
393+
328394 private static function retrieveFinders (array $ config ): array
329395 {
330396 if (false === array_key_exists (self ::FINDER_KEYWORD , $ config )) {
0 commit comments