Completed
Push — master ( dcddf7...d2fb4d )
by Théo
05:16 queued 03:22
created

HandleAddPrefix::__invoke()   B

Complexity

Conditions 2
Paths 4

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 17
nc 4
nop 8
dl 0
loc 24
ccs 8
cts 8
cp 1
crap 2
rs 8.9713
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\Handler;
16
17
use Closure;
18
use Humbug\PhpScoper\Logger\ConsoleLogger;
19
use Humbug\PhpScoper\Scoper;
20
use Humbug\PhpScoper\Throwable\Exception\ParsingException;
21
use Humbug\PhpScoper\Throwable\Exception\RuntimeException;
22
use SplFileInfo;
23
use Symfony\Component\Filesystem\Filesystem;
24
use Symfony\Component\Finder\Finder;
25
use Throwable;
26
use function Humbug\PhpScoper\get_common_path;
27
28
/**
29
 * @final
30
 */
31
class HandleAddPrefix
32
{
33
    private $fileSystem;
34
    private $scoper;
35
36 10
    public function __construct(Scoper $scoper)
37
    {
38 10
        $this->fileSystem = new Filesystem();
39 10
        $this->scoper = $scoper;
40
    }
41
42
    /**
43
     * Apply prefix to all the code found in the given paths, AKA scope all the files found.
44
     *
45
     * @param string              $prefix                   e.g. 'Foo'
46
     * @param string[]            $paths                    List of files (absolute paths) which will be scoped
47
     * @param string              $output                   Absolute path to the output directory
48
     * @param callable[]          $patchers
49
     * @param string[]            $whitelist                List of classes that will not be scoped
50
     * @param string[]|callable[] $globalNamespaceWhitelist
51
     * @param bool                $stopOnFailure
52
     * @param ConsoleLogger       $logger
53
     */
54 10
    public function __invoke(
55
        string $prefix,
56
        array $paths,
57
        string $output,
58
        array $patchers,
59
        array $whitelist,
60
        array $globalNamespaceWhitelist,
61
        bool $stopOnFailure,
62
        ConsoleLogger $logger
63
    ) {
64 10
        $this->fileSystem->mkdir($output);
65
66
        try {
67 10
            $files = $this->retrieveFiles($paths, $output);
68
69 9
            $globalWhitelister = $this->createGlobalWhitelister($globalNamespaceWhitelist);
70
71 9
            $this->scopeFiles($files, $prefix, $patchers, $whitelist, $globalWhitelister, $stopOnFailure, $logger);
72 3
        } catch (Throwable $throwable) {
73 3
            $this->fileSystem->remove($output);
74
75 3
            throw $throwable;
76
        }
77
    }
78
79
    /**
80
     * @param string[]|callable[] $globalNamespaceWhitelist
81
     *
82
     * @return Closure
83
     */
84 9
    private function createGlobalWhitelister(array $globalNamespaceWhitelist): Closure
85
    {
86
        return function (string $className) use ($globalNamespaceWhitelist): bool {
87
            foreach ($globalNamespaceWhitelist as $whitelister) {
88
                if (is_string($whitelister)) {
89
                    if ($className === $whitelister) {
90
                        return true;
91
                    } else {
92
                        continue;
93
                    }
94
                }
95
96
                /** @var callable $whitelister */
97
                if (true === $whitelister($className)) {
98
                    return true;
99
                }
100
            }
101
102
            return false;
103 9
        };
104
    }
105
106
    /**
107
     * @param string[] $paths
108
     * @param string   $output
109
     *
110
     * @return string[]
111
     */
112 10
    private function retrieveFiles(array $paths, string $output): array
113
    {
114 10
        $pathsToSearch = [];
115 10
        $filesToAppend = [];
116
117 10
        foreach ($paths as $path) {
118 10
            if (false === file_exists($path)) {
119 1
                throw new RuntimeException(
120 1
                    sprintf(
121 1
                        'Could not find the file "%s".',
122 1
                        $path
123
                    )
124
                );
125
            }
126
127 9
            if (is_dir($path)) {
128 3
                $pathsToSearch[] = $path;
129
            } else {
130 9
                $filesToAppend[] = $path;
131
            }
132
        }
133
134 9
        $finder = new Finder();
135
136 9
        $finder->files()
137 9
            ->in($pathsToSearch)
138 9
            ->append($filesToAppend)
139 9
            ->sortByName()
140
        ;
141
142 9
        $files = array_values(
143 9
            array_map(
144
                function (SplFileInfo $fileInfo) {
145 8
                    return $fileInfo->getRealPath();
146 9
                },
147 9
                iterator_to_array($finder)
148
            )
149
        );
150
151 9
        $commonPath = get_common_path($files);
152
153 9
        return array_reduce(
154 9
            $files,
155 9
            function (array $files, string $file) use ($output, $commonPath): array {
156 8
                if (false === file_exists($file)) {
157
                    throw new RuntimeException(
158
                        sprintf(
159
                            'Could not find the file "%s".',
160
                            $file
161
                        )
162
                    );
163
                }
164
165 8
                if (false === is_readable($file)) {
166
                    throw new RuntimeException(
167
                        sprintf(
168
                            'Could not read the file "%s".',
169
                            $file
170
                        )
171
                    );
172
                }
173
174 8
                $files[$file] = $output.str_replace($commonPath, '', $file);
175
176 8
                return $files;
177 9
            },
178 9
            []
179
        );
180
    }
181
182
    /**
183
     * @param string[]      $files
184
     * @param string        $prefix
185
     * @param callable[]    $patchers
186
     * @param string[]      $whitelist
187
     * @param callable      $globalWhitelister
188
     * @param bool          $stopOnFailure
189
     * @param ConsoleLogger $logger
190
     */
191 9
    private function scopeFiles(
192
        array $files,
193
        string $prefix,
194
        array $patchers,
195
        array $whitelist,
196
        callable $globalWhitelister,
197
        bool $stopOnFailure,
198
        ConsoleLogger $logger
199
    ) {
200 9
        $count = count($files);
201 9
        $logger->outputFileCount($count);
202
203 9
        foreach ($files as $inputFilePath => $outputFilePath) {
204 8
            $this->scopeFile($inputFilePath, $outputFilePath, $prefix, $patchers, $whitelist, $globalWhitelister, $stopOnFailure, $logger);
205
        }
206
    }
207
208
    /**
209
     * @param string        $inputFilePath
210
     * @param string        $outputFilePath
211
     * @param string        $prefix
212
     * @param callable[]    $patchers
213
     * @param string[]      $whitelist
214
     * @param callable      $globalWhitelister
215
     * @param bool          $stopOnFailure
216
     * @param ConsoleLogger $logger
217
     */
218 8
    private function scopeFile(
219
        string $inputFilePath,
220
        string $outputFilePath,
221
        string $prefix,
222
        array $patchers,
223
        array $whitelist,
224
        callable $globalWhitelister,
225
        bool $stopOnFailure,
226
        ConsoleLogger $logger
227
    ) {
228
        try {
229 8
            $scoppedContent = $this->scoper->scope($inputFilePath, $prefix, $patchers, $whitelist, $globalWhitelister);
230 3
        } catch (Throwable $error) {
231 3
            $exception = new ParsingException(
232 3
                sprintf(
233 3
                    'Could not parse the file "%s".',
234 3
                    $inputFilePath
235
                ),
236 3
                0,
237 3
                $error
238
            );
239
240 3
            if ($stopOnFailure) {
241 2
                throw $exception;
242
            }
243
244 1
            $logger->outputWarnOfFailure($inputFilePath, $exception);
245
246 1
            $scoppedContent = file_get_contents($inputFilePath);
247
        }
248
249 6
        $this->fileSystem->dumpFile($outputFilePath, $scoppedContent);
250
251 6
        if (false === isset($exception)) {
252 5
            $logger->outputSuccess($inputFilePath);
253
        }
254
    }
255
}
256