vendor/ibexa/product-catalog/src/bundle/EventSubscriber/ProductFormSubscriber.php line 59

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. declare(strict_types=1);
  7. namespace Ibexa\Bundle\ProductCatalog\EventSubscriber;
  8. use Exception;
  9. use Ibexa\Bundle\ProductCatalog\Form\Data\AbstractProductData;
  10. use Ibexa\Bundle\ProductCatalog\Form\Data\ProductCreateData;
  11. use Ibexa\Bundle\ProductCatalog\Form\Data\ProductUpdateData;
  12. use Ibexa\Bundle\ProductCatalog\Form\Event\ProductFormEvents;
  13. use Ibexa\ContentForms\Event\FormActionEvent;
  14. use Ibexa\Contracts\AdminUi\Notification\TranslatableNotificationHandlerInterface;
  15. use Ibexa\Contracts\Core\Repository\Repository;
  16. use Ibexa\Contracts\ProductCatalog\Local\LocalProductServiceInterface;
  17. use Ibexa\Contracts\ProductCatalog\Values\ContentAwareProductInterface;
  18. use Ibexa\Contracts\ProductCatalog\Values\ProductInterface;
  19. use Ibexa\ProductCatalog\FieldType\ProductSpecification\Value as ProductSpecificationValue;
  20. use Ibexa\ProductCatalog\Tab\Product\TranslationsTab;
  21. use JMS\TranslationBundle\Annotation\Desc;
  22. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  23. use Symfony\Component\HttpFoundation\RedirectResponse;
  24. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  25. final class ProductFormSubscriber implements EventSubscriberInterface
  26. {
  27. private Repository $repository;
  28. private LocalProductServiceInterface $localProductService;
  29. private UrlGeneratorInterface $urlGenerator;
  30. private TranslatableNotificationHandlerInterface $notificationHandler;
  31. public function __construct(
  32. Repository $repository,
  33. LocalProductServiceInterface $localProductService,
  34. UrlGeneratorInterface $urlGenerator,
  35. TranslatableNotificationHandlerInterface $notificationHandler
  36. ) {
  37. $this->repository = $repository;
  38. $this->localProductService = $localProductService;
  39. $this->urlGenerator = $urlGenerator;
  40. $this->notificationHandler = $notificationHandler;
  41. }
  42. public static function getSubscribedEvents(): array
  43. {
  44. return [
  45. ProductFormEvents::PRODUCT_CREATE => ['onProductCreate', -255],
  46. ProductFormEvents::PRODUCT_UPDATE => ['onProductUpdate', -255],
  47. ];
  48. }
  49. public function onProductCreate(FormActionEvent $event): void
  50. {
  51. $form = $event->getForm();
  52. $data = $event->getData();
  53. if (!$data instanceof ProductCreateData) {
  54. return;
  55. }
  56. $languageCode = $form->getConfig()->getOption('languageCode');
  57. $createStruct = $this->localProductService->newProductCreateStruct(
  58. $data->getProductType(),
  59. $languageCode
  60. );
  61. $this->mapDataToStruct($createStruct, $data, $languageCode);
  62. $this->repository->beginTransaction();
  63. try {
  64. $product = $this->localProductService->createProduct($createStruct);
  65. $this->repository->commit();
  66. } catch (Exception $e) {
  67. $this->repository->rollback();
  68. throw $e;
  69. }
  70. $this->notificationHandler->success(
  71. /** @Desc("Product '%name%' created.") */
  72. 'product.create.success',
  73. ['%name%' => $product->getName()],
  74. 'ibexa_product_catalog'
  75. );
  76. $event->setResponse($this->createRedirectToProductView($product));
  77. }
  78. public function onProductUpdate(FormActionEvent $event): void
  79. {
  80. $form = $event->getForm();
  81. $data = $event->getData();
  82. if (!$data instanceof ProductUpdateData) {
  83. return;
  84. }
  85. $languageCode = $form->getConfig()->getOption('languageCode');
  86. $mainLanguageCode = $form->getConfig()->getOption('mainLanguageCode');
  87. $isTranslation = $languageCode !== $mainLanguageCode;
  88. $updateStruct = $this->localProductService->newProductUpdateStruct($data->getProduct());
  89. $updateStruct->getContentUpdateStruct()->initialLanguageCode = $languageCode;
  90. $this->mapDataToStruct($updateStruct, $data, $languageCode, $isTranslation);
  91. $this->repository->beginTransaction();
  92. try {
  93. $product = $this->localProductService->updateProduct($updateStruct);
  94. $this->repository->commit();
  95. } catch (Exception $e) {
  96. $this->repository->rollback();
  97. throw $e;
  98. }
  99. $this->notificationHandler->success(
  100. /** @Desc("Product '%name%' updated.") */
  101. 'product.update.success',
  102. ['%name%' => $product->getName()],
  103. 'ibexa_product_catalog'
  104. );
  105. $response = $this->createRedirectToProductView(
  106. $product,
  107. $isTranslation ? TranslationsTab::URI_FRAGMENT : null
  108. );
  109. $event->setResponse($response);
  110. }
  111. private function createRedirectToProductView(ProductInterface $product, ?string $fragment = null): RedirectResponse
  112. {
  113. $parameters = [
  114. 'productCode' => $product->getCode(),
  115. '_fragment' => $fragment,
  116. ];
  117. if ($product instanceof ContentAwareProductInterface) {
  118. $parameters['updatedContentId'] = $product->getContent()->id;
  119. }
  120. $redirectionUrl = $this->urlGenerator->generate(
  121. 'ibexa.product_catalog.product.view',
  122. $parameters,
  123. );
  124. return new RedirectResponse($redirectionUrl);
  125. }
  126. /**
  127. * @param \Ibexa\Contracts\ProductCatalog\Local\Values\Product\ProductCreateStruct|\Ibexa\Contracts\ProductCatalog\Local\Values\Product\ProductUpdateStruct $struct
  128. * @param \Ibexa\Bundle\ProductCatalog\Form\Data\AbstractProductData $data
  129. */
  130. private function mapDataToStruct(
  131. $struct,
  132. AbstractProductData $data,
  133. string $languageCode,
  134. bool $isTranslation = false
  135. ): void {
  136. $struct->setCode($data->getCode());
  137. foreach ($data->getFieldsData() as $fieldDefIdentifier => $fieldData) {
  138. if ($fieldData->value instanceof ProductSpecificationValue) {
  139. continue;
  140. }
  141. if ($isTranslation && !$fieldData->fieldDefinition->isTranslatable) {
  142. continue;
  143. }
  144. $struct->setField($fieldDefIdentifier, $fieldData->value, $languageCode);
  145. }
  146. if (!$isTranslation) {
  147. foreach ($data->getAttributes() as $attributeData) {
  148. $struct->setAttribute(
  149. $attributeData->getAttributeDefinition()->getIdentifier(),
  150. $attributeData->getValue()
  151. );
  152. }
  153. }
  154. }
  155. }