diff --git a/Controller/Content/ContentController.php b/Controller/Content/ContentController.php index 22f3a96d..2f1554f5 100644 --- a/Controller/Content/ContentController.php +++ b/Controller/Content/ContentController.php @@ -23,6 +23,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\MessageBusInterface; +use Webmozart\Assert\Assert; abstract class ContentController implements ClassResourceInterface { @@ -58,7 +59,7 @@ public function getAction(Request $request, string $id): Response { $content = null; try { - $message = new FindContentQuery($this->getResourceKey(), $id, $request->query->get('locale')); + $message = new FindContentQuery($this->getResourceKey(), $id, $this->getLocale($request)); $this->messageBus->dispatch($message); $content = $message->getContent(); } catch (HandlerFailedException $exception) { @@ -81,7 +82,7 @@ public function putAction(Request $request, string $resourceId): Response 'data' => $data, ]; - $locale = $request->query->get('locale'); + $locale = $this->getLocale($request); $message = new ModifyContentMessage($this->getResourceKey(), $resourceId, $locale, $payload); $this->messageBus->dispatch($message); @@ -107,4 +108,12 @@ protected function handleAction(string $resourceId, string $locale, string $acti abstract protected function handlePublish(string $resourceId, string $locale): void; abstract protected function getResourceKey(): string; + + public function getLocale(Request $request): string + { + $locale = $request->query->get('locale'); + Assert::notNull($locale); + + return $locale; + } } diff --git a/Controller/Product/ProductController.php b/Controller/Product/ProductController.php index 0214743d..b7de5c0e 100644 --- a/Controller/Product/ProductController.php +++ b/Controller/Product/ProductController.php @@ -24,6 +24,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\MessageBusInterface; +use Webmozart\Assert\Assert; class ProductController implements ClassResourceInterface, SecuredControllerInterface { @@ -78,8 +79,11 @@ public function getSecurityContext() return SyliusConsumerAdmin::PRODUCT_SECURITY_CONTEXT; } - public function getLocale(Request $request) + public function getLocale(Request $request): string { - return $request->query->get('locale'); + $locale = $request->query->get('locale'); + Assert::notNull($locale); + + return $locale; } } diff --git a/Gateway/ProductVariantChannelPricingGateway.php b/Gateway/ProductVariantGateway.php similarity index 74% rename from Gateway/ProductVariantChannelPricingGateway.php rename to Gateway/ProductVariantGateway.php index da09bdef..93a3d3c6 100644 --- a/Gateway/ProductVariantChannelPricingGateway.php +++ b/Gateway/ProductVariantGateway.php @@ -13,7 +13,7 @@ namespace Sulu\Bundle\SyliusConsumerBundle\Gateway; -class ProductVariantChannelPricingGateway extends AbstractGateway implements ProductVariantChannelPricingGatewayInterface +class ProductVariantGateway extends AbstractGateway implements ProductVariantGatewayInterface { const URI = '/api/v1/products/{PRODUCT_ID}/variants/'; @@ -27,8 +27,7 @@ public function findByCodeAndVariantCode(string $code, string $variantCode): arr if (200 !== $response->getStatusCode()) { $this->handleErrors($response); } - $data = json_decode($response->getBody()->getContents(), true); - return $data['channelPricings']; + return json_decode($response->getBody()->getContents(), true); } } diff --git a/Gateway/ProductVariantChannelPricingGatewayInterface.php b/Gateway/ProductVariantGatewayInterface.php similarity index 87% rename from Gateway/ProductVariantChannelPricingGatewayInterface.php rename to Gateway/ProductVariantGatewayInterface.php index a345c362..55501dd1 100644 --- a/Gateway/ProductVariantChannelPricingGatewayInterface.php +++ b/Gateway/ProductVariantGatewayInterface.php @@ -13,7 +13,7 @@ namespace Sulu\Bundle\SyliusConsumerBundle\Gateway; -interface ProductVariantChannelPricingGatewayInterface +interface ProductVariantGatewayInterface { public function findByCodeAndVariantCode(string $code, string $variantCode): array; } diff --git a/Mail/MailFactory.php b/Mail/MailFactory.php index 54aef1a6..8d2becdb 100644 --- a/Mail/MailFactory.php +++ b/Mail/MailFactory.php @@ -14,8 +14,8 @@ namespace Sulu\Bundle\SyliusConsumerBundle\Mail; use Sulu\Bundle\SyliusConsumerBundle\Model\Customer\CustomerInterface; -use Symfony\Component\Templating\EngineInterface; use Symfony\Component\Translation\TranslatorInterface; +use Twig\Environment; class MailFactory { @@ -25,9 +25,9 @@ class MailFactory protected $mailer; /** - * @var EngineInterface + * @var Environment */ - protected $engine; + protected $twig; /** * @var TranslatorInterface @@ -41,12 +41,12 @@ class MailFactory public function __construct( \Swift_Mailer $mailer, - EngineInterface $engine, + Environment $twig, TranslatorInterface $translator, array $sender ) { $this->mailer = $mailer; - $this->engine = $engine; + $this->twig = $twig; $this->translator = $translator; $this->sender = $sender; } @@ -60,7 +60,7 @@ public function sendVerifyEmail(CustomerInterface $customer): void $this->sendEmail( [$customer->getEmail() => $customer->getFullName()], 'sulu_sylius.email_customer_verify.subject', - 'SuluSyliusConsumerBundle:Email:customer-verify.html.twig', + '@SuluSyliusConsumer/Email/customer-verify.html.twig', [ 'customer' => $customer, 'token' => $customer->getUser()->getToken(), @@ -73,7 +73,7 @@ public function sendOrderConfirmationEmail(CustomerInterface $customer, array $o $this->sendEmail( [$customer->getEmail() => $customer->getFullName()], 'sulu_sylius.email_order-confirmation.subject', - 'SuluSyliusConsumerBundle:Email:order-confirmation.html.twig', + '@SuluSyliusConsumer/Email/order-confirmation.html.twig', [ 'customer' => $customer, 'order' => $order, @@ -97,7 +97,7 @@ protected function sendEmail( $this->translator->setLocale($locale); } - $body = $this->engine->render($template, $data); + $body = $this->twig->render($template, $data); $message = new \Swift_Message(); $message->setSubject($this->translator->trans($subject)); diff --git a/Model/Product/Handler/Query/LoadProductVariantChannelPricingQueryHandler.php b/Model/Product/Handler/Query/LoadProductVariantChannelPricingQueryHandler.php index 2ca2d41f..2366b28c 100644 --- a/Model/Product/Handler/Query/LoadProductVariantChannelPricingQueryHandler.php +++ b/Model/Product/Handler/Query/LoadProductVariantChannelPricingQueryHandler.php @@ -13,26 +13,29 @@ namespace Sulu\Bundle\SyliusConsumerBundle\Model\Product\Handler\Query; -use Sulu\Bundle\SyliusConsumerBundle\Gateway\ProductVariantChannelPricingGatewayInterface; +use Sulu\Bundle\SyliusConsumerBundle\Gateway\ProductVariantGatewayInterface; use Sulu\Bundle\SyliusConsumerBundle\Model\Product\Query\LoadProductVariantChannelPricingQuery; class LoadProductVariantChannelPricingQueryHandler { /** - * @var ProductVariantChannelPricingGatewayInterface + * @var ProductVariantGatewayInterface */ private $gateway; - public function __construct(ProductVariantChannelPricingGatewayInterface $productChannelPricingGateway) + public function __construct(ProductVariantGatewayInterface $productVariantGateway) { - $this->gateway = $productChannelPricingGateway; + $this->gateway = $productVariantGateway; } public function __invoke(LoadProductVariantChannelPricingQuery $query): void { - $channelPricings = $this->gateway->findByCodeAndVariantCode($query->getCode(), $query->getVariantCode()); + $variantData = $this->gateway->findByCodeAndVariantCode( + $query->getCode(), + $query->getVariantCode() + ); - foreach ($channelPricings as $channelPricing) { + foreach ($variantData['channelPricings'] as $channelPricing) { if ($query->getChannel() === $channelPricing['channelCode']) { $query->setPrice($channelPricing['price']); } diff --git a/Model/Product/Handler/Query/LoadProductVariantStockQueryHandler.php b/Model/Product/Handler/Query/LoadProductVariantStockQueryHandler.php new file mode 100644 index 00000000..19e38e42 --- /dev/null +++ b/Model/Product/Handler/Query/LoadProductVariantStockQueryHandler.php @@ -0,0 +1,41 @@ +gateway = $productVariantGateway; + } + + public function __invoke(LoadProductVariantStockQuery $query): void + { + $variantData = $this->gateway->findByCodeAndVariantCode( + $query->getCode(), + $query->getVariantCode() + ); + + $query->setOnHand($variantData['onHand']); + $query->setOnHold($variantData['onHold']); + } +} diff --git a/Model/Product/Query/LoadProductVariantStockQuery.php b/Model/Product/Query/LoadProductVariantStockQuery.php new file mode 100644 index 00000000..ea34a7e0 --- /dev/null +++ b/Model/Product/Query/LoadProductVariantStockQuery.php @@ -0,0 +1,77 @@ +code = $code; + $this->variantCode = $variantCode; + } + + public function getCode(): string + { + return $this->code; + } + + public function getVariantCode(): string + { + return $this->variantCode; + } + + public function getOnHold(): ?int + { + return $this->onHold; + } + + public function setOnHold(?int $onHold): self + { + $this->onHold = $onHold; + + return $this; + } + + public function getOnHand(): ?int + { + return $this->onHand; + } + + public function setOnHand(?int $onHand): self + { + $this->onHand = $onHand; + + return $this; + } +} diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 1000458a..61a2fb63 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -72,7 +72,7 @@ - + %sulu_sylius_consumer.mail_sender% diff --git a/Resources/config/services/gateway.xml b/Resources/config/services/gateway.xml index 2c403aef..038e2126 100644 --- a/Resources/config/services/gateway.xml +++ b/Resources/config/services/gateway.xml @@ -33,8 +33,8 @@ - + diff --git a/Resources/config/services/product-handler.xml b/Resources/config/services/product-handler.xml index a976f74e..c3ddb60c 100644 --- a/Resources/config/services/product-handler.xml +++ b/Resources/config/services/product-handler.xml @@ -138,7 +138,13 @@ - + + + + + + + diff --git a/Resources/views/Email/customer-verify.html.twig b/Resources/views/Email/customer-verify.html.twig index 0b6fa6c1..038a262e 100644 --- a/Resources/views/Email/customer-verify.html.twig +++ b/Resources/views/Email/customer-verify.html.twig @@ -1,6 +1,6 @@ -{% extends "SuluSyliusConsumerBundle:Email:master-email.html.twig" %} +{% extends "@SuluSyliusConsumer/Email/master-email.html.twig" %} {% block content %} {% set confirmUrl = url('sulu_sylius.customer.verify', { token: token }) %} {{ confirmUrl }} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/Resources/views/Email/order-confirmation.html.twig b/Resources/views/Email/order-confirmation.html.twig index c5dfd089..939023a8 100644 --- a/Resources/views/Email/order-confirmation.html.twig +++ b/Resources/views/Email/order-confirmation.html.twig @@ -1,4 +1,4 @@ -{% extends "SuluSyliusConsumerBundle:Email:master-email.html.twig" %} +{% extends "@SuluSyliusConsumer/Email/master-email.html.twig" %} {% block content %} {{ 'sulu_sylius.email_order-confirmation.body'|trans({'%orderId%': order.id})|raw }} diff --git a/Tests/Functional/Model/Product/Handler/SynchronizeProductTest.php b/Tests/Functional/Model/Product/Handler/SynchronizeProductTest.php index 8c58ed6e..3c9b551f 100644 --- a/Tests/Functional/Model/Product/Handler/SynchronizeProductTest.php +++ b/Tests/Functional/Model/Product/Handler/SynchronizeProductTest.php @@ -14,6 +14,7 @@ namespace Sulu\Bundle\SyliusConsumerBundle\Tests\Functional\Model\Product\Handler; use Sulu\Bundle\SyliusConsumerBundle\Model\Product\Message\SynchronizeProductMessage; +use Sulu\Bundle\SyliusConsumerBundle\Model\Product\ProductInformation; use Sulu\Bundle\SyliusConsumerBundle\Tests\Functional\Traits\DimensionTrait; use Sulu\Bundle\SyliusConsumerBundle\Tests\Functional\Traits\ProductInformationTrait; use Sulu\Bundle\TestBundle\Testing\SuluTestCase; @@ -41,6 +42,7 @@ public function testSynchronizeProductCreate() $messageBus->dispatch($message); + /** @var ProductInformation|null $result */ $result = $this->findProductInformationByCode(ExampleSynchronizeProductMessage::getCode(), 'de'); $this->assertNotNull($result); diff --git a/Tests/Functional/Traits/ProductInformationTrait.php b/Tests/Functional/Traits/ProductInformationTrait.php index 8eaee9c7..01f0ade9 100644 --- a/Tests/Functional/Traits/ProductInformationTrait.php +++ b/Tests/Functional/Traits/ProductInformationTrait.php @@ -17,6 +17,7 @@ use Sulu\Bundle\SyliusConsumerBundle\Model\Dimension\DimensionInterface; use Sulu\Bundle\SyliusConsumerBundle\Model\Product\Product; use Sulu\Bundle\SyliusConsumerBundle\Model\Product\ProductInformation; +use Sulu\Bundle\SyliusConsumerBundle\Model\Product\ProductInterface; trait ProductInformationTrait { @@ -29,8 +30,9 @@ protected function createProductInformation(string $productId, string $locale): ] ); + /** @var ProductInterface|null $product */ $product = $this->getEntityManager()->find(Product::class, $productId); - if (!$product) { + if (!$product instanceof ProductInterface) { throw new \RuntimeException('Product not fount'); } @@ -52,8 +54,9 @@ protected function createProductInformationLive(string $productId, string $local ] ); + /** @var ProductInterface|null $product */ $product = $this->getEntityManager()->find(Product::class, $productId); - if (!$product) { + if (!$product instanceof ProductInterface) { throw new \RuntimeException('Product not fount'); } @@ -75,10 +78,13 @@ protected function findProductInformation(string $id, string $locale): ?ProductI ] ); - return $this->getEntityManager()->find( + /** @var ProductInformation $productInformation */ + $productInformation = $this->getEntityManager()->find( ProductInformation::class, ['product' => $id, 'dimension' => $dimension] ); + + return $productInformation; } protected function findProductInformationByCode(string $code, string $locale): ?ProductInformation @@ -95,13 +101,16 @@ protected function findProductInformationByCode(string $code, string $locale): ? throw new \RuntimeException('Product not fount'); } - return $this->getEntityManager()->find( + /** @var ProductInformation $productInformation */ + $productInformation = $this->getEntityManager()->find( ProductInformation::class, [ 'product' => $product, 'dimension' => $dimension, ] ); + + return $productInformation; } abstract protected function findDimension(array $attributes): DimensionInterface; diff --git a/Tests/Functional/Traits/ProductTrait.php b/Tests/Functional/Traits/ProductTrait.php index 39b444c3..0425366d 100644 --- a/Tests/Functional/Traits/ProductTrait.php +++ b/Tests/Functional/Traits/ProductTrait.php @@ -31,7 +31,10 @@ protected function createProduct(string $code): Product protected function findProduct(string $code): ?Product { - return $this->getEntityManager()->find(Product::class, $code); + /** @var Product $product */ + $product = $this->getEntityManager()->find(Product::class, $code); + + return $product; } /** diff --git a/composer.json b/composer.json index c193e516..5b49003b 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "phpstan/phpstan": "^0.11", "phpstan/phpstan-doctrine": "^0.11", "phpstan/phpstan-symfony": "^0.11", + "phpstan/phpstan-webmozart-assert": "0.11.3", "phpunit/phpunit": "^8.2", "symfony/browser-kit": "^4.3", "symfony/dotenv": "^4.3", diff --git a/phpstan.neon b/phpstan.neon index 23e68a85..c54d597d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,6 +2,7 @@ includes: - vendor/jangregor/phpstan-prophecy/src/extension.neon - vendor/phpstan/phpstan-doctrine/extension.neon - vendor/phpstan/phpstan-symfony/extension.neon + - vendor/phpstan/phpstan-webmozart-assert/extension.neon parameters: level: 7 @@ -18,4 +19,4 @@ parameters: - %currentWorkingDirectory%/Tests/var/* - %currentWorkingDirectory%/Tests/Unit/EventSubscriber/ProductViewSerializerSubscriberTest.php symfony: - container_xml_path: %rootDir%/../../../Tests/Application/var/cache/admin/dev/adminAdminDevDebugProjectContainer.xml + container_xml_path: %rootDir%/../../../Tests/Application/var/cache/admin/dev/Sulu_Bundle_SyliusConsumerBundle_Tests_Application_KernelDevDebugContainer.xml