Completed
Push — master ( f56a64...b6e499 )
by Théo
04:01 queued 01:18
created

HandleAddPrefix   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 145
ccs 54
cts 54
cp 1
rs 10
c 0
b 0
f 0
wmc 13
lcom 1
cbo 6

5 Methods

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