Reset settings when the config is divided into parts
I want to put the filter configurations into modules, but in this case the global settings of resolvers and loaders will no longer apply to all filters.
Preconditions
# php -v
PHP 7.2.8 (cli) (built: Jul 21 2018 07:56:11) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.8, Copyright (c) 1999-2018, by Zend Technologies
# composer show --latest 'liip/*'
liip/imagine-bundle 2.1.0 2.1.0 This bundle provides an image manipulation abstraction toolkit for Symfony-based projects.
Steps to reproduce
- Create global config
/config/packages/liip_imagine.ymlwith:
liip_imagine:
resolvers:
default:
web_path:
cache_prefix: 'media/suit'
filter_sets:
autocomplete:
filters:
fixed: { width: 60, height: 60 }
- Create config in module with:
liip_imagine:
filter_sets:
news_cover_in_list:
filters:
fixed: { width: 800, height: 600 }
- Then use this filters in template:
<img src="{{ 'media/test.jpg' | imagine_filter('autocomplete') }}" alt="" />
<img src="{{ 'media/test.jpg' | imagine_filter('news_cover_in_list') }}" alt="" />
Expected result
<img src="/media/suit/autocomplete/media/test.jpg" alt="" />
<img src="/media/suit/news_cover_in_list/media/test.jpg" alt="" />
Actual result
<img src="/media/cache/autocomplete/media/test.jpg" alt="" />
<img src="/media/cache/news_cover_in_list/media/test.jpg" alt="" />
i also had this problem (and also 2 friends of mine @vworld, @MaxValEh)
we split our config in edition.yaml and app.yaml where edition.yaml are our global defaults and app.yaml are the settings for the current project/app.
our kernel.php looks a little bit different:
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
parent::configureContainer($container, $loader);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/{edition}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{edition}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{app}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{app}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
}
edition.yaml
liip_imagine:
driver: "gd"
resolvers:
default:
web_path:
web_root: '%kernel.project_dir%/public'
cache_prefix: 'cache/images'
loaders:
default:
filesystem:
data_root:
- '%kernel.project_dir%/assets/images'
app.yaml:
liip_imagine:
loaders:
default:
filesystem:
data_root:
- '%kernel.project_dir%/var/data/uploads/photo-app'
php bin/console debug:config liip_imagine
liip_imagine:
driver: gd
resolvers:
default:
web_path:
web_root: '/src/web'
cache_prefix: media/cache
loaders:
default:
filesystem:
data_root:
- '/src/assets/images'
- '/src/var/data/uploads/photo-app'
so the data_root root gets correctly merged but the web_path is wrong now.
the reason is how the bundle handles the config.
vendor/liip/imagine-bundle/DependencyInjection/Configuration.php
$rootNode
->beforeNormalization()
->ifTrue(function ($v) {
return
empty($v['loaders']) ||
empty($v['loaders']['default']) ||
empty($v['resolvers']) ||
empty($v['resolvers']['default']);
})
->then(function ($v) {
if (empty($v['loaders'])) {
$v['loaders'] = [];
}
if (false === is_array($v['loaders'])) {
throw new \LogicException('Loaders has to be array');
}
if (false === array_key_exists('default', $v['loaders'])) {
$v['loaders']['default'] = ['filesystem' => null];
}
if (empty($v['resolvers'])) {
$v['resolvers'] = [];
}
if (false === is_array($v['resolvers'])) {
throw new \LogicException('Resolvers has to be array');
}
if (false === array_key_exists('default', $v['resolvers'])) {
$v['resolvers']['default'] = ['web_path' => null];
}
return $v;
})
->end();
if you remove the following part from liip imagines code
// if (false === array_key_exists('default', $v['resolvers'])) {
// $v['resolvers']['default'] = ['web_path' => null];
// }
it works.
quite a unpleasent situation, the current error handling is correct but kills hierarchical configuration. i rather would go for hierarchical config instead of "better" error handling, feels like the better DX.
having only the following config
liip_imagine:
loaders:
default:
filesystem:
data_root:
- '%kernel.project_dir%/var/data/uploads/photo-app'
still creates a valid config (no exceptions, no errors) where its clear that i have no resolvers configured.
liip_imagine:
driver: gd
loaders:
default:
filesystem:
data_root:
- '/src/var/data/uploads/photo-app'
locator: filesystem
bundle_resources:
enabled: false
access_control_type: blacklist
access_control_list: { }
resolvers: {}
the current behavior feels like symfony1 magic.
The problem is that additional configs are loaded after the main config.
# main config
liip_imagine:
resolvers:
default:
flysystem:
filesystem_service: oneup_flysystem.profile_photos_filesystem
root_url: "http://images.example.com"
cache_prefix: media/cache
visibility: public
loaders:
default:
flysystem:
filesystem_service: oneup_flysystem.profile_photos_filesystem
# additional config
liip_imagine:
filter_sets:
autocomplete:
quality: 80
format: jpg
filters:
background: { color: '#ffffff' }
fixed: { width: 60, height: 60 }
Additional configs doesn't have options resolvers and loaders and a normalizer is launched for them. The normalizer adds options to the additional config and after the main and additional config are merged, the data in the main config is overwritten.
# ./bin/console debug:config liip_imagine
liip_imagine:
resolvers:
default:
web_path:
web_root: /application/app/../web
cache_prefix: media/cache
loaders:
default:
flysystem:
filesystem_service: oneup_flysystem.profile_photos_filesystem
filesystem:
locator: filesystem
data_root:
- /application/app/../web
bundle_resources:
enabled: false
access_control_type: blacklist
access_control_list: { }
I agree with @c33s. I would generally remove the normalization here.