diff --git a/src/Builder/Capacity/Extractor/All.php b/src/Builder/Capacity/Extractor/All.php index 495cb91..e03e657 100644 --- a/src/Builder/Capacity/Extractor/All.php +++ b/src/Builder/Capacity/Extractor/All.php @@ -12,7 +12,9 @@ final class All implements Builder { private null|Node\Expr|Node\Identifier $endpoint = null; private null|Node\Expr $search = null; - private null|Node\Expr $code = null; + private null|Node\Expr $attributeCode = null; + private null|Node\Expr $assetFamilyCode = null; + private null|Node\Expr $file = null; private null|string $type = null; public function __construct() @@ -33,9 +35,23 @@ public function withSearch(Node\Expr $search): self return $this; } - public function withCode(?Node\Expr $code): self + public function withAttributeOption(?Node\Expr $attributeCode): self { - $this->code = $code; + $this->attributeCode = $attributeCode; + + return $this; + } + + public function withAssetManager(?Node\Expr $assetFamilyCode): self + { + $this->assetFamilyCode = $assetFamilyCode; + + return $this; + } + + public function withFile(Node\Expr $file): self + { + $this->file = $file; return $this; } @@ -75,8 +91,16 @@ public function getNode(): Node ), name: new Node\Identifier('queryParameters'), ), - null !== $this->code ? new Node\Arg( - value: $this->code, + null !== $this->attributeCode ? new Node\Arg( + value: $this->attributeCode, + name: $this->compileCodeNamedArgument($this->type), + ) : null, + null !== $this->assetFamilyCode ? new Node\Arg( + value: $this->assetFamilyCode, + name: $this->compileCodeNamedArgument($this->type), + ) : null, + null !== $this->file ? new Node\Arg( + value: $this->file, name: $this->compileCodeNamedArgument($this->type), ) : null, ], diff --git a/src/Builder/Capacity/Extractor/Get.php b/src/Builder/Capacity/Extractor/Get.php index 5925c17..ef35835 100644 --- a/src/Builder/Capacity/Extractor/Get.php +++ b/src/Builder/Capacity/Extractor/Get.php @@ -4,6 +4,7 @@ namespace Kiboko\Plugin\Akeneo\Builder\Capacity\Extractor; +use Kiboko\Plugin\Akeneo\Handler\EndpointArgumentHandlerInterface; use Kiboko\Plugin\Akeneo\MissingEndpointException; use PhpParser\Builder; use PhpParser\Node; @@ -11,10 +12,10 @@ final class Get implements Builder { private null|Node\Expr|Node\Identifier $endpoint = null; - private null|Node\Expr $identifier = null; - public function __construct() - { + public function __construct( + private readonly EndpointArgumentHandlerInterface $handler, + ) { } public function withEndpoint(Node\Expr|Node\Identifier $endpoint): self @@ -24,13 +25,6 @@ public function withEndpoint(Node\Expr|Node\Identifier $endpoint): self return $this; } - public function withIdentifier(?Node\Expr $identifier): self - { - $this->identifier = $identifier; - - return $this; - } - public function getNode(): Node { if (null === $this->endpoint) { @@ -52,16 +46,8 @@ class: new Node\Name\FullyQualified(name: \Kiboko\Component\Bucket\AcceptanceRes name: $this->endpoint ), name: new Node\Identifier('get'), - args: array_filter( - [ - new Node\Arg( - value: $this->identifier, - name: new Node\Identifier('code'), - ), - ], - ), + args: $this->handler->compileEndpointArguments(), ), - unpack: true, ), ], ), diff --git a/src/Capacity/Extractor/All.php b/src/Capacity/Extractor/All.php index 0b73402..047358a 100644 --- a/src/Capacity/Extractor/All.php +++ b/src/Capacity/Extractor/All.php @@ -10,7 +10,6 @@ use PhpParser\Node; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use function Kiboko\Component\SatelliteToolbox\Configuration\compileValue; use function Kiboko\Component\SatelliteToolbox\Configuration\compileValueWhenExpression; final class All implements Akeneo\Capacity\CapacityInterface @@ -79,11 +78,11 @@ private function compileFilters(array ...$filters): Node\Expr } $builder->addFilter( - field: compileValue($this->interpreter, $filter['field']), - operator: compileValue($this->interpreter, $filter['operator']), - value: \array_key_exists('value', $filter) ? compileValue($this->interpreter, $filter['value']) : null, - scope: \array_key_exists('scope', $filter) ? compileValue($this->interpreter, $filter['scope']) : null, - locale: \array_key_exists('locale', $filter) ? compileValue($this->interpreter, $filter['locale']) : null + field: compileValueWhenExpression($this->interpreter, $filter['field']), + operator: compileValueWhenExpression($this->interpreter, $filter['operator']), + value: \array_key_exists('value', $filter) ? compileValueWhenExpression($this->interpreter, $filter['value']) : null, + scope: \array_key_exists('scope', $filter) ? compileValueWhenExpression($this->interpreter, $filter['scope']) : null, + locale: \array_key_exists('locale', $filter) ? compileValueWhenExpression($this->interpreter, $filter['locale']) : null ); } @@ -101,8 +100,16 @@ public function getBuilder(array $config): Builder $builder->withSearch($this->compileFilters(...$config['search'])); } - if (\in_array($config['type'], ['attributeOption', 'assetManager', 'referenceEntityRecord']) && \array_key_exists('code', $config)) { - $builder->withCode(compileValueWhenExpression($this->interpreter, $config['code'])); + if (\in_array($config['type'], ['attributeOption'])) { + $builder->withAttributeOption(compileValueWhenExpression($this->interpreter, $config['attribute_code'])); + } + + if (\in_array($config['type'], ['assetManager'])) { + $builder->withAssetManager(compileValueWhenExpression($this->interpreter, $config['asset_family_code'])); + } + + if (\in_array($config['type'], ['productMediaFile', 'assetMediaFile'])) { + $builder->withFile(compileValueWhenExpression($this->interpreter, $config['file'])); } return $builder; diff --git a/src/Capacity/Extractor/Get.php b/src/Capacity/Extractor/Get.php index f7f897e..0b449e7 100644 --- a/src/Capacity/Extractor/Get.php +++ b/src/Capacity/Extractor/Get.php @@ -7,9 +7,6 @@ use Kiboko\Plugin\Akeneo; use PhpParser\Builder; use PhpParser\Node; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - -use function Kiboko\Component\SatelliteToolbox\Configuration\compileValueWhenExpression; final class Get implements Akeneo\Capacity\CapacityInterface { @@ -43,8 +40,9 @@ final class Get implements Akeneo\Capacity\CapacityInterface 'assetManager', ]; - public function __construct(private readonly ExpressionLanguage $interpreter) - { + public function __construct( + private readonly Akeneo\Handler\EndpointHandlerFactoryInterface $factory, + ) { } public function applies(array $config): bool @@ -57,12 +55,10 @@ public function applies(array $config): bool public function getBuilder(array $config): Builder { - $builder = (new Akeneo\Builder\Capacity\Extractor\Get()) - ->withEndpoint(new Node\Identifier(sprintf('get%sApi', ucfirst((string) $config['type'])))) + return (new Akeneo\Builder\Capacity\Extractor\Get($this->factory->create($config['type'], $config))) + ->withEndpoint( + new Node\Identifier(sprintf('get%sApi', ucfirst((string) $config['type']))), + ) ; - - $builder->withIdentifier(compileValueWhenExpression($this->interpreter, $config['identifier'])); - - return $builder; } } diff --git a/src/Configuration/Extractor.php b/src/Configuration/Extractor.php index 3e2c7db..0dbd6d1 100644 --- a/src/Configuration/Extractor.php +++ b/src/Configuration/Extractor.php @@ -148,26 +148,64 @@ public function getConfigTreeBuilder(): Config\Definition\Builder\TreeBuilder /* @phpstan-ignore-next-line */ $builder->getRootNode() ->validate() - ->ifArray() - ->then(function (array $item) { - if (!\in_array($item['method'], self::$endpoints[$item['type']])) { - throw new \InvalidArgumentException(sprintf('the value should be one of [%s], got %s', implode(', ', self::$endpoints[$item['type']]), json_encode($item['method'], \JSON_THROW_ON_ERROR))); - } - - return $item; - }) + ->ifTrue(fn ($data) => (\array_key_exists('asset_family_code', $data) || \array_key_exists('asset_code', $data)) + && \array_key_exists('type', $data) + && !\in_array($data['type'], ['assetManager'], true)) + ->thenInvalid('The asset_family_code and asset_code options should only be used with the "assetManager" endpoint.') + ->end() + ->validate() + ->ifTrue(fn ($data) => (!\array_key_exists('asset_family_code', $data) || !\array_key_exists('asset_code', $data)) + && 'get' === $data['method'] + && \array_key_exists('type', $data) + && \in_array($data['type'], ['assetManager'], true)) + ->thenInvalid('The asset_family_code and the asset_code options should be used with the "assetManager" endpoint.') ->end() ->validate() - ->ifTrue(fn ($data) => \array_key_exists('code', $data) + ->ifTrue(fn ($data) => !\array_key_exists('asset_family_code', $data) + && 'all' === $data['method'] + && \array_key_exists('type', $data) + && \in_array($data['type'], ['assetManager'], true)) + ->thenInvalid('The asset_family_code option should be used with the "assetManager" endpoint.') + ->end() + ->validate() + ->ifTrue(fn ($data) => (\array_key_exists('attribute_code', $data) || \array_key_exists('code', $data)) + && 'get' === $data['method'] && \array_key_exists('type', $data) - && !\in_array($data['type'], ['attributeOption', 'referenceEntityRecord', 'assetManager'], true)) - ->thenInvalid('The code option should only be used with the "attributeOption" and "assetManager" endpoints.') + && !\in_array($data['type'], ['attributeOption'], true)) + ->thenInvalid('The attribute_code and code options should only be used with the "attributeOption" endpoint.') + ->end() + ->validate() + ->ifTrue(fn ($data) => \array_key_exists('attribute_code', $data) + && 'all' === $data['method'] + && \array_key_exists('type', $data) + && !\in_array($data['type'], ['attributeOption'], true)) + ->thenInvalid('The attribute_code option should only be used with the "attributeOption" endpoint.') + ->end() + ->validate() + ->ifTrue(fn ($data) => (!\array_key_exists('attribute_code', $data) || !\array_key_exists('code', $data)) + && 'get' === $data['method'] + && \array_key_exists('type', $data) + && \in_array($data['type'], ['attributeOption'], true)) + ->thenInvalid('The attribute_code and code options should be used with the "attributeOption" endpoint.') + ->end() + ->validate() + ->ifTrue(fn ($data) => !\array_key_exists('attribute_code', $data) + && 'all' === $data['method'] + && \array_key_exists('type', $data) + && \in_array($data['type'], ['attributeOption'], true)) + ->thenInvalid('The attribute_code option should be used with the "attributeOption" endpoint.') ->end() ->validate() ->ifTrue(fn ($data) => \array_key_exists('file', $data) && \array_key_exists('type', $data) && !\in_array($data['type'], ['productMediaFile', 'assetMediaFile'], true)) - ->thenInvalid('The file option should only be used with the "productMediaFile" endpoint.') + ->thenInvalid('The file option should only be used with the "productMediaFile" and the "assetMediaFile" endpoints.') + ->end() + ->validate() + ->ifTrue(fn ($data) => !\array_key_exists('file', $data) + && \array_key_exists('type', $data) + && \in_array($data['type'], ['productMediaFile', 'assetMediaFile'], true)) + ->thenInvalid('The file option should be used with the "productMediaFile" and the "assetMediaFile" endpoints.') ->end() ->validate() ->ifTrue(fn ($data) => \array_key_exists('identifier', $data) && \array_key_exists('method', $data) && 'get' !== $data['method']) @@ -202,6 +240,24 @@ public function getConfigTreeBuilder(): Config\Definition\Builder\TreeBuilder ->then(asExpression()) ->end() ->end() + ->scalarNode('attribute_code') + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ->end() + ->scalarNode('asset_family_code') + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ->end() + ->scalarNode('asset_code') + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ->end() ->append((new Search())->getConfigTreeBuilder()->getRootNode()) ->end() ; diff --git a/src/DTO/GetAssetManager.php b/src/DTO/GetAssetManager.php new file mode 100644 index 0000000..42a3d56 --- /dev/null +++ b/src/DTO/GetAssetManager.php @@ -0,0 +1,16 @@ +configuration = new Akeneo\Configuration\Extractor(); $this->capacities = [ new Akeneo\Capacity\Extractor\All($this->interpreter), - new Akeneo\Capacity\Extractor\Get($this->interpreter), + new Akeneo\Capacity\Extractor\Get( + new Akeneo\Handler\GetEndpointHandlerFactory($this->interpreter), + ), new Akeneo\Capacity\Extractor\ListPerPage($this->interpreter), ]; } diff --git a/src/Handler/EndpointArgumentHandlerInterface.php b/src/Handler/EndpointArgumentHandlerInterface.php new file mode 100644 index 0000000..a984ed9 --- /dev/null +++ b/src/Handler/EndpointArgumentHandlerInterface.php @@ -0,0 +1,10 @@ +assetManager->assetFamilyCode, + name: new Node\Identifier('assetFamilyCode'), + ), + new Node\Arg( + value: $this->assetManager->assetCode, + name: new Node\Identifier('assetCode'), + ), + ]; + } +} diff --git a/src/Handler/GetAttributeOptionHandler.php b/src/Handler/GetAttributeOptionHandler.php new file mode 100644 index 0000000..fda4614 --- /dev/null +++ b/src/Handler/GetAttributeOptionHandler.php @@ -0,0 +1,29 @@ +attributeOption->attributeCode, + name: new Node\Identifier('attributeCode'), + ), + new Node\Arg( + value: $this->attributeOption->code, + name: new Node\Identifier('code'), + ), + ]; + } +} diff --git a/src/Handler/GetDefaultEndpointHandler.php b/src/Handler/GetDefaultEndpointHandler.php new file mode 100644 index 0000000..040422f --- /dev/null +++ b/src/Handler/GetDefaultEndpointHandler.php @@ -0,0 +1,25 @@ +defaultEndpoint->identifier, + name: new Node\Identifier('identifier'), + ), + ]; + } +} diff --git a/src/Handler/GetEndpointHandlerFactory.php b/src/Handler/GetEndpointHandlerFactory.php new file mode 100644 index 0000000..e3fe7e3 --- /dev/null +++ b/src/Handler/GetEndpointHandlerFactory.php @@ -0,0 +1,43 @@ + new GetAttributeOptionHandler( + new GetAttributeOption( + compileValueWhenExpression($this->interpreter, $config['attribute_code']), + compileValueWhenExpression($this->interpreter, $config['code']), + ), + ), + 'assetManager' => new GetAssetManagerHandler( + new GetAssetManager( + compileValueWhenExpression($this->interpreter, $config['asset_family_code']), + compileValueWhenExpression($this->interpreter, $config['asset_code']), + ), + ), + default => new GetDefaultEndpointHandler( + new GetDefaultEndpoint( + compileValueWhenExpression($this->interpreter, $config['asset_family_code']) + ), + ), + }; + } +} diff --git a/tests/functional/Builder/Capacity/Extractor/AllTest.php b/tests/functional/Builder/Capacity/Extractor/AllTest.php index 9e9946d..35b0917 100644 --- a/tests/functional/Builder/Capacity/Extractor/AllTest.php +++ b/tests/functional/Builder/Capacity/Extractor/AllTest.php @@ -16,7 +16,7 @@ public function testWithoutEndpoint() $this->expectException(MissingEndpointException::class); $this->expectExceptionMessage('Please check your capacity builder, you should have selected an endpoint.'); - $capacity->withCode(new Node\Scalar\String_('foo')); + $capacity->withAttributeOption(new Node\Scalar\String_('foo')); $capacity->getNode(); } diff --git a/tests/functional/Builder/Capacity/Extractor/GetTest.php b/tests/functional/Builder/Capacity/Extractor/GetTest.php index 40b21ae..e18e33b 100644 --- a/tests/functional/Builder/Capacity/Extractor/GetTest.php +++ b/tests/functional/Builder/Capacity/Extractor/GetTest.php @@ -4,6 +4,8 @@ use functional\Kiboko\Plugin\Akeneo\Builder\BuilderTestCase; use Kiboko\Plugin\Akeneo\Builder\Capacity\Extractor\Get; +use Kiboko\Plugin\Akeneo\DTO\GetDefaultEndpoint; +use Kiboko\Plugin\Akeneo\Handler\GetDefaultEndpointHandler; use Kiboko\Plugin\Akeneo\MissingEndpointException; use PhpParser\Node; @@ -11,9 +13,13 @@ final class GetTest extends BuilderTestCase { public function testWithoutEndpoint() { - $capacity = new Get(); - - $capacity->withIdentifier(new Node\Scalar\String_('foo')); + $capacity = new Get( + new GetDefaultEndpointHandler( + new GetDefaultEndpoint( + new Node\Scalar\String_('foo'), + ), + ), + ); $this->expectException(MissingEndpointException::class); $this->expectExceptionMessage('Please check your capacity builder, you should have selected an endpoint.'); @@ -23,7 +29,13 @@ public function testWithoutEndpoint() public function testWithoutIdentifier() { - $capacity = new Get(); + $capacity = new Get( + new GetDefaultEndpointHandler( + new GetDefaultEndpoint( + new Node\Scalar\String_('foo'), + ), + ), + ); $capacity->withEndpoint(new Node\Identifier('foo')); @@ -34,10 +46,15 @@ public function testWithoutIdentifier() public function testWithEndpoint() { - $capacity = new Get(); + $capacity = new Get( + new GetDefaultEndpointHandler( + new GetDefaultEndpoint( + new Node\Scalar\String_('foo'), + ), + ), + ); $capacity->withEndpoint(new Node\Identifier('foo')); - $capacity->withIdentifier(new Node\Scalar\String_('foo')); $this->assertInstanceOf(Node\Stmt\Expression::class, $capacity->getNode()); } diff --git a/tests/functional/Builder/Extractor/ExtractorTest.php b/tests/functional/Builder/Extractor/ExtractorTest.php index 89ad411..8b26b5c 100644 --- a/tests/functional/Builder/Extractor/ExtractorTest.php +++ b/tests/functional/Builder/Extractor/ExtractorTest.php @@ -7,6 +7,9 @@ use Kiboko\Component\PHPUnitExtension\Assert\ExtractorBuilderAssertTrait; use Kiboko\Plugin\Akeneo\Builder\Extractor; use Kiboko\Plugin\Akeneo\Capacity; +use Kiboko\Plugin\Akeneo\DTO\GetDefaultEndpoint; +use Kiboko\Plugin\Akeneo\Handler\GetDefaultEndpointHandler; +use Kiboko\Plugin\Akeneo\Handler\GetEndpointHandlerFactory; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; final class ExtractorTest extends BuilderTestCase @@ -173,7 +176,7 @@ public function testGetProduct(): void ->withAuthenticatedByPassword() ; - $capacity = (new Capacity\Extractor\Get(new ExpressionLanguage()))->getBuilder([ + $capacity = (new Capacity\Extractor\Get(new GetEndpointHandlerFactory(new ExpressionLanguage())))->getBuilder([ 'type' => 'product', 'identifier' => '123qwerty' ]); diff --git a/tests/functional/Configuration/ExtractorTest.php b/tests/functional/Configuration/ExtractorTest.php index 1e89067..feffb01 100644 --- a/tests/functional/Configuration/ExtractorTest.php +++ b/tests/functional/Configuration/ExtractorTest.php @@ -72,12 +72,14 @@ public static function validDataProvider(): iterable 'config' => [ 'method' => 'get', 'type' => 'attributeOption', + 'attribute_code' => 'color', 'code' => '123', 'search' => [], ], 'expected' => [ 'method' => 'get', 'type' => 'attributeOption', + 'attribute_code' => 'color', 'code' => '123', 'search' => [], ],