edmondscommerce /
doctrine-static-meta
| 1 | <?php |
||||
| 2 | |||||
| 3 | declare(strict_types=1); |
||||
| 4 | |||||
| 5 | namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PostProcessor; |
||||
| 6 | |||||
| 7 | use Generator; |
||||
| 8 | use RecursiveDirectoryIterator; |
||||
| 9 | use RecursiveIteratorIterator; |
||||
| 10 | use RuntimeException; |
||||
| 11 | use SebastianBergmann\Diff\Differ; |
||||
| 12 | use SebastianBergmann\Diff\Output\DiffOnlyOutputBuilder; |
||||
| 13 | use SplFileInfo; |
||||
| 14 | |||||
| 15 | use function copy; |
||||
| 16 | use function dirname; |
||||
| 17 | use function realpath; |
||||
| 18 | |||||
| 19 | /** |
||||
| 20 | * This class provides the necessary functionality to allow you to maintain a set of file overrides and to safely apply |
||||
| 21 | * them as part of a post process to your main build process |
||||
| 22 | * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) |
||||
| 23 | */ |
||||
| 24 | class FileOverrider |
||||
| 25 | { |
||||
| 26 | /** |
||||
| 27 | * The default path to the overrides folder, relative to the project root |
||||
| 28 | */ |
||||
| 29 | public const OVERRIDES_PATH = '/build/overrides'; |
||||
| 30 | |||||
| 31 | private const EXTENSION_LENGTH_NO_HASH_IN_PROJECT = 4; |
||||
| 32 | private const EXTENSION_LENGTH_WITH_HASH_IN_OVERRIDES = 46; |
||||
| 33 | private const OVERRIDE_EXTENSION = 'override'; |
||||
| 34 | |||||
| 35 | /** |
||||
| 36 | * @var string |
||||
| 37 | */ |
||||
| 38 | private $pathToProjectRoot; |
||||
| 39 | /** |
||||
| 40 | * @var string |
||||
| 41 | */ |
||||
| 42 | private $pathToOverridesDirectory; |
||||
| 43 | /** |
||||
| 44 | * @var Differ |
||||
| 45 | */ |
||||
| 46 | private $differ; |
||||
| 47 | |||||
| 48 | 5 | public function __construct( |
|||
| 49 | string $pathToProjectRoot = null |
||||
| 50 | ) { |
||||
| 51 | 5 | if (null !== $pathToProjectRoot) { |
|||
| 52 | 5 | $this->setPathToProjectRoot($pathToProjectRoot); |
|||
| 53 | } |
||||
| 54 | 5 | $builder = new DiffOnlyOutputBuilder(''); |
|||
| 55 | 5 | $this->differ = new Differ($builder); |
|||
| 56 | 5 | } |
|||
| 57 | |||||
| 58 | /** |
||||
| 59 | * @return string |
||||
| 60 | */ |
||||
| 61 | public function getPathToProjectRoot(): string |
||||
| 62 | { |
||||
| 63 | return $this->pathToProjectRoot; |
||||
| 64 | } |
||||
| 65 | |||||
| 66 | /** |
||||
| 67 | * @param string $pathToProjectRoot |
||||
| 68 | * |
||||
| 69 | * @return $this |
||||
| 70 | * @throws RuntimeException |
||||
| 71 | */ |
||||
| 72 | 5 | public function setPathToProjectRoot(string $pathToProjectRoot): self |
|||
| 73 | { |
||||
| 74 | 5 | $this->pathToProjectRoot = $this->getRealPath($pathToProjectRoot); |
|||
| 75 | 5 | $this->setPathToOverridesDirectory($this->pathToProjectRoot . self::OVERRIDES_PATH); |
|||
| 76 | |||||
| 77 | 5 | return $this; |
|||
| 78 | } |
||||
| 79 | |||||
| 80 | public function recreateOverride(string $relativePathToFileInOverrides): array |
||||
| 81 | { |
||||
| 82 | $overridePath = $this->cleanPath($this->pathToProjectRoot . '/' . $relativePathToFileInOverrides); |
||||
| 83 | |||||
| 84 | $relativePathToFileInProject = $this->getRelativePathInProjectFromOverridePath($overridePath); |
||||
| 85 | |||||
| 86 | $old = $relativePathToFileInOverrides . '-old'; |
||||
| 87 | rename($overridePath, $overridePath . '-old'); |
||||
| 88 | |||||
| 89 | $new = $this->createNewOverride($this->pathToProjectRoot . '/' . $relativePathToFileInProject); |
||||
| 90 | |||||
| 91 | return [$old, $new]; |
||||
| 92 | } |
||||
| 93 | |||||
| 94 | 4 | private function cleanPath(string $path): string |
|||
| 95 | { |
||||
| 96 | 4 | return preg_replace('%/{2,}%', '/', $path); |
|||
| 97 | } |
||||
| 98 | |||||
| 99 | 4 | private function getRelativePathInProjectFromOverridePath(string $pathToFileInOverrides): string |
|||
| 100 | { |
||||
| 101 | 4 | $pathToFileInOverrides = $this->cleanPath($pathToFileInOverrides); |
|||
| 102 | 4 | $relativePath = substr($pathToFileInOverrides, strlen($this->getPathToOverridesDirectory())); |
|||
| 103 | 4 | $relativeDir = dirname($relativePath); |
|||
| 104 | 4 | $filename = basename($pathToFileInOverrides); |
|||
| 105 | 4 | $filename = substr($filename, 0, -self::EXTENSION_LENGTH_WITH_HASH_IN_OVERRIDES) . '.php'; |
|||
| 106 | |||||
| 107 | 4 | return $this->getRelativePathToFile( |
|||
| 108 | 4 | $this->getRealPath($this->pathToProjectRoot . '/' . $relativeDir . '/' . $filename) |
|||
| 109 | ); |
||||
| 110 | } |
||||
| 111 | |||||
| 112 | /** |
||||
| 113 | * @return string |
||||
| 114 | */ |
||||
| 115 | 5 | public function getPathToOverridesDirectory(): string |
|||
| 116 | { |
||||
| 117 | 5 | return $this->getRealPath($this->pathToOverridesDirectory); |
|||
| 118 | } |
||||
| 119 | |||||
| 120 | /** |
||||
| 121 | * @param string $pathToOverridesDirectory |
||||
| 122 | * |
||||
| 123 | * @return FileOverrider |
||||
| 124 | */ |
||||
| 125 | 5 | public function setPathToOverridesDirectory(string $pathToOverridesDirectory): FileOverrider |
|||
| 126 | { |
||||
| 127 | 5 | $this->pathToOverridesDirectory = $this->getRealPath($pathToOverridesDirectory); |
|||
| 128 | |||||
| 129 | 5 | return $this; |
|||
| 130 | } |
||||
| 131 | |||||
| 132 | 5 | private function getRealPath(string $path): string |
|||
| 133 | { |
||||
| 134 | 5 | $realPath = realpath($path); |
|||
| 135 | 5 | if (false === $realPath) { |
|||
| 136 | if (!mkdir($path, 0777, true) && !is_dir($path)) { |
||||
| 137 | throw new RuntimeException(sprintf('Directory "%s" was not created', $path)); |
||||
| 138 | } |
||||
| 139 | $realPath = realpath($path); |
||||
| 140 | } |
||||
| 141 | |||||
| 142 | 5 | return $realPath; |
|||
| 143 | } |
||||
| 144 | |||||
| 145 | 5 | private function getRelativePathToFile(string $pathToFileInProject): string |
|||
| 146 | { |
||||
| 147 | 5 | return str_replace($this->pathToProjectRoot, '', $this->getRealPath($pathToFileInProject)); |
|||
| 148 | } |
||||
| 149 | |||||
| 150 | /** |
||||
| 151 | * Create a new Override File by copying the file from the project into the project's overrides directory |
||||
| 152 | * |
||||
| 153 | * @param string $pathToFileInProject |
||||
| 154 | * |
||||
| 155 | * @return string |
||||
| 156 | */ |
||||
| 157 | 2 | public function createNewOverride(string $pathToFileInProject): string |
|||
| 158 | { |
||||
| 159 | 2 | $relativePathToFileInProject = $this->getRelativePathToFile($pathToFileInProject); |
|||
| 160 | 2 | if (null !== $this->getOverrideForPath($relativePathToFileInProject)) { |
|||
| 161 | 1 | throw new RuntimeException('Override already exists for path ' . $relativePathToFileInProject); |
|||
| 162 | } |
||||
| 163 | $overridePath = |
||||
| 164 | 1 | $this->getOverrideDirectoryForFile($relativePathToFileInProject) . |
|||
| 165 | 1 | '/' . $this->getFileNameNoExtensionForPathInProject($relativePathToFileInProject) . |
|||
| 166 | 1 | '.' . $this->getProjectFileHash($relativePathToFileInProject) . |
|||
| 167 | 1 | '.php.override'; |
|||
| 168 | 1 | $pathToFileInProject = $this->pathToProjectRoot . '/' . $relativePathToFileInProject; |
|||
| 169 | 1 | if (false === is_file($pathToFileInProject)) { |
|||
| 170 | throw new RuntimeException('path ' . $pathToFileInProject . ' is not a file'); |
||||
| 171 | } |
||||
| 172 | 1 | copy($pathToFileInProject, $overridePath); |
|||
| 173 | |||||
| 174 | 1 | return $this->getRelativePathToFile($overridePath); |
|||
| 175 | } |
||||
| 176 | |||||
| 177 | 2 | private function getOverrideForPath(string $relativePathToFileInProject): ?string |
|||
| 178 | { |
||||
| 179 | 2 | $fileDirectory = $this->getOverrideDirectoryForFile($relativePathToFileInProject); |
|||
| 180 | 2 | $fileNameNoExtension = $this->getFileNameNoExtensionForPathInProject($relativePathToFileInProject); |
|||
| 181 | 2 | $filesInDirectory = glob("$fileDirectory/$fileNameNoExtension*" . self::OVERRIDE_EXTENSION); |
|||
| 182 | 2 | if ([] === $filesInDirectory) { |
|||
| 183 | 1 | return null; |
|||
| 184 | } |
||||
| 185 | 1 | if (1 === count($filesInDirectory)) { |
|||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
| 186 | 1 | return $fileDirectory . '/' . current($filesInDirectory); |
|||
|
0 ignored issues
–
show
It seems like
$filesInDirectory can also be of type false; however, parameter $array of current() does only seem to accept array, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 187 | } |
||||
| 188 | throw new RuntimeException( |
||||
| 189 | 'Found more than one override in path ' . $fileDirectory . ': ' |
||||
| 190 | . print_r($filesInDirectory, true) |
||||
| 191 | ); |
||||
| 192 | } |
||||
| 193 | |||||
| 194 | 2 | private function getOverrideDirectoryForFile(string $relativePathToFileInProject): string |
|||
| 195 | { |
||||
| 196 | 2 | $path = $this->getPathToOverridesDirectory() . dirname($relativePathToFileInProject); |
|||
| 197 | 2 | if (!is_dir($path) && !(mkdir($path, 0777, true) && is_dir($path))) { |
|||
| 198 | throw new RuntimeException('Failed making override directory path ' . $path); |
||||
| 199 | } |
||||
| 200 | |||||
| 201 | 2 | return $this->getRealPath($path); |
|||
| 202 | } |
||||
| 203 | |||||
| 204 | 2 | private function getFileNameNoExtensionForPathInProject(string $relativePathToFileInProject): string |
|||
| 205 | { |
||||
| 206 | 2 | $fileName = basename($relativePathToFileInProject); |
|||
| 207 | |||||
| 208 | 2 | return substr($fileName, 0, -self::EXTENSION_LENGTH_NO_HASH_IN_PROJECT); |
|||
| 209 | } |
||||
| 210 | |||||
| 211 | 3 | private function getProjectFileHash(string $relativePathToFileInProject): string |
|||
| 212 | { |
||||
| 213 | 3 | return $this->getFileHash($this->pathToProjectRoot . '/' . $relativePathToFileInProject); |
|||
| 214 | } |
||||
| 215 | |||||
| 216 | 4 | private function getFileHash(string $path): string |
|||
| 217 | { |
||||
| 218 | 4 | $contents = \ts\file_get_contents($path); |
|||
| 219 | |||||
| 220 | 4 | return md5($contents); |
|||
| 221 | } |
||||
| 222 | |||||
| 223 | /** |
||||
| 224 | * Loop over all the override files and update with the file contents from the project |
||||
| 225 | * |
||||
| 226 | * @param array|null $toUpdateRelativePathToFilesInProject |
||||
| 227 | * |
||||
| 228 | * @return array[] the file paths that have been updated |
||||
| 229 | */ |
||||
| 230 | 1 | public function updateOverrideFiles(array $toUpdateRelativePathToFilesInProject): array |
|||
| 231 | { |
||||
| 232 | 1 | $filesUpdated = []; |
|||
| 233 | 1 | $filesSkipped = []; |
|||
| 234 | 1 | [$filesDifferent, $filesSame] = $this->compareOverridesWithProject(); |
|||
| 235 | |||||
| 236 | 1 | foreach ($filesDifferent as $fileDifferent) { |
|||
| 237 | 1 | $relativePathToFileInOverrides = $fileDifferent['overridePath']; |
|||
| 238 | 1 | $relativePathToFileInProject = $fileDifferent['projectPath']; |
|||
| 239 | 1 | if (false === isset($toUpdateRelativePathToFilesInProject[$relativePathToFileInProject])) { |
|||
| 240 | $filesSkipped[] = $relativePathToFileInProject; |
||||
| 241 | continue; |
||||
| 242 | } |
||||
| 243 | 1 | $pathToFileInProject = $this->pathToProjectRoot . $relativePathToFileInProject; |
|||
| 244 | 1 | $pathToFileInOverrides = $this->pathToProjectRoot . $relativePathToFileInOverrides; |
|||
| 245 | 1 | copy($pathToFileInProject, $pathToFileInOverrides); |
|||
| 246 | 1 | $filesUpdated[] = $relativePathToFileInProject; |
|||
| 247 | } |
||||
| 248 | |||||
| 249 | return [ |
||||
| 250 | 1 | $this->sortFiles($filesUpdated), |
|||
| 251 | 1 | $this->sortFiles($filesSkipped), |
|||
| 252 | 1 | $this->sortFiles($filesSame), |
|||
| 253 | ]; |
||||
| 254 | } |
||||
| 255 | |||||
| 256 | 1 | public function compareOverridesWithProject(): array |
|||
| 257 | { |
||||
| 258 | 1 | $fileSame = []; |
|||
| 259 | 1 | $filesDifferent = []; |
|||
| 260 | 1 | foreach ($this->getOverridesIterator() as $pathToFileInOverrides) { |
|||
| 261 | 1 | $relativePathToFileInProject = $this->getRelativePathInProjectFromOverridePath($pathToFileInOverrides); |
|||
| 262 | 1 | if ($this->projectFileIsSameAsOverride($pathToFileInOverrides)) { |
|||
| 263 | $fileSame[] = $relativePathToFileInProject; |
||||
| 264 | continue; |
||||
| 265 | } |
||||
| 266 | 1 | $pathToFileInProject = $this->pathToProjectRoot . $relativePathToFileInProject; |
|||
| 267 | 1 | if (false === is_file($pathToFileInProject)) { |
|||
| 268 | throw new RuntimeException( |
||||
| 269 | 'path ' . $pathToFileInProject |
||||
| 270 | . ' is not a file, the override should probably be removed, unless something else has gone wrong?' |
||||
| 271 | ); |
||||
| 272 | } |
||||
| 273 | 1 | $relativePathToFileInOverrides = $this->getRelativePathToFile($pathToFileInOverrides); |
|||
| 274 | |||||
| 275 | 1 | $filesDifferent[$relativePathToFileInProject]['overridePath'] = $relativePathToFileInOverrides; |
|||
| 276 | 1 | $filesDifferent[$relativePathToFileInProject]['projectPath'] = $relativePathToFileInProject; |
|||
| 277 | 1 | $filesDifferent[$relativePathToFileInProject]['diff'] = $this->getDiff( |
|||
| 278 | 1 | $relativePathToFileInProject, |
|||
| 279 | 1 | $relativePathToFileInOverrides |
|||
| 280 | ); |
||||
| 281 | } |
||||
| 282 | |||||
| 283 | 1 | return [$this->sortFilesByKey($filesDifferent), $this->sortFiles($fileSame)]; |
|||
| 284 | } |
||||
| 285 | |||||
| 286 | /** |
||||
| 287 | * Yield file paths in the override folder |
||||
| 288 | * |
||||
| 289 | * @return Generator|string[] |
||||
| 290 | */ |
||||
| 291 | 4 | private function getOverridesIterator(): Generator |
|||
| 292 | { |
||||
| 293 | try { |
||||
| 294 | 4 | $recursiveIterator = new RecursiveIteratorIterator( |
|||
| 295 | 4 | new RecursiveDirectoryIterator( |
|||
| 296 | 4 | $this->getPathToOverridesDirectory(), |
|||
| 297 | 4 | RecursiveDirectoryIterator::SKIP_DOTS |
|||
| 298 | ), |
||||
| 299 | 4 | RecursiveIteratorIterator::SELF_FIRST |
|||
| 300 | ); |
||||
| 301 | 4 | foreach ($recursiveIterator as $fileInfo) { |
|||
| 302 | /** |
||||
| 303 | * @var SplFileInfo $fileInfo |
||||
| 304 | */ |
||||
| 305 | 4 | if ($fileInfo->isFile()) { |
|||
| 306 | if ( |
||||
| 307 | 4 | self::OVERRIDE_EXTENSION !== substr( |
|||
| 308 | 4 | $fileInfo->getFilename(), |
|||
| 309 | 4 | -strlen(self::OVERRIDE_EXTENSION) |
|||
| 310 | ) |
||||
| 311 | ) { |
||||
| 312 | continue; |
||||
| 313 | } |
||||
| 314 | 4 | $overridesPath = $fileInfo->getPathname(); |
|||
| 315 | 4 | $this->checkForDuplicateOverrides($overridesPath); |
|||
| 316 | 4 | yield $overridesPath; |
|||
| 317 | } |
||||
| 318 | } |
||||
| 319 | 4 | } finally { |
|||
| 320 | 4 | $recursiveIterator = null; |
|||
| 321 | 4 | unset($recursiveIterator); |
|||
| 322 | } |
||||
| 323 | 4 | } |
|||
| 324 | |||||
| 325 | 4 | private function checkForDuplicateOverrides(string $overridesPath): void |
|||
| 326 | { |
||||
| 327 | 4 | $overridesPathNoExtension = substr( |
|||
| 328 | 4 | $overridesPath, |
|||
| 329 | 4 | 0, |
|||
| 330 | 4 | -self::EXTENSION_LENGTH_WITH_HASH_IN_OVERRIDES |
|||
| 331 | ); |
||||
| 332 | |||||
| 333 | 4 | $glob = glob($overridesPathNoExtension . '*.' . self::OVERRIDE_EXTENSION); |
|||
| 334 | 4 | if (count($glob) > 1) { |
|||
|
0 ignored issues
–
show
It seems like
$glob can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 335 | $glob = array_map('basename', $glob); |
||||
|
0 ignored issues
–
show
It seems like
$glob can also be of type false; however, parameter $arr1 of array_map() does only seem to accept array, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 336 | $dirname = dirname($overridesPathNoExtension); |
||||
| 337 | throw new RuntimeException( |
||||
| 338 | "Found duplicated overrides in:\n\n$dirname\n\n" |
||||
| 339 | . print_r($glob, true) |
||||
| 340 | . "\n\nYou need to fix this so that there is only one override" |
||||
| 341 | ); |
||||
| 342 | } |
||||
| 343 | 4 | } |
|||
| 344 | |||||
| 345 | /** |
||||
| 346 | * Is the file in the project the same as the override file already? |
||||
| 347 | * |
||||
| 348 | * @param string $pathToFileInOverrides |
||||
| 349 | * |
||||
| 350 | * @return bool |
||||
| 351 | */ |
||||
| 352 | 2 | private function projectFileIsSameAsOverride(string $pathToFileInOverrides): bool |
|||
| 353 | { |
||||
| 354 | 2 | $relativePathToFileInProject = $this->getRelativePathInProjectFromOverridePath($pathToFileInOverrides); |
|||
| 355 | |||||
| 356 | 2 | return $this->getFileHash($this->pathToProjectRoot . '/' . $relativePathToFileInProject) === |
|||
| 357 | 2 | $this->getFileHash($pathToFileInOverrides); |
|||
| 358 | } |
||||
| 359 | |||||
| 360 | 2 | private function getDiff( |
|||
| 361 | string $relativePathToFileInProject, |
||||
| 362 | string $relativePathToFileInOverrides |
||||
| 363 | ): string { |
||||
| 364 | 2 | $diff = $this->differ->diff( |
|||
| 365 | 2 | \ts\file_get_contents($this->pathToProjectRoot . '/' . $relativePathToFileInOverrides), |
|||
| 366 | 2 | \ts\file_get_contents($this->pathToProjectRoot . '/' . $relativePathToFileInProject) |
|||
| 367 | ); |
||||
| 368 | |||||
| 369 | return <<<TEXT |
||||
| 370 | |||||
| 371 | ------------------------------------------------------------------------- |
||||
| 372 | |||||
| 373 | Diff between: |
||||
| 374 | |||||
| 375 | 2 | +++ Project: $relativePathToFileInProject |
|||
| 376 | 2 | --- Override: $relativePathToFileInOverrides |
|||
| 377 | |||||
| 378 | 2 | $diff |
|||
| 379 | |||||
| 380 | ------------------------------------------------------------------------- |
||||
| 381 | |||||
| 382 | TEXT; |
||||
| 383 | } |
||||
| 384 | |||||
| 385 | 1 | private function sortFilesByKey(array $files): array |
|||
| 386 | { |
||||
| 387 | 1 | ksort($files, SORT_STRING); |
|||
| 388 | |||||
| 389 | 1 | return $files; |
|||
| 390 | } |
||||
| 391 | |||||
| 392 | 3 | private function sortFiles(array $files): array |
|||
| 393 | { |
||||
| 394 | 3 | sort($files, SORT_STRING); |
|||
| 395 | |||||
| 396 | 3 | return $files; |
|||
| 397 | } |
||||
| 398 | |||||
| 399 | /** |
||||
| 400 | * Before applying overrides, we can check for errors and then return useful information |
||||
| 401 | * |
||||
| 402 | * @return array |
||||
| 403 | */ |
||||
| 404 | 1 | public function getInvalidOverrides(): array |
|||
| 405 | { |
||||
| 406 | 1 | $errors = []; |
|||
| 407 | 1 | foreach ($this->getOverridesIterator() as $pathToFileInOverrides) { |
|||
| 408 | 1 | if ($this->overrideFileHashIsCorrect($pathToFileInOverrides)) { |
|||
| 409 | 1 | continue; |
|||
| 410 | } |
||||
| 411 | if ($this->projectFileIsSameAsOverride($pathToFileInOverrides)) { |
||||
| 412 | continue; |
||||
| 413 | } |
||||
| 414 | $relativePathToFileInOverrides = $this->getRelativePathToFile($pathToFileInOverrides); |
||||
| 415 | $relativePathToFileInProject = |
||||
| 416 | $this->getRelativePathInProjectFromOverridePath($pathToFileInOverrides); |
||||
| 417 | |||||
| 418 | $errors[$relativePathToFileInOverrides]['overridePath'] = $relativePathToFileInOverrides; |
||||
| 419 | $errors[$relativePathToFileInOverrides]['projectPath'] = $relativePathToFileInProject; |
||||
| 420 | $errors[$relativePathToFileInOverrides]['diff'] = $this->getDiff( |
||||
| 421 | $relativePathToFileInProject, |
||||
| 422 | $relativePathToFileInOverrides |
||||
| 423 | ); |
||||
| 424 | $errors[$relativePathToFileInOverrides]['new md5'] = |
||||
| 425 | $this->getProjectFileHash($relativePathToFileInProject); |
||||
| 426 | } |
||||
| 427 | |||||
| 428 | 1 | return $errors; |
|||
| 429 | } |
||||
| 430 | |||||
| 431 | 3 | private function overrideFileHashIsCorrect(string $pathToFileInOverrides): bool |
|||
| 432 | { |
||||
| 433 | 3 | $filenameParts = explode('.', basename($pathToFileInOverrides)); |
|||
| 434 | 3 | if (4 !== count($filenameParts)) { |
|||
| 435 | throw new RuntimeException('Invalid override filename ' . $pathToFileInOverrides); |
||||
| 436 | } |
||||
| 437 | 3 | $hash = $filenameParts[1]; |
|||
| 438 | 3 | $relativePathToFileInProject = $this->getRelativePathInProjectFromOverridePath($pathToFileInOverrides); |
|||
| 439 | |||||
| 440 | 3 | return $hash === $this->getProjectFileHash($relativePathToFileInProject); |
|||
| 441 | } |
||||
| 442 | |||||
| 443 | /** |
||||
| 444 | * Loop over all the override files and copy into the project |
||||
| 445 | * |
||||
| 446 | * @return array[] the file paths that have been updated |
||||
| 447 | */ |
||||
| 448 | 3 | public function applyOverrides(): array |
|||
| 449 | { |
||||
| 450 | 3 | $filesUpdated = []; |
|||
| 451 | 3 | $filesSame = []; |
|||
| 452 | 3 | $errors = []; |
|||
| 453 | 3 | foreach ($this->getOverridesIterator() as $pathToFileInOverrides) { |
|||
| 454 | 3 | $relativePathToFileInProject = $this->getRelativePathInProjectFromOverridePath($pathToFileInOverrides); |
|||
| 455 | 3 | $relativePathToFileInOverrides = $this->getRelativePathToFile($pathToFileInOverrides); |
|||
| 456 | 3 | if ($this->overrideFileHashIsCorrect($pathToFileInOverrides)) { |
|||
| 457 | 2 | if (false === is_file($pathToFileInOverrides)) { |
|||
| 458 | throw new RuntimeException('path ' . $pathToFileInOverrides . ' is not a file'); |
||||
| 459 | } |
||||
| 460 | 2 | copy($pathToFileInOverrides, $this->pathToProjectRoot . $relativePathToFileInProject); |
|||
| 461 | 2 | $filesUpdated[] = $relativePathToFileInProject; |
|||
| 462 | 2 | continue; |
|||
| 463 | } |
||||
| 464 | 1 | if ($this->projectFileIsSameAsOverride($pathToFileInOverrides)) { |
|||
| 465 | $filesSame[] = $relativePathToFileInProject; |
||||
| 466 | continue; |
||||
| 467 | } |
||||
| 468 | 1 | $errors[$pathToFileInOverrides]['diff'] = $this->getDiff( |
|||
| 469 | 1 | $relativePathToFileInProject, |
|||
| 470 | 1 | $relativePathToFileInOverrides |
|||
| 471 | ); |
||||
| 472 | 1 | $errors[$pathToFileInOverrides]['new md5'] = $this->getProjectFileHash($relativePathToFileInProject); |
|||
| 473 | } |
||||
| 474 | 3 | if ([] !== $errors) { |
|||
| 475 | 1 | throw new RuntimeException('These file hashes were not up to date:' . print_r($errors, true)); |
|||
| 476 | } |
||||
| 477 | |||||
| 478 | 2 | return [$this->sortFiles($filesUpdated), $this->sortFiles($filesSame)]; |
|||
| 479 | } |
||||
| 480 | } |
||||
| 481 |