diff --git a/src/Console/Command/Extract.php b/src/Console/Command/Extract.php index 115c82839..399181969 100644 --- a/src/Console/Command/Extract.php +++ b/src/Console/Command/Extract.php @@ -59,64 +59,108 @@ protected function configure(): void protected function executeCommand(IO $io): int { - $input = $io->getInput(); + $filePath = self::getPharFilePath($io); + $outputDir = $io->getInput()->getArgument(self::OUTPUT_ARG); - $file = realpath($input->getArgument(self::PHAR_ARG)); + if (null === $filePath) { + return 1; + } - if (false === $file) { - $io->error( - sprintf( - 'The file "%s" could not be found.', - $input->getArgument(self::PHAR_ARG), - ), - ); + [$box, $cleanUpTmpPhar] = $this->getBox($filePath, $io); + if (null === $box) { return 1; } - $tmpFile = create_temporary_phar($file); + $restoreLimit = bump_open_file_descriptor_limit(count($box), $io); + + $cleanUp = static function () use ($cleanUpTmpPhar, $restoreLimit): void { + $cleanUpTmpPhar(); + $restoreLimit(); + }; try { - $box = Box::create($tmpFile); + self::dumpPhar($outputDir, $box, $cleanUp); + } catch (RuntimeException $exception) { + $io->error($exception->getMessage()); + + return 1; + } + + return 0; + } + + private static function getPharFilePath(IO $io): ?string + { + $filePathArg = $io->getInput()->getArgument(self::PHAR_ARG); + $filePath = realpath((string) $filePathArg); + + if (false !== $filePath) { + return $filePath; + } + + $io->error( + sprintf( + 'The file "%s" could not be found.', + $filePathArg, + ), + ); + + return null; + } + + /** + * @return array{Box, callable(): void}|array{null, null} + */ + private function getBox(string $filePath, IO $io): ?array + { + $tmpFile = create_temporary_phar($filePath); + $cleanUp = static fn () => remove($tmpFile); + + try { + return [ + Box::create($tmpFile), + $cleanUp, + ]; } catch (Throwable $throwable) { - if ($io->isDebug()) { - throw new ConsoleRuntimeException( - 'The given file is not a valid PHAR', - 0, - $throwable, - ); - } + // Continue + } - $io->error('The given file is not a valid PHAR'); + if ($io->isDebug()) { + $cleanUp(); - return 1; + throw new ConsoleRuntimeException( + 'The given file is not a valid PHAR', + 0, + $throwable, + ); } - $restoreLimit = bump_open_file_descriptor_limit(count($box), $io); + $io->error('The given file is not a valid PHAR'); - $outputDir = $input->getArgument(self::OUTPUT_ARG); + $cleanUp(); + return [null, null]; + } + + /** + * @param callable(): void $cleanUp + */ + private static function dumpPhar(string $outputDir, Box $box, callable $cleanUp): void + { try { remove($outputDir); $rootLength = strlen('phar://'.$box->getPhar()->getPath()) + 1; - foreach (new RecursiveIteratorIterator($box->getPhar()) as $file) { + foreach (new RecursiveIteratorIterator($box->getPhar()) as $filePath) { dump_file( - $outputDir.'/'.substr($file->getPathname(), $rootLength), - (string) $file->getContent(), + $outputDir.'/'.substr($filePath->getPathname(), $rootLength), + (string) $filePath->getContent(), ); } - } catch (RuntimeException $exception) { - $io->error($exception->getMessage()); - - return 1; } finally { - $restoreLimit(); - - remove($tmpFile); + $cleanUp(); } - - return 0; } }