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

Allow to add custom value handlers to the resolver with service tag #16

Merged
merged 1 commit into from
Nov 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,21 +181,31 @@ 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`).
* `Webgriffe\SyliusAkeneoPlugin\ValueHandler\ImmutableSlugValueHandler` (type `immutable_slug`): it slugifies the value found on a given Akeneo attribute (`options.akeneo_attribute_code`) and sets it on the Sylius slug product translation property.
* `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

Expand Down Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
25 changes: 24 additions & 1 deletion src/DependencyInjection/WebgriffeSyliusAkeneoExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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' => [
Expand Down Expand Up @@ -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 = [];
Expand Down
51 changes: 51 additions & 0 deletions tests/Integration/DependencyInjection/CompilerPassTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Tests\Webgriffe\SyliusAkeneoPlugin\Integration\DependencyInjection;

use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractCompilerPassTestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Webgriffe\SyliusAkeneoPlugin\DependencyInjection\WebgriffeSyliusAkeneoExtension;
use Webgriffe\SyliusAkeneoPlugin\ValueHandler\GenericPropertyValueHandler;

final class CompilerPassTest extends AbstractCompilerPassTestCase
{
/**
* @test
*/
public function adds_tagged_value_handlers_to_resolver(): void
{
$valueHandlersResolverDefinition = new Definition();
$this->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());
}
}