Skip to content

Commit

Permalink
Merge pull request #16 from webgriffe/issue-15
Browse files Browse the repository at this point in the history
Allow to add custom value handlers to the resolver with service tag
  • Loading branch information
mmenozzi committed Nov 1, 2020
2 parents c6f9456 + eb5f467 commit 4957b3d
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 8 deletions.
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());
}
}

0 comments on commit 4957b3d

Please sign in to comment.