Completed
Push — master ( 954942...2b19b6 )
by Théo
02:40
created

HandleAddPrefix::scopeFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 3
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 2
rs 9.6666
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\RuntimeException;
20
use SplFileInfo;
21
use Symfony\Component\Filesystem\Filesystem;
22
use Symfony\Component\Finder\Finder;
23
use Throwable;
24
use function Humbug\PhpScoper\get_common_path;
25
26
/**
27
 * @final
28
 */
29
class HandleAddPrefix
30
{
31
    /** @internal */
32
    const PHP_FILE_PATTERN = '/\.php$/';
33
34
    private $fileSystem;
35
    private $scoper;
36
37 7
    public function __construct(Scoper $scoper)
38
    {
39 7
        $this->fileSystem = new Filesystem();
40 7
        $this->scoper = $scoper;
41 7
    }
42
43
    /**
44
     * Apply prefix to all the code found in the given paths, AKA scope all the files found.
45
     *
46
     * @param string        $prefix e.g. 'Foo'
47
     * @param string[]      $paths  List of files to scan (absolute paths)
48
     * @param string        $output absolute path to the output directory
49
     * @param ConsoleLogger $logger
50
     */
51 7
    public function __invoke(string $prefix, array $paths, string $output, ConsoleLogger $logger)
52
    {
53 7
        $this->fileSystem->mkdir($output);
54
55
        try {
56 7
            $files = $this->retrieveFiles($paths, $output);
57
58 7
            $this->scopeFiles($files, $prefix, $logger);
59 1
        } catch (Throwable $throwable) {
60 1
            $this->fileSystem->remove($output);
61
62 1
            throw $throwable;
63
        }
64 6
    }
65
66
    /**
67
     * @param string[] $paths
68
     *
69
     * @return string[] absolute paths
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 (is_dir($path)) {
78 3
                $pathsToSearch[] = $path;
79 5
            } elseif (1 === preg_match(self::PHP_FILE_PATTERN, $path)) {
80 7
                $filesToAppend[] = $path;
81
            }
82
        }
83
84 7
        $finder = new Finder();
85
86 7
        $finder->files()
87 7
            ->name(self::PHP_FILE_PATTERN)
88 7
            ->in($pathsToSearch)
89 7
            ->append($filesToAppend)
90 7
            ->sortByName()
91
        ;
92
93 7
        $files = array_values(
94
            array_map(
95
                function (SplFileInfo $fileInfo) {
96 5
                    return $fileInfo->getRealPath();
97 7
                },
98
                iterator_to_array($finder)
99
            )
100
        );
101
102 7
        $commonPath = get_common_path($files);
103
104 7
        return array_reduce(
105
            $files,
106 7
            function (array $files, string $file) use ($output, $commonPath): array {
107 5
                if (false === file_exists($file)) {
108
                    throw new RuntimeException(
109
                        sprintf(
110
                            'Could not find the file "%s".',
111
                            $file
112
                        )
113
                    );
114
                }
115
116 5
                if (false === is_readable($file)) {
117
                    throw new RuntimeException(
118
                        sprintf(
119
                            'Could not read the file "%s".',
120
                            $file
121
                        )
122
                    );
123
                }
124
125 5
                $files[$file] = $output.str_replace($commonPath, '', $file);
126
127 5
                return $files;
128 7
            },
129 7
            []
130
        );
131
    }
132
133
    /**
134
     * @param string[]      $files
135
     * @param string        $prefix
136
     * @param ConsoleLogger $logger
137
     */
138 7
    private function scopeFiles(array $files, string $prefix, ConsoleLogger $logger)
139
    {
140 7
        $count = count($files);
141 7
        $logger->outputFileCount($count);
142
143 7
        foreach ($files as $inputFilePath => $outputFilePath) {
144 5
            $this->scopeFile($inputFilePath, $outputFilePath, $prefix, $logger);
145
        }
146 6
    }
147
148 5
    private function scopeFile(string $inputFilePath, string $outputFilePath, string $prefix, ConsoleLogger $logger)
149
    {
150 5
        $fileContent = file_get_contents($inputFilePath);
151
152 5
        $scoppedContent = $this->scoper->scope($fileContent, $prefix);
153
154 4
        $this->fileSystem->dumpFile($outputFilePath, $scoppedContent);
155
156 4
        $logger->outputSuccess($inputFilePath);
157 4
    }
158
}
159