diff --git a/README.md b/README.md index 30d5701b..4e9a077a 100644 --- a/README.md +++ b/README.md @@ -181,13 +181,13 @@ A **status resolver** (`Webgriffe\SyliusAkeneoPlugin\Product\StatusResolverInter A **value handlers resolver** (`Webgriffe\SyliusAkeneoPlugin\ValueHandlersResolverInterface`) which is responsible to return a list of **value handlers** (`Webgriffe\SyliusAkeneoPlugin\ValueHandlerInterface`) for each Akeneo product attribute value. -The provided implementation of the value handlers resolver is the `Webgriffe\SyliusAkeneoPlugin\PriorityValueHandlersResolver` which returns, for each attribute value, the list of all the value handlers supporting that attribute value sorted by a priority. +The provided implementation of the value handlers resolver is the `Webgriffe\SyliusAkeneoPlugin\PriorityValueHandlersResolver` which returns, for each attribute value, the list of all the value handlers supporting that attribute value sorted by a priority. Each value handler returned by the resolver for a given attribute is then called to handle that value. For more detail on how the Product importer works look at the code of the `Webgriffe\SyliusAkeneoPlugin\Product\Importer::import()` method. #### Value handlers -By default, the provided `Webgriffe\SyliusAkeneoPlugin\PriorityValueHandlersResolver` is configured without any value handler. By configuring the `webgriffe_sylius_akeneo.value_handlers.product` array as explained in the configuration paragraph you add value handlers to the value handlers resolver. This plugin already provides some value handler implementations but you can easily implement your own by implementing the `Webgriffe\SyliusAkeneoPlugin\ValueHandlerInterface`. The provided value handlers implementations are: +By default, the provided `Webgriffe\SyliusAkeneoPlugin\PriorityValueHandlersResolver` is configured with value handlers specified in the `webgriffe_sylius_akeneo.value_handlers.product` array as explained in the configuration paragraph. This plugin already provides some value handler implementations that are: * `Webgriffe\SyliusAkeneoPlugin\ValueHandler\ChannelPricingValueHandler` (type `channel_pricing`): it sets the value found on a given Akeneo price attribute (`options.akeneo_attribute_code`) as the Sylius product's channels price for channels which the base currency is the price currency of the Akeneo price. * `Webgriffe\SyliusAkeneoPlugin\ValueHandler\ImageValueHandler` (type `image`): it downloads the image found on a given Akeneo image attribute (`options.akeneo_attribute_code`) and sets it as a Sylius product image with a provided type string (`options.sylius_image_type`). @@ -195,7 +195,17 @@ By default, the provided `Webgriffe\SyliusAkeneoPlugin\PriorityValueHandlersReso * `Webgriffe\SyliusAkeneoPlugin\ValueHandler\ProductOptionValueHandler` (type `product_option`): it sets the value found on a given Akeneo attribute as a Sylius product option value on the product variant. * `Webgriffe\SyliusAkeneoPlugin\ValueHandler\TranslatablePropertyValueHandler` (type `translatable_property`): using the [Symofony's Property Access component](https://symfony.com/doc/current/components/property_access.html), it sets the value found on a given Akeneo attribute (`options.akeneo_attribute_code`) on a given property path (`options.sylius_translation_property_path`) of both product and product variant translations. -To see an example about how to add more value handlers to the value handlers resolver see the `tests/Application/config/packages/webgriffe_sylius_akeneo_plugin.yaml` config file provided in the test application of this plugin. +To add a custom value handler to the resolver you can implement your own by implementing the `Webgriffe\SyliusAkeneoPlugin\ValueHandlerInterface` and then tag it with the `webgriffe_sylius_akeneo.product.value_handler` tag: + +```yaml +# config/services.yaml +app.my_custom_value_handler: + class: App\MyCustomValueHandler + tags: + - { name: 'webgriffe_sylius_akeneo.product.value_handler', priority: 42 } +``` + + ## Product associations importer @@ -251,7 +261,7 @@ To be able to setup a plugin's database, remember to configure you database cred - Behat (JS scenarios) 1. [Install Symfony CLI command](https://symfony.com/download). - + 2. Start Headless Chrome: ```bash diff --git a/composer.json b/composer.json index 21f815ab..703e570b 100644 --- a/composer.json +++ b/composer.json @@ -22,11 +22,13 @@ "friends-of-behat/mink-extension": "^2.4", "friends-of-behat/page-object-extension": "^0.3", "friends-of-behat/suite-settings-extension": "^1.0", - "phpstan/extension-installer": "^1.0", "friends-of-behat/symfony-extension": "^2.1", "friends-of-behat/variadic-extension": "^1.3", "lakion/mink-debug-extension": "^1.2.3", + "matthiasnoback/symfony-dependency-injection-test": "^4.2", + "mikey179/vfsstream": "^1.6", "phpspec/phpspec": "^6.1", + "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "0.12.25", "phpstan/phpstan-doctrine": "0.12.13", "phpstan/phpstan-webmozart-assert": "0.12.4", @@ -39,9 +41,8 @@ "symfony/intl": "^4.4|^5.0", "symfony/web-profiler-bundle": "^4.4|^5.0", "symfony/web-server-bundle": "^4.4|^5.0", - "vimeo/psalm": "3.11.4", "theofidry/alice-data-fixtures": "^1.1", - "mikey179/vfsstream": "^1.6" + "vimeo/psalm": "3.11.4" }, "conflict": { "symfony/doctrine-bridge": "4.4.16", diff --git a/src/DependencyInjection/WebgriffeSyliusAkeneoExtension.php b/src/DependencyInjection/WebgriffeSyliusAkeneoExtension.php index 81216236..1d902511 100644 --- a/src/DependencyInjection/WebgriffeSyliusAkeneoExtension.php +++ b/src/DependencyInjection/WebgriffeSyliusAkeneoExtension.php @@ -6,6 +6,7 @@ use Sylius\Bundle\ResourceBundle\DependencyInjection\Extension\AbstractResourceExtension; use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; @@ -17,8 +18,10 @@ use Webgriffe\SyliusAkeneoPlugin\ValueHandler\ProductOptionValueHandler; use Webgriffe\SyliusAkeneoPlugin\ValueHandler\TranslatablePropertyValueHandler; -final class WebgriffeSyliusAkeneoExtension extends AbstractResourceExtension +final class WebgriffeSyliusAkeneoExtension extends AbstractResourceExtension implements CompilerPassInterface { + private const VALUE_HANDLER_TAG = 'webgriffe_sylius_akeneo.product.value_handler'; + /** @var array */ public static $valueHandlersTypesDefinitions = [ 'channel_pricing' => [ @@ -101,6 +104,26 @@ public function load(array $config, ContainerBuilder $container): void } } + public function process(ContainerBuilder $container): void + { + if (!$container->has('webgriffe_sylius_akeneo.product.value_handlers_resolver')) { + return; + } + + $valueHandlersResolverDefinition = $container->findDefinition( + 'webgriffe_sylius_akeneo.product.value_handlers_resolver' + ); + + $taggedValueHandlers = $container->findTaggedServiceIds(self::VALUE_HANDLER_TAG); + foreach ($taggedValueHandlers as $id => $tags) { + // a service could have the same tag twice + foreach ($tags as $attributes) { + $priority = $attributes['priority'] ?? 0; + $valueHandlersResolverDefinition->addMethodCall('add', [new Reference($id), $priority]); + } + } + } + private function createValueHandlersDefinitionsAndPriorities(array $valueHandlers): array { $definitions = []; diff --git a/tests/Integration/DependencyInjection/CompilerPassTest.php b/tests/Integration/DependencyInjection/CompilerPassTest.php new file mode 100644 index 00000000..427d044f --- /dev/null +++ b/tests/Integration/DependencyInjection/CompilerPassTest.php @@ -0,0 +1,51 @@ +setDefinition( + 'webgriffe_sylius_akeneo.product.value_handlers_resolver', + $valueHandlersResolverDefinition + ); + $taggedValueHandlerDefinition = new Definition( + GenericPropertyValueHandler::class, + [ + new Reference('property_accessor'), + 'akeneo_attribute', + 'sylius_property', + ] + ); + $taggedValueHandlerDefinition->addTag('webgriffe_sylius_akeneo.product.value_handler', ['priority' => 42]); + $this->container->setDefinition('app.my.custom.value_handler', $taggedValueHandlerDefinition); + + $this->compile(); + + $this->assertContainerBuilderHasService('webgriffe_sylius_akeneo.product.value_handlers_resolver'); + $this->assertContainerBuilderHasServiceDefinitionWithMethodCall( + 'webgriffe_sylius_akeneo.product.value_handlers_resolver', + 'add', + [new Reference('app.my.custom.value_handler'), 42] + ); + } + + protected function registerCompilerPass(ContainerBuilder $container): void + { + $container->addCompilerPass(new WebgriffeSyliusAkeneoExtension()); + } +}