diff --git a/psalm.baseline.xml b/psalm.baseline.xml index b23f625..908b551 100644 --- a/psalm.baseline.xml +++ b/psalm.baseline.xml @@ -407,6 +407,19 @@ PaginatorExtension + + + + + + + + + + + ThumbnailExtension + + column @@ -648,6 +661,11 @@ array + + + __construct + + EventSubscriber diff --git a/src/Bridge/Twig/Extension/ThumbnailExtension.php b/src/Bridge/Twig/Extension/ThumbnailExtension.php index a04a88b..39e05b0 100644 --- a/src/Bridge/Twig/Extension/ThumbnailExtension.php +++ b/src/Bridge/Twig/Extension/ThumbnailExtension.php @@ -13,24 +13,34 @@ namespace Sigwin\YASSG\Bridge\Twig\Extension; +use Sigwin\YASSG\ThumbnailQueue; +use Symfony\Component\Asset\Packages; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; final class ThumbnailExtension extends AbstractExtension { + public function __construct(private readonly Packages $packages, private readonly ThumbnailQueue $thumbnailQueue) {} + public function getFunctions(): array { return [ - new TwigFunction('yassg_thumbnail', static function (array $context, string $path): string { + new TwigFunction('yassg_thumbnail', function (array $context, string $path): string { if (str_starts_with($path, './')) { $newPath = realpath(\dirname($context['_path']).'/'.$path); if ($newPath === false) { - throw new \RuntimeException(sprintf('Invalid thumbnail path '.$path)); + throw new \RuntimeException('Invalid thumbnail path '.$path); } $path = $newPath; } - return str_replace($GLOBALS['YASSG_BASEDIR'], '', $path); + $relative = str_replace($GLOBALS['YASSG_BASEDIR'], '', $path); + $this->thumbnailQueue->add([ + 'source' => $path, + 'destination' => $relative, + ]); + + return $this->packages->getUrl(ltrim($relative, '/')); }, ['needs_context' => true]), ]; } diff --git a/src/Generator.php b/src/Generator.php index 3542aba..65a1f0e 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -28,8 +28,13 @@ */ final readonly class Generator { - public function __construct(private string $buildDir, private Permutator $permutator, private UrlGeneratorInterface $urlGenerator, private KernelInterface $kernel, private Filesystem $filesystem) {} + public function __construct(private string $buildDir, private Permutator $permutator, private UrlGeneratorInterface $urlGenerator, private KernelInterface $kernel, private Filesystem $filesystem, private ThumbnailQueue $thumbnailQueue) {} + /** + * @param callable(Request, Response, string): void $callable + * + * @throws \Exception + */ public function generate(callable $callable): void { $requestContext = $this->urlGenerator->getContext(); @@ -71,6 +76,10 @@ public function generate(callable $callable): void $response = $this->dumpRequest($callable, $request); $urlSet->addUrl(new UrlConcrete($url, new \DateTimeImmutable($response->headers->get('Last-Modified', 'now')))); + + $this->thumbnailQueue->flush(function (array $item) use ($callable): void { + $callable($this->createRequest($item['destination']), new Response('OK'), $item['destination']); + }); } if ($urlSet !== null) { $this->dumpSitemap($urlSet, $deflate); @@ -105,6 +114,11 @@ private function generateUrl(string $path): string return sprintf('%1$s://%2$s%3$s%4$s', $context->getScheme(), $context->getHost(), $context->getBaseUrl(), $path); } + /** + * @param callable(Request, Response, string): void $callable + * + * @throws \Exception + */ private function dumpRequest(callable $callable, Request $request, int $expectedStatusCode = 200): Response { try { diff --git a/src/ThumbnailQueue.php b/src/ThumbnailQueue.php new file mode 100644 index 0000000..c8b487e --- /dev/null +++ b/src/ThumbnailQueue.php @@ -0,0 +1,54 @@ + + */ + private array $queue = []; + + public function __construct(private string $buildDir, private Filesystem $filesystem) {} + + /** + * @param TThumbnailOptions $specification + */ + public function add(array $specification): void + { + $this->queue[$specification['destination']] = $specification; + } + + /** + * @param callable(TThumbnailOptions): void $callable + */ + public function flush(callable $callable): void + { + foreach ($this->queue as $specification) { + $destination = $this->buildDir.'/'.ltrim($specification['destination'], '/'); + if (file_exists($destination)) { + continue; + } + + // TODO: ImgProxy + $this->filesystem->copy($specification['source'], $destination); + $callable($specification); + } + } +} diff --git a/tests/functional/site/fixtures/en/article/images/index.html b/tests/functional/site/fixtures/en/article/images/index.html index df7e3d6..83b5492 100644 --- a/tests/functional/site/fixtures/en/article/images/index.html +++ b/tests/functional/site/fixtures/en/article/images/index.html @@ -43,8 +43,8 @@

Images!

This is a database lookup example: Hello World!

-

This is an asset lookup: /sub/dir/another/assets/images/sigwin.6f9a3d5b.svg

-

Logo

+

This is an asset lookup: /sub/dir/another/content/articles/images/image.webp

+

Logo