Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate WebP in liip:imagine:cache:resolve CLI command and async resolve cache messages #1347

Merged
merged 9 commits into from
Oct 16, 2021
5 changes: 2 additions & 3 deletions Async/ResolveCacheProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,9 @@ public function process(Message $psrMessage, Context $psrContext)
$filters = $message->getFilters() ?: array_keys($this->filterManager->getFilterConfiguration()->all());
$path = $message->getPath();
$results = [];

foreach ($filters as $filter) {
if ($message->isForce()) {
$this->filterService->bustCache($path, $filter);
}
$this->filterService->warmUpCache($path, $filter, null, $message->isForce());

$results[$filter] = $this->filterService->getUrlOfFilteredImage($path, $filter);
}
Expand Down
19 changes: 13 additions & 6 deletions Command/RemoveCacheCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Liip\ImagineBundle\Service\FilterService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -22,14 +23,21 @@
class RemoveCacheCommand extends Command
{
use CacheCommandTrait;

protected static $defaultName = 'liip:imagine:cache:remove';

public function __construct(CacheManager $cacheManager, FilterManager $filterManager)
/**
* @var FilterService
*/
private $filterService;

public function __construct(CacheManager $cacheManager, FilterManager $filterManager, FilterService $filterService)
{
parent::__construct();

$this->cacheManager = $cacheManager;
$this->filterManager = $filterManager;
$this->filterService = $filterService;
}

protected function configure(): void
Expand Down Expand Up @@ -79,9 +87,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if (empty($images)) {
$this->cacheManager->remove(null, $filters);
} else {
foreach ($images as $i) {
foreach ($filters as $f) {
$this->runCacheImageRemove($i, $f);
foreach ($images as $image) {
foreach ($filters as $filter) {
$this->runCacheImageRemove($image, $filter);
}
}
}
Expand All @@ -99,8 +107,7 @@ private function runCacheImageRemove(string $image, string $filter): void

$this->io->group($image, $filter, 'blue');

if ($this->cacheManager->isStored($image, $filter)) {
$this->cacheManager->remove($image, $filter);
if ($this->filterService->bustCache($image, $filter)) {
$this->io->status('removed', 'green');
} else {
$this->io->status('skipped', 'yellow');
Expand Down
20 changes: 10 additions & 10 deletions Command/ResolveCacheCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
namespace Liip\ImagineBundle\Command;

use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Liip\ImagineBundle\Service\FilterService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -23,20 +23,21 @@
class ResolveCacheCommand extends Command
{
use CacheCommandTrait;

protected static $defaultName = 'liip:imagine:cache:resolve';

/**
* @var DataManager
* @var FilterService
*/
private $dataManager;
private $filterService;

public function __construct(DataManager $dataManager, CacheManager $cacheManager, FilterManager $filterManager)
public function __construct(CacheManager $cacheManager, FilterManager $filterManager, FilterService $filterService)
{
parent::__construct();

$this->dataManager = $dataManager;
$this->cacheManager = $cacheManager;
$this->filterManager = $filterManager;
$this->filterService = $filterService;
}

protected function configure(): void
Expand Down Expand Up @@ -90,9 +91,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$forced = $input->getOption('force');
[$images, $filters] = $this->resolveInputFiltersAndPaths($input);

foreach ($images as $i) {
foreach ($filters as $f) {
$this->runCacheImageResolve($i, $f, $forced);
foreach ($images as $image) {
foreach ($filters as $filter) {
$this->runCacheImageResolve($image, $filter, $forced);
}
}

Expand All @@ -110,8 +111,7 @@ private function runCacheImageResolve(string $image, string $filter, bool $force
$this->io->group($image, $filter, 'blue');

try {
if ($forced || !$this->cacheManager->isStored($image, $filter)) {
$this->cacheManager->store($this->filterManager->applyFilter($this->dataManager->find($filter, $image), $filter), $image, $filter);
if ($this->filterService->warmUpCache($image, $filter, null, $forced)) {
$this->io->status('resolved', 'green');
} else {
$this->io->status('cached', 'white');
Expand Down
4 changes: 1 addition & 3 deletions Message/Handler/WarmupCacheHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ public function __invoke(WarmupCache $message): void
$path = $message->getPath();

foreach ($filters as $filter) {
if ($message->isForce()) {
$this->filterService->bustCache($path, $filter);
}
$this->filterService->warmUpCache($path, $filter, null, $message->isForce());

$this->filterService->getUrlOfFilteredImage($path, $filter);
}
Expand Down
3 changes: 2 additions & 1 deletion Resources/config/commands.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
<service id="liip_imagine.command.cache_remove" class="Liip\ImagineBundle\Command\RemoveCacheCommand">
<argument type="service" id="liip_imagine.cache.manager" />
<argument type="service" id="liip_imagine.filter.manager" />
<argument type="service" id="liip_imagine.service.filter" />
<tag name="console.command" command="liip:imagine:cache:remove" alias="imagine:del" />
</service>

<service id="liip_imagine.command.cache_resolve" class="Liip\ImagineBundle\Command\ResolveCacheCommand">
<argument type="service" id="liip_imagine.data.manager" />
<argument type="service" id="liip_imagine.cache.manager" />
<argument type="service" id="liip_imagine.filter.manager" />
<argument type="service" id="liip_imagine.service.filter" />
<tag name="console.command" command="liip:imagine:cache:resolve" alias="imagine:get" />
</service>

Expand Down
124 changes: 92 additions & 32 deletions Service/FilterService.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class FilterService
private $webpGenerate;

/**
* @var array
* @var mixed[]
*/
private $webpOptions;

Expand All @@ -70,21 +70,44 @@ public function __construct(
/**
* @param string $path
* @param string $filter
*
* @return bool Returns true if we removed at least one cached image
*/
public function bustCache($path, $filter)
{
$basePathContainer = new FilterPathContainer($path);
$filterPathContainers = [$basePathContainer];

if ($this->webpGenerate) {
$filterPathContainers[] = $basePathContainer->createWebp($this->webpOptions);
}
$busted = false;

foreach ($filterPathContainers as $filterPathContainer) {
foreach ($this->buildFilterPathContainers($path) as $filterPathContainer) {
if ($this->cacheManager->isStored($filterPathContainer->getTarget(), $filter)) {
$this->cacheManager->remove($filterPathContainer->getTarget(), $filter);

$busted = true;
}
}

return $busted;
}

/**
* @param bool $forced Force warm up cache
*
* @return bool Returns true if the cache is warmed up
*/
public function warmUpCache(
string $path,
string $filter,
?string $resolver = null,
bool $forced = false
): bool {
$warmedUp = false;

foreach ($this->buildFilterPathContainers($path) as $filterPathContainer) {
if ($this->warmUpCacheFilterPathContainer($filterPathContainer, $filter, $resolver, $forced)) {
$warmedUp = true;
}
}

return $warmedUp;
}

/**
Expand All @@ -96,9 +119,11 @@ public function bustCache($path, $filter)
*/
public function getUrlOfFilteredImage($path, $filter, $resolver = null, bool $webpSupported = false)
{
$basePathContainer = new FilterPathContainer($path);
foreach ($this->buildFilterPathContainers($path) as $filterPathContainer) {
$this->warmUpCacheFilterPathContainer($filterPathContainer, $filter, $resolver);
}

return $this->getUrlOfFilteredImageByContainer($basePathContainer, $filter, $resolver, $webpSupported);
return $this->resolveFilterPathContainer(new FilterPathContainer($path), $filter, $resolver, $webpSupported);
}

/**
Expand All @@ -116,42 +141,77 @@ public function getUrlOfFilteredImageWithRuntimeFilters(
bool $webpSupported = false
) {
$runtimePath = $this->cacheManager->getRuntimePath($path, $runtimeFilters);
$basePathContainer = new FilterPathContainer($path, $runtimePath, [
$runtimeOptions = [
'filters' => $runtimeFilters,
]);
];

foreach ($this->buildFilterPathContainers($path, $runtimePath, $runtimeOptions) as $filterPathContainer) {
$this->warmUpCacheFilterPathContainer($filterPathContainer, $filter, $resolver);
}

return $this->resolveFilterPathContainer(
new FilterPathContainer($path, $runtimePath, $runtimeOptions),
$filter,
$resolver,
$webpSupported
);
}

/**
* @param mixed[] $options
*
* @return FilterPathContainer[]
*/
private function buildFilterPathContainers(string $source, string $target = '', array $options = []): array
{
$basePathContainer = new FilterPathContainer($source, $target, $options);
$filterPathContainers = [$basePathContainer];

if ($this->webpGenerate) {
$filterPathContainers[] = $basePathContainer->createWebp($this->webpOptions);
}

return $this->getUrlOfFilteredImageByContainer($basePathContainer, $filter, $resolver, $webpSupported);
return $filterPathContainers;
}

private function getUrlOfFilteredImageByContainer(
FilterPathContainer $basePathContainer,
private function resolveFilterPathContainer(
FilterPathContainer $filterPathContainer,
string $filter,
?string $resolver = null,
bool $webpSupported = false
): string {
$filterPathContainers = [$basePathContainer];
$path = $filterPathContainer->getTarget();

if ($this->webpGenerate) {
$webpPathContainer = $basePathContainer->createWebp($this->webpOptions);
$filterPathContainers[] = $webpPathContainer;
if ($webpSupported) {
$path = $filterPathContainer->createWebp($this->webpOptions)->getTarget();
}

foreach ($filterPathContainers as $filterPathContainer) {
if (!$this->cacheManager->isStored($filterPathContainer->getTarget(), $filter, $resolver)) {
$this->cacheManager->store(
$this->createFilteredBinary($filterPathContainer, $filter),
$filterPathContainer->getTarget(),
$filter,
$resolver
);
}
}
return $this->cacheManager->resolve($path, $filter, $resolver);
}

/**
* @param bool $forced Force warm up cache
*
* @return bool Returns true if the cache is warmed up
*/
private function warmUpCacheFilterPathContainer(
FilterPathContainer $filterPathContainer,
string $filter,
?string $resolver = null,
bool $forced = false
): bool {
if ($forced || !$this->cacheManager->isStored($filterPathContainer->getTarget(), $filter, $resolver)) {
$this->cacheManager->store(
$this->createFilteredBinary($filterPathContainer, $filter),
$filterPathContainer->getTarget(),
$filter,
$resolver
);

if ($webpSupported && isset($webpPathContainer)) {
return $this->cacheManager->resolve($webpPathContainer->getTarget(), $filter, $resolver);
return true;
}

return $this->cacheManager->resolve($basePathContainer->getTarget(), $filter, $resolver);
return false;
}

/**
Expand Down
7 changes: 4 additions & 3 deletions Tests/Async/ResolveCacheProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ public function testShouldCreateOneImagePerRequestedFilter(): void

public function testShouldBurstCacheWhenResolvingForced(): void
{
$force = true;
$filterName = 'fooFilter';
$imagePath = 'theImagePath';

Expand All @@ -308,8 +309,8 @@ public function testShouldBurstCacheWhenResolvingForced(): void
$filterServiceMock = $this->createFilterServiceMock();
$filterServiceMock
->expects($this->once())
->method('bustCache')
->with($imagePath, $filterName);
->method('warmUpCache')
->with($imagePath, $filterName, null, $force);

$processor = new ResolveCacheProcessor(
$filterManagerMock,
Expand All @@ -318,7 +319,7 @@ public function testShouldBurstCacheWhenResolvingForced(): void
);

$message = new NullMessage();
$message->setBody(json_encode(['path' => $imagePath, 'force' => true]));
$message->setBody(json_encode(['path' => $imagePath, 'force' => $force]));

$result = $processor->process($message, new NullContext());

Expand Down
Loading