mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
[Api][Attribute] Switch storage type setting from persister to event subscriber
This commit is contained in:
parent
cf5f3ac76b
commit
41ba211323
8 changed files with 233 additions and 43 deletions
|
|
@ -9,13 +9,13 @@ Feature: Deleting a product attribute
|
|||
And the store has a product "44 Magnum"
|
||||
|
||||
@ui @api
|
||||
Scenario: Try deleting a attribute from the registry when product use him
|
||||
Scenario: Try deleting a attribute from the registry when a product uses it
|
||||
Given this product has a text attribute "Gun caliber" with value "11 mm"
|
||||
When I delete this product attribute
|
||||
Then I should be notified that it is in use
|
||||
|
||||
@ui @api
|
||||
Scenario: Deleting a text product attribute when not by used
|
||||
Scenario: Deleting a text product attribute when it's not used
|
||||
Given the store has a text product attribute "Gun caliber"
|
||||
When I delete this product attribute
|
||||
Then I should be notified that it has been successfully deleted
|
||||
|
|
|
|||
|
|
@ -770,6 +770,26 @@ parameters:
|
|||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:remove\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductAttributeDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/ProductAttributeDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductTaxonDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
|
@ -2250,6 +2270,11 @@ parameters:
|
|||
count: 1
|
||||
path: src/Sylius/Bundle/CoreBundle/CatalogPromotion/Checker/CatalogPromotionEligibilityChecker.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\CatalogPromotion\\\\Checker\\\\InForTaxonsScopeVariantChecker\\:\\:__construct\\(\\) has parameter \\$taxonRepository with generic interface Sylius\\\\Component\\\\Taxonomy\\\\Repository\\\\TaxonRepositoryInterface but does not specify its types\\: T$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/CoreBundle/CatalogPromotion/Checker/InForTaxonsScopeVariantChecker.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\CoreBundle\\\\CatalogPromotion\\\\Checker\\\\ProductVariantForCatalogPromotionEligibility\\:\\:__construct\\(\\) has parameter \\$locator with generic class Symfony\\\\Component\\\\DependencyInjection\\\\ServiceLocator but does not specify its types\\: T$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -7,17 +7,13 @@ namespace Sylius\Bundle\ApiBundle\DataPersister;
|
|||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
|
||||
use Sylius\Bundle\ApiBundle\Exception\ProductAttributeCannotBeRemoved;
|
||||
use Sylius\Component\Attribute\AttributeType\AttributeTypeInterface;
|
||||
use Sylius\Component\Product\Model\ProductAttributeInterface;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductAttributeDataPersister implements ContextAwareDataPersisterInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||
private ServiceRegistryInterface $attributeTypeRegistry,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -29,13 +25,6 @@ final class ProductAttributeDataPersister implements ContextAwareDataPersisterIn
|
|||
/** @param ProductAttributeInterface $data */
|
||||
public function persist($data, array $context = [])
|
||||
{
|
||||
if (null === $data->getStorageType() && null !== $data->getType()) {
|
||||
/** @var AttributeTypeInterface $attributeType */
|
||||
$attributeType = $this->attributeTypeRegistry->get($data->getType());
|
||||
|
||||
$data->setStorageType($attributeType->getStorageType());
|
||||
}
|
||||
|
||||
return $this->decoratedDataPersister->persist($data, $context);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\EventSubscriber;
|
||||
|
||||
use ApiPlatform\Core\EventListener\EventPriorities;
|
||||
use Sylius\Component\Attribute\AttributeType\AttributeTypeInterface;
|
||||
use Sylius\Component\Attribute\Model\AttributeInterface;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\ViewEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/** @experimental */
|
||||
final class AttributeEventSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(private ServiceRegistryInterface $attributeTypeRegistry)
|
||||
{
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::VIEW => ['assignStorageType', EventPriorities::PRE_VALIDATE],
|
||||
];
|
||||
}
|
||||
|
||||
public function assignStorageType(ViewEvent $event): void
|
||||
{
|
||||
$attribute = $event->getControllerResult();
|
||||
$method = $event->getRequest()->getMethod();
|
||||
|
||||
if (
|
||||
!$attribute instanceof AttributeInterface ||
|
||||
!in_array($method, [Request::METHOD_POST, Request::METHOD_PUT], true)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $attribute->getType() || '' === $attribute->getType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
null !== $attribute->getStorageType() ||
|
||||
!$this->attributeTypeRegistry->has($attribute->getType())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var AttributeTypeInterface $attributeType */
|
||||
$attributeType = $this->attributeTypeRegistry->get($attribute->getType());
|
||||
|
||||
$attribute->setStorageType($attributeType->getStorageType());
|
||||
|
||||
$event->setControllerResult($attribute);
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,6 @@
|
|||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\ProductAttributeDataPersister">
|
||||
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
|
||||
<argument type="service" id="sylius.registry.attribute_type" />
|
||||
<tag name="api_platform.data_persister" />
|
||||
</service>
|
||||
|
||||
|
|
|
|||
|
|
@ -54,5 +54,10 @@
|
|||
<argument type="service" id="sylius.generator.taxon_slug" />
|
||||
<tag name="kernel.event_subscriber" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\EventSubscriber\AttributeEventSubscriber">
|
||||
<argument type="service" id="sylius.registry.attribute_type" />
|
||||
<tag name="kernel.event_subscriber" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -17,17 +17,13 @@ use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
|||
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Exception\ProductAttributeCannotBeRemoved;
|
||||
use Sylius\Component\Attribute\AttributeType\AttributeTypeInterface;
|
||||
use Sylius\Component\Attribute\AttributeType\TextAttributeType;
|
||||
use Sylius\Component\Attribute\Model\AttributeValueInterface;
|
||||
use Sylius\Component\Product\Model\ProductAttributeInterface;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
|
||||
final class ProductAttributeDataPersisterSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ContextAwareDataPersisterInterface $persister, ServiceRegistryInterface $typesRegistry): void
|
||||
function let(ContextAwareDataPersisterInterface $persister): void
|
||||
{
|
||||
$this->beConstructedWith($persister, $typesRegistry);
|
||||
$this->beConstructedWith($persister);
|
||||
}
|
||||
|
||||
function it_is_a_context_aware_persister(): void
|
||||
|
|
@ -41,32 +37,10 @@ final class ProductAttributeDataPersisterSpec extends ObjectBehavior
|
|||
$this->supports($productAttribute)->shouldReturn(true);
|
||||
}
|
||||
|
||||
function it_uses_inner_persister_to_persist_product_attribute_when_storage_type_is_set(
|
||||
function it_uses_inner_persister_to_persist_product_attribute(
|
||||
ContextAwareDataPersisterInterface $persister,
|
||||
ProductAttributeInterface $productAttribute,
|
||||
): void {
|
||||
$productAttribute->getType()->willReturn(TextAttributeType::TYPE);
|
||||
$productAttribute->getStorageType()->willReturn(AttributeValueInterface::STORAGE_TEXT);
|
||||
|
||||
$persister->persist($productAttribute, [])->shouldBeCalled();
|
||||
|
||||
$this->persist($productAttribute, []);
|
||||
}
|
||||
|
||||
function it_sets_storage_type_when_none_is_set_but_type_is(
|
||||
ContextAwareDataPersisterInterface $persister,
|
||||
ServiceRegistryInterface $typesRegistry,
|
||||
AttributeTypeInterface $attributeType,
|
||||
ProductAttributeInterface $productAttribute,
|
||||
): void {
|
||||
$productAttribute->getType()->willReturn(TextAttributeType::TYPE);
|
||||
$productAttribute->getStorageType()->willReturn(null);
|
||||
|
||||
$attributeType->getStorageType()->willReturn(AttributeValueInterface::STORAGE_TEXT);
|
||||
$typesRegistry->get(TextAttributeType::TYPE)->willReturn($attributeType);
|
||||
|
||||
$productAttribute->setStorageType(AttributeValueInterface::STORAGE_TEXT)->shouldBeCalled();
|
||||
|
||||
$persister->persist($productAttribute, [])->shouldBeCalled();
|
||||
|
||||
$this->persist($productAttribute, []);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\EventSubscriber;
|
||||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Component\Attribute\AttributeType\AttributeTypeInterface;
|
||||
use Sylius\Component\Attribute\Model\AttributeInterface;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\ViewEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
final class AttributeEventSubscriberSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ServiceRegistryInterface $registry): void
|
||||
{
|
||||
$this->beConstructedWith($registry);
|
||||
}
|
||||
|
||||
function it_implements_event_subscriber_interface(): void
|
||||
{
|
||||
$this->shouldImplement(EventSubscriberInterface::class);
|
||||
}
|
||||
|
||||
function it_does_nothing_when_controller_result_is_not_an_attribute(
|
||||
ServiceRegistryInterface $registry,
|
||||
HttpKernelInterface $kernel,
|
||||
Request $request,
|
||||
): void {
|
||||
$request->getMethod()->shouldBeCalled();
|
||||
$registry->has(Argument::any())->shouldNotBeCalled();
|
||||
|
||||
$this->assignStorageType(new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
new \stdClass(),
|
||||
));
|
||||
}
|
||||
|
||||
function it_does_nothing_when_attribute_has_no_type(
|
||||
ServiceRegistryInterface $registry,
|
||||
HttpKernelInterface $kernel,
|
||||
Request $request,
|
||||
AttributeInterface $attribute,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_POST);
|
||||
$attribute->getType()->willReturn(null);
|
||||
|
||||
$registry->has(Argument::any())->shouldNotBeCalled();
|
||||
|
||||
$this->assignStorageType(new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$attribute->getWrappedObject(),
|
||||
));
|
||||
}
|
||||
|
||||
function it_does_nothing_when_attribute_has_a_storage_type(
|
||||
ServiceRegistryInterface $registry,
|
||||
HttpKernelInterface $kernel,
|
||||
Request $request,
|
||||
AttributeInterface $attribute,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_POST);
|
||||
$attribute->getType()->willReturn('text');
|
||||
$attribute->getStorageType()->willReturn('text');
|
||||
|
||||
$registry->has(Argument::any())->shouldNotBeCalled();
|
||||
|
||||
$this->assignStorageType(new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$attribute->getWrappedObject(),
|
||||
));
|
||||
}
|
||||
|
||||
function it_does_nothing_when_attribute_type_is_not_registered(
|
||||
ServiceRegistryInterface $registry,
|
||||
HttpKernelInterface $kernel,
|
||||
Request $request,
|
||||
AttributeInterface $attribute,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_POST);
|
||||
$attribute->getType()->willReturn('foo');
|
||||
$attribute->getStorageType()->willReturn(null);
|
||||
|
||||
$registry->has('foo')->willReturn(false);
|
||||
|
||||
$this->assignStorageType(new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$attribute->getWrappedObject(),
|
||||
));
|
||||
}
|
||||
|
||||
function it_sets_storage_type_based_on_set_attribute_type(
|
||||
ServiceRegistryInterface $registry,
|
||||
HttpKernelInterface $kernel,
|
||||
Request $request,
|
||||
AttributeInterface $attribute,
|
||||
AttributeTypeInterface $attributeType,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_POST);
|
||||
$attribute->getType()->willReturn('foo');
|
||||
$attribute->getStorageType()->willReturn(null);
|
||||
|
||||
$registry->has('foo')->willReturn(true);
|
||||
$registry->get('foo')->willReturn($attributeType);
|
||||
|
||||
$attributeType->getStorageType()->willReturn('bar');
|
||||
|
||||
$attribute->setStorageType('bar')->shouldBeCalled();
|
||||
|
||||
$this->assignStorageType(new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$attribute->getWrappedObject(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue