Test Failed
Pull Request — master (#38)
by Théo
02:36
created

HandleAddPrefix::scopeFile()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 15
nc 4
nop 4
dl 0
loc 24
ccs 2
cts 2
cp 1
crap 3
rs 8.9713
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\Handler;
16
17
use Humbug\PhpScoper\Logger\ConsoleLogger;
18
use Humbug\PhpScoper\Scoper;
19
use Humbug\PhpScoper\Throwable\Exception\ParsingException;
20
use Humbug\PhpScoper\Throwable\Exception\RuntimeException;
21
use PhpParser\Error;
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
    public function __construct(Scoper $scoper)
37 7
    {
38
        $this->fileSystem = new Filesystem();
39 7
        $this->scoper = $scoper;
40 7
    }
41 7
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 to scan (absolute paths)
47
     * @param string        $output absolute path to the output directory
48
     * @param ConsoleLogger $logger
49
     */
50
    public function __invoke(string $prefix, array $paths, string $output, ConsoleLogger $logger)
51 7
    {
52
        $this->fileSystem->mkdir($output);
53 7
54
        try {
55
            $files = $this->retrieveFiles($paths, $output);
56 7
57
            $this->scopeFiles($files, $prefix, $logger);
58 7
        } catch (Throwable $throwable) {
59 1
            $this->fileSystem->remove($output);
60 1
61
            throw $throwable;
62 1
        }
63
    }
64 6
65
    /**
66
     * @param string[] $paths
67
     * @param string   $output
68
     *
69
     * @return string[]
70
     */
71 7
    private function retrieveFiles(array $paths, string $output): array
72
    {
73 7
        $pathsToSearch = [];
74 7
        $filesToAppend = [];
75
76 7
        foreach ($paths as $path) {
77 7
            if (false === file_exists($path)) {
78 3
                throw new RuntimeException(
79 5
                    sprintf(
80 7
                        'Could not find the file "%s".',
81
                        $path
82
                    )
83
                );
84 7
            }
85
86 7
            if (is_dir($path)) {
87 7
                $pathsToSearch[] = $path;
88 7
            } else {
89 7
                $filesToAppend[] = $path;
90 7
            }
91
        }
92
93 7
        $finder = new Finder();
94
95
        $finder->files()
96 5
            ->in($pathsToSearch)
97 7
            ->append($filesToAppend)
98
            ->sortByName()
99
        ;
100
101
        $files = array_values(
102 7
            array_map(
103
                function (SplFileInfo $fileInfo) {
104 7
                    return $fileInfo->getRealPath();
105
                },
106 7
                iterator_to_array($finder)
107 5
            )
108
        );
109
110
        $commonPath = get_common_path($files);
111
112
        return array_reduce(
113
            $files,
114
            function (array $files, string $file) use ($output, $commonPath): array {
115
                if (false === file_exists($file)) {
116 5
                    throw new RuntimeException(
117
                        sprintf(
118
                            'Could not find the file "%s".',
119
                            $file
120
                        )
121
                    );
122
                }
123
124
                if (false === is_readable($file)) {
125 5
                    throw new RuntimeException(
126
                        sprintf(
127 5
                            'Could not read the file "%s".',
128 7
                            $file
129 7
                        )
130
                    );
131
                }
132
133
                $files[$file] = $output.str_replace($commonPath, '', $file);
134
135
                return $files;
136
            },
137
            []
138 7
        );
139
    }
140 7
141 7
    /**
142
     * @param string[]      $files
143 7
     * @param string        $prefix
144 5
     * @param ConsoleLogger $logger
145
     */
146 6
    private function scopeFiles(array $files, string $prefix, ConsoleLogger $logger)
147
    {
148 5
        $count = count($files);
149
        $logger->outputFileCount($count);
150 5
151
        foreach ($files as $inputFilePath => $outputFilePath) {
152 5
            $this->scopeFile($inputFilePath, $outputFilePath, $prefix, $logger);
153
        }
154 4
    }
155
156 4
    private function scopeFile(string $inputFilePath, string $outputFilePath, string $prefix, ConsoleLogger $logger)
157 4
    {
158
        $fileContent = file_get_contents($inputFilePath);
159
160
        try {
161
            $scoppedContent = (1 === preg_match('/.*\.php$/', $inputFilePath)) ?
162
                $this->scoper->scope($fileContent, $prefix)
163
                : $fileContent
164
            ;
165
        } catch (Error $error) {
166
            throw new ParsingException(
167
                sprintf(
168
                    'Could not parse the file "%s".',
169
                    $inputFilePath
170
                ),
171
                0,
172
                $error
173
            );
174
        }
175
176
        $this->fileSystem->dumpFile($outputFilePath, $scoppedContent);
177
178
        $logger->outputSuccess($inputFilePath);
179
    }
180
}
181