Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e75dca3
Deprecate `webp` configuration in favor of `alternative_formats` and …
tito10047 Feb 19, 2026
d1451d6
Add `FormatNegotiator` service for handling Accept header format nego…
tito10047 Feb 19, 2026
6f012fa
Deprecate `createWebp` method in favor of more flexible `createAltern…
tito10047 Feb 19, 2026
ba61f54
Replace WebP configuration with `alternative_formats`, add `FormatNeg…
tito10047 Feb 19, 2026
d493ff6
Deprecate WebP-specific handling in favor of `alternative_formats`, u…
tito10047 Feb 19, 2026
7f8ffb4
Refactor `ImagineController` to support `FormatNegotiator` and `alter…
tito10047 Feb 19, 2026
d32251c
fix dependencie DependecieInjection tests
tito10047 Feb 19, 2026
0c62ca5
fixed some tests
tito10047 Feb 19, 2026
d49844a
fixed some tests
tito10047 Feb 19, 2026
bd0a357
All test are passed :)
tito10047 Feb 19, 2026
dae2888
cs fixer
tito10047 Feb 19, 2026
56072b4
revert phpunit.xml.dist
tito10047 Feb 19, 2026
75cc4a9
try fix tests
tito10047 Feb 19, 2026
4fad8f7
try fix tests
tito10047 Feb 19, 2026
f7fd821
fix bc break
tito10047 Feb 19, 2026
5e3e46e
fix bc break
tito10047 Feb 19, 2026
5909f3a
add AVIF support for post-processing and caching
tito10047 Feb 19, 2026
07e5821
add backguard compatibility
tito10047 Feb 19, 2026
d7be781
because avifenc binary cant convert from avif to avif. and because im…
tito10047 Feb 19, 2026
45c1b4a
remove option -o that is not supported on ubuntu
tito10047 Feb 19, 2026
0e2f735
replace options for supported on ubuntu
tito10047 Feb 19, 2026
5f62a74
correct way to handle use_default_driver
tito10047 Feb 20, 2026
eeb6255
fixes PR suggestions
tito10047 Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:

- name: Run PHPUnit tests
env:
SYMFONY_DEPRECATIONS_HELPER: max[self]=0
SYMFONY_DEPRECATIONS_HELPER: disabled=1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't change this setting.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was not addressed

run: vendor/bin/simple-phpunit -v

- name: Install php-coveralls
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@
/Tests/Functional/app/web/media/cache
/var/
/vendor/
/.idea/
/.junie/guidelines.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do not add local dev environment specific things to the gitignore. use your global gitignore on your workstation for those.

39 changes: 36 additions & 3 deletions Controller/ImagineController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Liip\ImagineBundle\Imagine\Cache\SignerInterface;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Service\FilterService;
use Liip\ImagineBundle\Service\FormatNegotiator;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -47,11 +48,23 @@ class ImagineController
*/
private $controllerConfig;

/**
* @var FormatNegotiator
*/
private $formatNegotiator;

/**
* @var array
*/
private $alternativeFormats;

public function __construct(
FilterService $filterService,
DataManager $dataManager,
SignerInterface $signer,
?ControllerConfig $controllerConfig = null
?ControllerConfig $controllerConfig = null,
?FormatNegotiator $formatNegotiator = null,
array $alternativeFormats = []
) {
$this->filterService = $filterService;
$this->dataManager = $dataManager;
Expand All @@ -64,6 +77,8 @@ public function __construct(
}

$this->controllerConfig = $controllerConfig ?? new ControllerConfig(301);
$this->formatNegotiator = $formatNegotiator;
$this->alternativeFormats = $alternativeFormats;
}

/**
Expand Down Expand Up @@ -92,7 +107,8 @@ public function filterAction(Request $request, $path, $filter)
$path,
$filter,
$resolver,
$this->isWebpSupported($request)
false,
$this->getAlternativeFormats($request)
);
}, $path, $filter);
}
Expand Down Expand Up @@ -130,7 +146,8 @@ public function filterRuntimeAction(Request $request, $hash, $path, $filter)
$filter,
$runtimeConfig,
$resolver,
$this->isWebpSupported($request)
false,
$this->getAlternativeFormats($request)
);
}, $path, $filter, $hash);
}
Expand Down Expand Up @@ -163,8 +180,24 @@ private function createRedirectResponse(\Closure $url, string $path, string $fil
}
}

private function getAlternativeFormats(Request $request): array
{
if (null === $this->formatNegotiator) {
return $this->isWebpSupported($request) ? ['webp'] : [];
}

return $this->formatNegotiator->negotiate($request, $this->alternativeFormats);
}

/**
* @deprecated since 2.12, use FormatNegotiator instead.
*/
private function isWebpSupported(Request $request): bool
{
if (null !== $this->formatNegotiator) {
return $this->formatNegotiator->isFormatAccepted('webp', $request);
}

return false !== mb_stripos($request->headers->get('accept', ''), 'image/webp');
}
}
56 changes: 53 additions & 3 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,35 @@ public function getConfigTreeBuilder(): TreeBuilder
$treeBuilder = new TreeBuilder('liip_imagine');
$rootNode = $treeBuilder->getRootNode();

$rootNode
->beforeNormalization()
->always(function ($v) {
if (\is_array($v) && \array_key_exists('webp', $v)) {
if (!\array_key_exists('alternative_formats', $v)) {
$v['alternative_formats'] = [];
}
if (!\array_key_exists('webp', $v['alternative_formats'])) {
$v['alternative_formats']['webp'] = $v['webp'];
}
unset($v['webp']);
}

if (\is_array($v) && \array_key_exists('alternative_formats', $v)) {
$defaults = [
'webp' => ['image/webp'],
'avif' => ['image/avif'],
];
foreach ($v['alternative_formats'] as $format => &$config) {
if (isset($defaults[$format]) && (empty($config['mime_types']) || !\is_array($config['mime_types']))) {
$config['mime_types'] = $defaults[$format];
}
}
}

return $v;
})
->end();

$resolversPrototypeNode = $rootNode
->children()
->arrayNode('resolvers')
Expand Down Expand Up @@ -195,8 +224,29 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->end()
->end()
->arrayNode('twig')
->end()
->arrayNode('alternative_formats')
->useAttributeAsKey('format')
->prototype('array')
->children()
->booleanNode('generate')->defaultFalse()->end()
->integerNode('quality')->defaultValue(100)->end()
->scalarNode('cache')->defaultNull()->end()
->scalarNode('data_loader')->defaultNull()->end()
->arrayNode('post_processors')
->defaultValue([])
->useAttributeAsKey('name')
->prototype('variable')->end()
->end()
->arrayNode('mime_types')
->prototype('scalar')->end()
->end()
->integerNode('priority')->defaultNull()->end()
->booleanNode('use_default_driver')->defaultTrue()->end()
->end()
->end()
->end()
->arrayNode('twig')
->addDefaultsIfNotSet()
->children()
->enumNode('mode')
Expand Down Expand Up @@ -242,7 +292,7 @@ public function getConfigTreeBuilder(): TreeBuilder
$rootNode
->children()
->arrayNode('webp')
->addDefaultsIfNotSet()
->setDeprecated('liip/imagine-bundle', '2.x', 'The "webp" option is deprecated and will be removed in 3.0. Use "alternative_formats" instead.')
->children()
->booleanNode('generate')->defaultFalse()->end()
->integerNode('quality')->defaultValue(100)->end()
Expand Down
54 changes: 50 additions & 4 deletions DependencyInjection/LiipImagineExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
use Symfony\Component\Mime\MimeTypes;
Expand Down Expand Up @@ -146,10 +147,55 @@ public function load(array $configs, ContainerBuilder $container): void
->replaceArgument(1, $mimeTypes);
}

$container->setParameter('liip_imagine.webp.generate', $config['webp']['generate']);
$webpOptions = $config['webp'];
unset($webpOptions['generate']);
$container->setParameter('liip_imagine.webp.options', $webpOptions);
$alternativeFormats = $config['alternative_formats'] ?? [];
$container->setParameter('liip_imagine.alternative_formats', $alternativeFormats);

$mimeMap = [];
foreach ($alternativeFormats as $format => $formatConfig) {
if (!empty($formatConfig['mime_types'])) {
$mimeMap[$format] = $formatConfig['mime_types'];
}
}
$container->setParameter('liip_imagine.format_negotiator.mime_map', $mimeMap);

$postProcessorsMap = [];
foreach ($alternativeFormats as $format => $formatConfig) {
if (!empty($formatConfig['post_processors'])) {
$postProcessorsMap[$format] = $formatConfig['post_processors'];
}
}
$container->setParameter('liip_imagine.post_processors.map', $postProcessorsMap);

$formatNegotiatorDefinition = new Definition('Liip\ImagineBundle\Service\FormatNegotiator');
$formatNegotiatorDefinition->setArguments([
$container->getParameter('liip_imagine.format_negotiator.mime_map'),
new Reference('logger', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE),
]);
$container->setDefinition('liip_imagine.format_negotiator', $formatNegotiatorDefinition);

$container->setParameter('liip_imagine.alternative_formats', $alternativeFormats);

$container->getDefinition('liip_imagine.service.filter')
->replaceArgument(6, $alternativeFormats);

$this->setWebpCompatibilityParameters($container, $alternativeFormats);
}

private function setWebpCompatibilityParameters(ContainerBuilder $container, array $alternativeFormats): void
{
$webpConfig = $alternativeFormats['webp'] ?? [
'generate' => false,
'quality' => 100,
'cache' => null,
'data_loader' => null,
'post_processors' => [],
];

$container->setParameter('liip_imagine.webp.generate', $webpConfig['generate']);
$container->setParameter('liip_imagine.webp.quality', $webpConfig['quality']);
$container->setParameter('liip_imagine.webp.cache', $webpConfig['cache']);
$container->setParameter('liip_imagine.webp.data_loader', $webpConfig['data_loader']);
$container->setParameter('liip_imagine.webp.post_processors', $webpConfig['post_processors']);
}

public function prepend(ContainerBuilder $container): void
Expand Down
33 changes: 25 additions & 8 deletions Imagine/Cache/CacheManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,39 @@ class CacheManager
protected $defaultResolver;

/**
* @var bool
* @var array|bool
*/
private $webpGenerate;
private $alternativeFormats;

/**
* Constructs the cache manager to handle Resolvers based on the provided FilterConfiguration.
*
* @param string $defaultResolver
* @param bool $webpGenerate
* @param string $defaultResolver
* @param array|bool $alternativeFormats
*/
public function __construct(
FilterConfiguration $filterConfig,
RouterInterface $router,
SignerInterface $signer,
EventDispatcherInterface $dispatcher,
$defaultResolver = null,
$webpGenerate = false
$alternativeFormats = []
) {
if (\is_bool($alternativeFormats)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we default the parameter to [] instead? otherwise not setting alternative formats triggers a deprecation

@trigger_error(\sprintf('Passing a boolean as the second argument to %s is deprecated since LiipImagineBundle 2.x and will be removed in 3.0. Pass an array of alternative formats instead.', __METHOD__), E_USER_DEPRECATED);
$alternativeFormats = $alternativeFormats?["webp" => ["generate" => true]]:[];
}

if (!is_array($alternativeFormats)) {
throw new \InvalidArgumentException('The second argument to '.__METHOD__.' must be an array or boolean.');
}

$this->filterConfig = $filterConfig;
$this->router = $router;
$this->signer = $signer;
$this->dispatcher = $dispatcher;
$this->defaultResolver = $defaultResolver ?: 'default';
$this->webpGenerate = $webpGenerate;
$this->alternativeFormats = $alternativeFormats;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would normalize this to have the property only accept array and translate false to [] and true to ['webp]. that way the BC is constrained to the constructor and the rest of the class simpler.

}

/**
Expand Down Expand Up @@ -108,15 +117,23 @@ public function addResolver($filter, ResolverInterface $resolver)
*/
public function getBrowserPath($path, $filter, array $runtimeConfig = [], $resolver = null, $referenceType = UrlGeneratorInterface::ABSOLUTE_URL)
{
$shouldGenerateAlternative = false;
foreach ($this->alternativeFormats as $formatConfig) {
if (isset($formatConfig['generate']) && true === $formatConfig['generate']) {
$shouldGenerateAlternative = true;
break;
}
}

if (!empty($runtimeConfig)) {
$rcPath = $this->getRuntimePath($path, $runtimeConfig);

return !$this->webpGenerate && $this->isStored($rcPath, $filter, $resolver) ?
return !$shouldGenerateAlternative && $this->isStored($rcPath, $filter, $resolver) ?
$this->resolve($rcPath, $filter, $resolver) :
$this->generateUrl($path, $filter, $runtimeConfig, $resolver, $referenceType);
}

return !$this->webpGenerate && $this->isStored($path, $filter, $resolver) ?
return !$shouldGenerateAlternative && $this->isStored($path, $filter, $resolver) ?
$this->resolve($path, $filter, $resolver) :
$this->generateUrl($path, $filter, [], $resolver, $referenceType);
}
Expand Down
6 changes: 5 additions & 1 deletion Imagine/Filter/FilterManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ private function exportConfiguredImageBinary(BinaryInterface $binary, ImageInter
$options['animated'] = $config['animated'];
}

$filteredFormat = $config['format'] ?? $binary->getFormat();
// If user explicitly requests to NOT use the default driver for conversion,
// ignore the configured target format here and export using the original format.
$useDefaultDriver = $config['use_default_driver'] ?? true;
$filteredFormat = $useDefaultDriver ? ($config['format'] ?? $binary->getFormat()) : $binary->getFormat();

try {
$filteredString = $image->get($filteredFormat, $options);
} catch (\Exception $exception) {
Expand Down
Loading
Loading