mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
[API][Admin] Add DELETE endpoint for product variant resource
This commit is contained in:
parent
1bbfc60b7d
commit
98a7e3cab2
9 changed files with 231 additions and 0 deletions
|
|
@ -0,0 +1,49 @@
|
|||
<?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 Sylius\Bundle\ApiBundle\DataPersister;
|
||||
|
||||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
|
||||
use Sylius\Bundle\ApiBundle\Exception\ProductVariantCannotBeRemoved;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductVariantDataPersister implements ContextAwareDataPersisterInterface
|
||||
{
|
||||
public function __construct(private ContextAwareDataPersisterInterface $decoratedDataPersister)
|
||||
{
|
||||
}
|
||||
|
||||
/** @param array<mixed> $context */
|
||||
public function supports($data, array $context = []): bool
|
||||
{
|
||||
return $data instanceof ProductVariantInterface;
|
||||
}
|
||||
|
||||
/** @param array<mixed> $context */
|
||||
public function persist($data, array $context = [])
|
||||
{
|
||||
return $this->decoratedDataPersister->persist($data, $context);
|
||||
}
|
||||
|
||||
/** @param array<mixed> $context */
|
||||
public function remove($data, array $context = [])
|
||||
{
|
||||
try {
|
||||
return $this->decoratedDataPersister->remove($data, $context);
|
||||
} catch (ForeignKeyConstraintViolationException) {
|
||||
throw new ProductVariantCannotBeRemoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?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 Sylius\Bundle\ApiBundle\Exception;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductVariantCannotBeRemoved extends \RuntimeException
|
||||
{
|
||||
public function __construct(
|
||||
string $message = 'Cannot delete, the product variant is in use.',
|
||||
int $code = 0,
|
||||
\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,11 @@
|
|||
<attribute name="groups">shop:product_variant:read</attribute>
|
||||
</attribute>
|
||||
</itemOperation>
|
||||
|
||||
<itemOperation name="admin_delete">
|
||||
<attribute name="method">DELETE</attribute>
|
||||
<attribute name="path">/admin/product-variants/{code}</attribute>
|
||||
</itemOperation>
|
||||
</itemOperations>
|
||||
|
||||
<collectionOperations>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ api_platform:
|
|||
Sylius\Bundle\ApiBundle\Exception\OrderNoLongerEligibleForPromotion: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ProductAttributeCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ProductCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ProductVariantCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ProvinceCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ShippingMethodCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\TaxonCannotBeRemoved: 422
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@
|
|||
<tag name="api_platform.data_persister" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\ProductVariantDataPersister">
|
||||
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
|
||||
<tag name="api_platform.data_persister" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\ZoneDataPersister">
|
||||
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
|
||||
<argument type="service" id="Sylius\Component\Addressing\Checker\ZoneDeletionCheckerInterface" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
<?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\DataPersister;
|
||||
|
||||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Exception\ProductVariantCannotBeRemoved;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
|
||||
final class ProductVariantDataPersisterSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ContextAwareDataPersisterInterface $dataPersister): void
|
||||
{
|
||||
$this->beConstructedWith($dataPersister);
|
||||
}
|
||||
|
||||
function it_is_a_context_aware_persister(): void
|
||||
{
|
||||
$this->shouldImplement(ContextAwareDataPersisterInterface::class);
|
||||
}
|
||||
|
||||
function it_supports_only_product_variant(ProductVariantInterface $productVariant): void
|
||||
{
|
||||
$this->supports(new \stdClass())->shouldReturn(false);
|
||||
$this->supports($productVariant)->shouldReturn(true);
|
||||
}
|
||||
|
||||
function it_uses_inner_persister_to_persist_product_variant(
|
||||
ContextAwareDataPersisterInterface $dataPersister,
|
||||
ProductVariantInterface $productVariant,
|
||||
): void {
|
||||
$dataPersister->persist($productVariant, [])->shouldBeCalled();
|
||||
|
||||
$this->persist($productVariant);
|
||||
}
|
||||
|
||||
function it_throws_cannot_be_removed_exception_if_constraint_fails_on_removal(
|
||||
ContextAwareDataPersisterInterface $dataPersister,
|
||||
ProductVariantInterface $productVariant,
|
||||
): void {
|
||||
$dataPersister->remove($productVariant, [])->willThrow(ForeignKeyConstraintViolationException::class);
|
||||
|
||||
$this->shouldThrow(ProductVariantCannotBeRemoved::class)->during('remove', [$productVariant]);
|
||||
}
|
||||
|
||||
function it_uses_inner_persister_to_remove_product_variant(
|
||||
ContextAwareDataPersisterInterface $dataPersister,
|
||||
ProductVariantInterface $productVariant,
|
||||
): void {
|
||||
$dataPersister->remove($productVariant, [])->shouldBeCalled();
|
||||
|
||||
$this->remove($productVariant);
|
||||
}
|
||||
}
|
||||
|
|
@ -395,4 +395,56 @@ final class ProductVariantsTest extends JsonApiTestCase
|
|||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_deletes_the_product_variant(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'authentication/api_administrator.yaml',
|
||||
'channel.yaml',
|
||||
'tax_category.yaml',
|
||||
'shipping_category.yaml',
|
||||
'product/product_variant.yaml',
|
||||
]);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
/** @var ProductVariantInterface $productVariant */
|
||||
$productVariant = $fixtures['product_variant_2'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'DELETE',
|
||||
uri: sprintf('/api/v2/admin/product-variants/%s', $productVariant->getCode()),
|
||||
server: $header,
|
||||
);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_delete_the_product_variant_in_use(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'authentication/api_administrator.yaml',
|
||||
'channel.yaml',
|
||||
'tax_category.yaml',
|
||||
'shipping_category.yaml',
|
||||
'product/product_variant.yaml',
|
||||
]);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
/** @var ProductVariantInterface $productVariant */
|
||||
$productVariant = $fixtures['product_variant'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'DELETE',
|
||||
uri: sprintf('/api/v2/admin/product-variants/%s', $productVariant->getCode()),
|
||||
server: $header,
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/product_variant/delete_product_variant_in_use_response',
|
||||
Response::HTTP_UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,3 +95,24 @@ Sylius\Component\Product\Model\ProductOptionValueTranslation:
|
|||
locale: 'en_US'
|
||||
value: 'Red'
|
||||
translatable: '@product_option_value_color_red'
|
||||
|
||||
Sylius\Component\Core\Model\Customer:
|
||||
customer:
|
||||
firstName: 'John'
|
||||
lastName: 'Doe'
|
||||
email: 'john.doe@example.com'
|
||||
emailCanonical: 'john.doe@example.com'
|
||||
|
||||
Sylius\Component\Core\Model\Order:
|
||||
cart:
|
||||
channel: '@channel_web'
|
||||
items: ['@order_item']
|
||||
currencyCode: 'USD'
|
||||
localeCode: 'en_US'
|
||||
customer: '@customer'
|
||||
state: 'cart'
|
||||
|
||||
Sylius\Component\Core\Model\OrderItem:
|
||||
order_item:
|
||||
variant: '@product_variant'
|
||||
order: '@cart'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"@context": "\/api\/v2\/contexts\/Error",
|
||||
"@type": "hydra:Error",
|
||||
"hydra:title": "An error occurred",
|
||||
"hydra:description": "Cannot delete, the product variant is in use."
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue