From 370e6ce66588d5078298575100b5737d4b146b7d Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 17 Dec 2023 11:54:11 +0100 Subject: [PATCH] Initial commit --- .gitignore | 2 +- src/Command/GenerateManifestCommand.php | 165 +++++++++++++++--------- 2 files changed, 102 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index c84ab0c..18e5996 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /vendor/ /composer.lock -/.phpunit.result.cache +/.phpunit.cache diff --git a/src/Command/GenerateManifestCommand.php b/src/Command/GenerateManifestCommand.php index 9148c02..9475e34 100644 --- a/src/Command/GenerateManifestCommand.php +++ b/src/Command/GenerateManifestCommand.php @@ -9,6 +9,7 @@ use SpomkyLabs\PwaBundle\ImageProcessor\ImageProcessor; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -18,6 +19,8 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; use Symfony\Component\Mime\MimeTypes; +use function count; +use function is_int; use const JSON_PRETTY_PRINT; use const JSON_THROW_ON_ERROR; use const JSON_UNESCAPED_SLASHES; @@ -62,7 +65,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int $assetFolder = '/' . trim((string) $input->getArgument('asset_folder'), '/'); $outputFile = '/' . trim((string) $input->getArgument('output'), '/'); - $this->filesystem->mkdir($publicFolder); + if (! $this->filesystem->exists($publicFolder)) { + $this->filesystem->mkdir($publicFolder); + } $manifest = $this->processIcons($io, $manifest, $publicUrl, $publicFolder, $assetFolder); if ($manifest === self::FAILURE) { @@ -86,7 +91,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int ) ); } catch (JsonException $exception) { - echo 'An error occurred while creating your directory at ' . $exception->getPath(); + $io->error('An error occurred while creating your directory at ' . $exception->getPath()); + return self::FAILURE; } return self::SUCCESS; @@ -161,6 +167,22 @@ private function storeScreenshot( ]; } + private function handleSizeAndPurpose(?string $purpose, int $size, array $fileData): array + { + $sizes = $size === 0 ? 'any' : $size . 'x' . $size; + $fileData += [ + 'sizes' => $sizes, + ]; + + if ($purpose !== null) { + $fileData += [ + 'purpose' => $purpose, + ]; + } + + return $fileData; + } + /** * @return array{src: string, sizes: string, type: string, purpose: ?string} */ @@ -169,7 +191,7 @@ private function storeShortcutIcon( string $publicUrl, string $publicFolder, string $assetFolder, - string $sizes, + int $size, ?string $purpose ): array { $fileData = $this->storeFile( @@ -178,17 +200,10 @@ private function storeShortcutIcon( $publicFolder, $assetFolder, 'shortcut-icon', - ['shortcut-icon', $purpose, $sizes] + ['shortcut-icon', $purpose, $size === 0 ? 'any' : $size . 'x' . $size] ); - return ($purpose !== null) - ? $fileData + [ - 'sizes' => $sizes, - 'purpose' => $purpose, - ] - : $fileData + [ - 'sizes' => $sizes, - ]; + return $this->handleSizeAndPurpose($purpose, $size, $fileData); } /** @@ -199,19 +214,19 @@ private function storeIcon( string $publicUrl, string $publicFolder, string $assetFolder, - string $sizes, + int $size, ?string $purpose ): array { - $fileData = $this->storeFile($data, $publicUrl, $publicFolder, $assetFolder, 'icon', ['icon', $purpose, $sizes]); + $fileData = $this->storeFile( + $data, + $publicUrl, + $publicFolder, + $assetFolder, + 'icon', + ['icon', $purpose, $size === 0 ? 'any' : $size . 'x' . $size] + ); - return ($purpose !== null) - ? $fileData + [ - 'sizes' => $sizes, - 'purpose' => $purpose, - ] - : $fileData + [ - 'sizes' => $sizes, - ]; + return $this->handleSizeAndPurpose($purpose, $size, $fileData); } private function processIcons( @@ -224,45 +239,40 @@ private function processIcons( if ($this->config['icons'] === []) { return $manifest; } - - try { - $this->filesystem->mkdir(sprintf('%s%s', $publicFolder, $assetFolder)); - } catch (IOExceptionInterface $exception) { - echo 'An error occurred while creating your directory at ' . $exception->getPath(); + if (! $this->createDirectoryIfNotExists($publicFolder, $assetFolder) || ! $this->checkImageProcessor($io)) { + return self::FAILURE; } $manifest['icons'] = []; + $progressBar = $io->createProgressBar(count($this->config['icons'])); + $progressBar->start(); $io->info('Processing icons'); - if ($this->imageProcessor === null) { - $io->error('Image processor not found'); - return self::FAILURE; - } + $progressBar->start(); foreach ($this->config['icons'] as $icon) { + $this->processProgressBar($progressBar, 'icon', $icon['src']); foreach ($icon['sizes'] as $size) { - if (!is_int($size) || $size < 0) { + if (! is_int($size) || $size < 0) { $io->error('The icon size must be a positive integer'); return self::FAILURE; } - $data = file_get_contents($icon['src']); - if ($data === false) { + $data = $this->loadFile($icon['src'], $size, $icon['format'] ?? null); + if ($data === null) { $io->error(sprintf('Unable to read the icon "%s"', $icon['src'])); return self::FAILURE; } - if ($size !== 0) { - $data = $this->imageProcessor->process($data, $size, $size, $icon['format'] ?? null); - } - $sizes = $size === 0 ? 'any' : $size . 'x' . $size; $iconManifest = $this->storeIcon( $data, $publicUrl, $publicFolder, $assetFolder, - $sizes, + $size, $icon['purpose'] ?? null ); $manifest['icons'][] = $iconManifest; } } + $progressBar->finish(); + $io->info('Icons are built'); return $manifest; } @@ -277,21 +287,18 @@ private function processScreenshots( if ($this->config['screenshots'] === []) { return $manifest; } - try { - $this->filesystem->mkdir(sprintf('%s%s', $publicFolder, $assetFolder)); - } catch (IOExceptionInterface $exception) { - echo 'An error occurred while creating your directory at ' . $exception->getPath(); + if (! $this->createDirectoryIfNotExists($publicFolder, $assetFolder) || ! $this->checkImageProcessor($io)) { + return self::FAILURE; } $manifest['screenshots'] = []; + $progressBar = $io->createProgressBar(count($this->config['screenshots'])); + $progressBar->start(); $io->info('Processing screenshots'); - if ($this->imageProcessor === null) { - $io->error('Image processor not found'); - return self::FAILURE; - } foreach ($this->config['screenshots'] as $screenshot) { - $data = file_get_contents($screenshot['src']); - if ($data === false) { - $io->error(sprintf('Unable to read the screenshot "%s"', $screenshot['src'])); + $this->processProgressBar($progressBar, 'screenshot', $screenshot['src']); + $data = $this->loadFile($screenshot['src'], null, $screenshot['format'] ?? null); + if ($data === null) { + $io->error(sprintf('Unable to read the icon "%s"', $screenshot['src'])); return self::FAILURE; } $screenshotManifest = $this->storeScreenshot( @@ -310,6 +317,7 @@ private function processScreenshots( } $manifest['screenshots'][] = $screenshotManifest; } + $progressBar->finish(); return $manifest; } @@ -324,14 +332,15 @@ private function processShortcutIcons( if ($this->config['shortcuts'] === []) { return $manifest; } - try { - $this->filesystem->mkdir(sprintf('%s%s', $publicFolder, $assetFolder)); - } catch (IOExceptionInterface $exception) { - echo 'An error occurred while creating your directory at ' . $exception->getPath(); + if (! $this->createDirectoryIfNotExists($publicFolder, $assetFolder) || ! $this->checkImageProcessor($io)) { + return self::FAILURE; } $manifest['shortcuts'] = []; - $io->info('Processing schortcuts'); + $progressBar = $io->createProgressBar(count($this->config['shortcuts'])); + $io->info('Processing shortcuts'); + $progressBar->start(); foreach ($this->config['shortcuts'] as $shortcutConfig) { + $this->processProgressBar($progressBar, 'shortcuts', $shortcutConfig['name']); $shortcut = $shortcutConfig; if (isset($shortcut['icons'])) { unset($shortcut['icons']); @@ -342,27 +351,23 @@ private function processShortcutIcons( } foreach ($shortcutConfig['icons'] as $icon) { foreach ($icon['sizes'] as $size) { - if (!is_int($size) || $size < 0) { + if (! is_int($size) || $size < 0) { $io->error('The icon size must be a positive integer'); return self::FAILURE; } - $data = file_get_contents($icon['src']); - if ($data === false) { - $io->error(sprintf('Unable to read the screenshot "%s"', $icon['src'])); + $data = $this->loadFile($icon['src'], $size, $icon['format'] ?? null); + if ($data === null) { + $io->error(sprintf('Unable to read the icon "%s"', $icon['src'])); return self::FAILURE; } - if ($size !== 0) { - $data = $this->imageProcessor->process($data, $size, $size, $icon['format'] ?? null); - } - $sizes = $size === 0 ? 'any' : $size . 'x' . $size; $iconManifest = $this->storeShortcutIcon( $data, $publicUrl, $publicFolder, $assetFolder, - $sizes, + $size, $icon['purpose'] ?? null ); $shortcut['icons'][] = $iconManifest; @@ -371,11 +376,25 @@ private function processShortcutIcons( } $manifest['shortcuts'][] = $shortcut; } + $progressBar->finish(); $manifest['shortcuts'] = array_values($manifest['shortcuts']); return $manifest; } + private function loadFile(string $src, ?int $size, ?string $format): ?string + { + $data = file_get_contents($src); + if ($data === false) { + return null; + } + if ($size !== 0 && $size !== null) { + $data = $this->imageProcessor->process($data, $size, $size, $format); + } + + return $data; + } + private function checkImageProcessor(SymfonyStyle $io): bool { if ($this->imageProcessor === null) { @@ -385,4 +404,22 @@ private function checkImageProcessor(SymfonyStyle $io): bool return true; } + + private function createDirectoryIfNotExists(string $publicFolder, string $assetFolder): bool + { + try { + $this->filesystem->mkdir(sprintf('%s%s', $publicFolder, $assetFolder)); + } catch (IOExceptionInterface $exception) { + echo 'An error occurred while creating your directory at ' . $exception->getPath(); + return false; + } + + return true; + } + + private function processProgressBar(ProgressBar $progressBar, string $type, string $src): void + { + $progressBar->advance(); + $progressBar->setMessage(sprintf('Processing %s %s', $type, $src)); + } }