GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 6a4e57...36c412 )
by joseph
26:54
created

FileOverrider::setPathToProjectRoot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PostProcessor;
4
5
/**
6
 * This class provides the necessary functoinality to allow you to maintain a set of file overrides and to safely apply
7
 * them as part of a post process to your main build process
8
 */
9
class FileOverrider
10
{
11
    /**
12
     * The default path to the overrides folder, relative to the project root
13
     */
14
    public const OVERRIDES_PATH = '/build/overrides';
15
16
    private const EXTENSION_LENGTH_NO_HASH   = 4;
17
    private const EXTENSION_LENGTH_WITH_HASH = 37;
18
19
    /**
20
     * @var string
21
     */
22
    private $pathToProjectRoot;
23
24
    /**
25
     * @var string
26
     */
27
    private $pathToOverridesDirectory;
28
29 5
    public function __construct(
30
        string $pathToProjectRoot = null,
31
        string $relativePathToOverridesDirectory = self::OVERRIDES_PATH
32
    ) {
33 5
        if (null !== $pathToProjectRoot) {
34 5
            $this->setPathToProjectRoot($pathToProjectRoot);
35 5
            $this->setPathToOverridesDirectory($this->pathToProjectRoot . '/' . $relativePathToOverridesDirectory);
36
        }
37 5
    }
38
39
    /**
40
     * @param string $pathToProjectRoot
41
     *
42
     * @return $this
43
     * @throws \RuntimeException
44
     */
45 5
    public function setPathToProjectRoot(string $pathToProjectRoot): self
46
    {
47 5
        $this->pathToProjectRoot = $this->getRealPath($pathToProjectRoot);
48 5
        $this->setPathToOverridesDirectory($this->pathToProjectRoot . self::OVERRIDES_PATH);
49
50 5
        return $this;
51
    }
52
53 5
    private function getRealPath(string $path): string
54
    {
55 5
        $realPath = \realpath($path);
56 5
        if (false === $realPath) {
57
            throw new \RuntimeException('Invalid path ' . $path);
58
        }
59
60 5
        return $realPath;
61
    }
62
63
    /**
64
     * Create a new Override File by copying the file from the project into the project's overrides directory
65
     *
66
     * @param string $pathToFileInProject
67
     *
68
     * @return string
69
     */
70 2
    public function createNewOverride(string $pathToFileInProject): string
71
    {
72 2
        $relativePathToFileInProject = $this->getRelativePathToFile($pathToFileInProject);
73 2
        if (null !== $this->getOverrideForPath($relativePathToFileInProject)) {
74 1
            throw new \RuntimeException('Override already exists for path ' . $relativePathToFileInProject);
75
        }
76
        $overridePath =
77 1
            $this->getOverrideDirectoryForFile($relativePathToFileInProject) .
78 1
            '/' . $this->getFileNameNoExtensionForPath($relativePathToFileInProject) .
79 1
            '.' . $this->getProjectFileHash($relativePathToFileInProject) .
80 1
            '.php';
81 1
        copy($this->pathToProjectRoot . '/' . $relativePathToFileInProject, $overridePath);
82
83 1
        return $this->getRelativePathToFile($overridePath);
84
    }
85
86 5
    private function getRelativePathToFile(string $pathToFileInProject): string
87
    {
88 5
        return str_replace($this->pathToProjectRoot, '', $this->getRealPath($pathToFileInProject));
89
    }
90
91 2
    private function getOverrideForPath(string $relativePathToFileInProject): ?string
92
    {
93 2
        $fileDirectory       = $this->getOverrideDirectoryForFile($relativePathToFileInProject);
94 2
        $fileNameNoExtension = $this->getFileNameNoExtensionForPath($relativePathToFileInProject);
95 2
        $filesInDirectory    = glob("$fileDirectory/$fileNameNoExtension*");
96 2
        if ([] === $filesInDirectory) {
97 1
            return null;
98
        }
99 1
        if (1 === count($filesInDirectory)) {
100 1
            return $fileDirectory . '/' . current($filesInDirectory);
101
        }
102
        throw new \RuntimeException(
103
            'Found more than one override in path ' . $fileDirectory . ': '
104
            . print_r($filesInDirectory, true)
105
        );
106
    }
107
108 2
    private function getOverrideDirectoryForFile(string $relativePathToFileInProject): string
109
    {
110 2
        $path = $this->getPathToOverridesDirectory() . \dirname($relativePathToFileInProject);
111 2
        if (!is_dir($path) && !(mkdir($path, 0777, true) && is_dir($path))) {
112
            throw new \RuntimeException('Failed making override directory path ' . $path);
113
        }
114
115 2
        return $this->getRealPath($path);
116
    }
117
118
    /**
119
     * @return string
120
     */
121 5
    public function getPathToOverridesDirectory(): string
122
    {
123 5
        return $this->getRealPath($this->pathToOverridesDirectory);
124
    }
125
126
    /**
127
     * @param string $pathToOverridesDirectory
128
     *
129
     * @return FileOverrider
130
     */
131 5
    public function setPathToOverridesDirectory(string $pathToOverridesDirectory): FileOverrider
132
    {
133 5
        $this->pathToOverridesDirectory = $this->getRealPath($pathToOverridesDirectory);
134
135 5
        return $this;
136
    }
137
138 2
    private function getFileNameNoExtensionForPath(string $relativePathToFileInProject): string
139
    {
140 2
        $fileName = basename($relativePathToFileInProject);
141
142 2
        return substr($fileName, 0, -self::EXTENSION_LENGTH_NO_HASH);
143
    }
144
145 3
    private function getProjectFileHash(string $relativePathToFileInProject): string
146
    {
147 3
        $contents = \ts\file_get_contents($this->pathToProjectRoot . '/' . $relativePathToFileInProject);
148
149 3
        return md5($contents);
150
    }
151
152
    /**
153
     * Loop over all the override files and update with the file contents from the project
154
     *
155
     * @return array|string[] the file paths that have been updated
156
     */
157 1
    public function updateOverrideFiles(): array
158
    {
159 1
        $filesUpdated = [];
160 1
        foreach ($this->getOverridesIterator() as $pathToFileInOverrides) {
161 1
            $relativePathToFileInProject = $this->getRelativePathFromOverridePath($pathToFileInOverrides);
162 1
            copy($this->pathToProjectRoot . $relativePathToFileInProject, $pathToFileInOverrides);
163 1
            $filesUpdated[] = $this->getRelativePathFromOverridePath($pathToFileInOverrides);
164
        }
165
166 1
        return $this->sortFiles($filesUpdated);
167
    }
168
169
    /**
170
     * Yield file paths in the override folder
171
     *
172
     * @return \Generator|string[]
173
     */
174 3
    private function getOverridesIterator(): \Generator
175
    {
176
        try {
177 3
            $recursiveIterator = new \RecursiveIteratorIterator(
178 3
                new \RecursiveDirectoryIterator(
179 3
                    $this->getPathToOverridesDirectory(),
180 3
                    \RecursiveDirectoryIterator::SKIP_DOTS
181
                ),
182 3
                \RecursiveIteratorIterator::SELF_FIRST
183
            );
184 3
            foreach ($recursiveIterator as $fileInfo) {
185
                /**
186
                 * @var \SplFileInfo $fileInfo
187
                 */
188 3
                if ($fileInfo->isFile()) {
189 3
                    yield $fileInfo->getPathname();
190
                }
191
            }
192 3
        } finally {
193 3
            $recursiveIterator = null;
194 3
            unset($recursiveIterator);
195
        }
196 3
    }
197
198 3
    private function getRelativePathFromOverridePath(string $pathToFileInOverrides): string
199
    {
200 3
        $relativePath = substr($pathToFileInOverrides, strlen($this->getPathToOverridesDirectory()));
201 3
        $relativeDir  = dirname($relativePath);
202 3
        $filename     = basename($pathToFileInOverrides);
203 3
        $filename     = substr($filename, 0, -self::EXTENSION_LENGTH_WITH_HASH) . '.php';
204
205 3
        return $this->getRelativePathToFile(
206 3
            $this->getRealPath($this->pathToProjectRoot . '/' . $relativeDir . '/' . $filename)
207
        );
208
    }
209
210 2
    private function sortFiles(array $files): array
211
    {
212 2
        sort($files, SORT_STRING);
213
214 2
        return $files;
215
    }
216
217
    /**
218
     * Loop over all the override files and copy into the project
219
     *
220
     * @return array|string[] the file paths that have been updated
221
     */
222 2
    public function applyOverrides(): array
223
    {
224 2
        $filesUpdated = [];
225 2
        $errors       = [];
226 2
        foreach ($this->getOverridesIterator() as $pathToFileInOverrides) {
227 2
            $relativePathToFileInProject = $this->getRelativePathFromOverridePath($pathToFileInOverrides);
228 2
            if ($this->overrideFileHashIsCorrect($pathToFileInOverrides)) {
229 1
                copy($pathToFileInOverrides, $this->pathToProjectRoot . $relativePathToFileInProject);
230 1
                $filesUpdated[] = $relativePathToFileInProject;
231 1
                continue;
232
            }
233 1
            $errors[$pathToFileInOverrides] = $this->getProjectFileHash($relativePathToFileInProject);
234
        }
235 2
        if ([] !== $errors) {
236 1
            throw new \RuntimeException('These file hashes were not up to date:' . print_r($errors, true));
237
        }
238
239 1
        return $this->sortFiles($filesUpdated);
240
    }
241
242 2
    private function overrideFileHashIsCorrect(string $pathToFileInOverrides): bool
243
    {
244 2
        $filenameParts = explode('.', basename($pathToFileInOverrides));
245 2
        if (3 !== count($filenameParts)) {
246
            throw new \RuntimeException('Invalid override filename ' . $pathToFileInOverrides);
247
        }
248 2
        $hash                        = $filenameParts[1];
249 2
        $relativePathToFileInProject = $this->getRelativePathFromOverridePath($pathToFileInOverrides);
250
251 2
        return $hash === $this->getProjectFileHash($relativePathToFileInProject);
252
    }
253
}
254