custom/plugins/WbfkBundles/src/Subscriber/AddBundleDataToProductPage.php line 102

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Wbfk\Bundles\Subscriber;
  3. use Shopware\Core\Content\Product\ProductCollection;
  4. use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
  5. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductCollection;
  6. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductDefinition;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  11. use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityLoadedEvent;
  12. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  13. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  16. use Wbfk\Bundles\Entity\Bundle\BundleProductCollection;
  17. use Wbfk\Bundles\Entity\Bundle\BundleProductEntity;
  18. use Wbfk\Bundles\Struct\ProductBundlesStruct;
  19. class AddBundleDataToProductPage implements EventSubscriberInterface
  20. {
  21. public function __construct(
  22. private EntityRepository $bundleProductRepository,
  23. private AbstractProductPriceCalculator $calculator,
  24. private EventDispatcherInterface $eventDispatcher,
  25. private SalesChannelProductDefinition $salesChannelProductDefinition
  26. )
  27. {
  28. }
  29. public static function getSubscribedEvents(): array
  30. {
  31. return [
  32. ProductPageLoadedEvent::class => 'addBundleDataToProductPage'
  33. ];
  34. }
  35. public function addBundleDataToProductPage(ProductPageLoadedEvent $event): void
  36. {
  37. $salesChannelContext = $event->getSalesChannelContext();
  38. /** @var ProductBundlesStruct $struct */
  39. $struct = new ProductBundlesStruct();
  40. $product = $event->getPage()->getProduct();
  41. if (!$product) {
  42. return;
  43. }
  44. $struct->setBundleChildren($this->getBundleChildren($product->getId(), $salesChannelContext));
  45. $struct->setBundleParents($this->setBundleParents($product->getId(), $salesChannelContext));
  46. $event->getPage()->addExtension('wbfkBundlesData', $struct);
  47. }
  48. public function getBundleChildren(string $productId, SalesChannelContext $salesChannelContext): BundleProductCollection
  49. {
  50. $context = $salesChannelContext->getContext();
  51. $criteria = new Criteria();
  52. $criteria->setTitle("Getting bundle products child products data");
  53. $criteria->addAssociation('salesChannelChildProduct');
  54. $criteria->addAssociation('salesChannelChildProduct.cover.media');
  55. $criteria->addSorting(new FieldSorting('salesChannelChildProduct.price.first.gross', 'DESC'));
  56. $criteria->addFilter(new EqualsFilter('productId', $productId));
  57. $criteria->addFilter(new EqualsFilter('childProduct.active', true));
  58. /** @var BundleProductCollection $bundleChildren */
  59. $bundleChildren = $this->bundleProductRepository->search($criteria, $context)->getEntities();
  60. $products = new SalesChannelProductCollection([]);
  61. /** @var BundleProductEntity $bundleChild */
  62. foreach ($bundleChildren as $bundleChild) {
  63. $products->add($bundleChild->getSalesChannelChildProduct());
  64. }
  65. $this->calculator->calculate($products, $salesChannelContext);
  66. $this->eventDispatcher->dispatch(new SalesChannelEntityLoadedEvent(
  67. $this->salesChannelProductDefinition,
  68. $products->getElements(),
  69. $salesChannelContext
  70. ), 'sales_channel.product.loaded');
  71. return $bundleChildren;
  72. }
  73. public function setBundleParents(string $productId, SalesChannelContext $salesChannelContext): BundleProductCollection
  74. {
  75. $context = $salesChannelContext->getContext();
  76. $criteria = new Criteria();
  77. $criteria->setTitle("Getting bundle products parent products data");
  78. $criteria->addAssociation('salesChannelProduct');
  79. $criteria->addAssociation('salesChannelChildProduct');
  80. $criteria->addSorting(new FieldSorting('salesChannelProduct.price.first.gross', 'ASC'));
  81. $criteria->addFilter(new EqualsFilter('childProduct.id', $productId));
  82. $criteria->addFilter(new EqualsFilter('product.active', true));
  83. /** @var BundleProductCollection $bundleParents */
  84. $bundleParents = $this->bundleProductRepository->search($criteria, $context)->getEntities();
  85. /** @var BundleProductEntity $bundleParent */
  86. foreach ($bundleParents as $bundleParent) {
  87. $bundleParent->setChildBundleProducts($this->getBundleChildren($bundleParent->getProductId(), $salesChannelContext));
  88. }
  89. $products = new ProductCollection([]);
  90. /** @var BundleProductEntity $bundleParent */
  91. foreach ($bundleParents as $bundleParent) {
  92. $products->add($bundleParent->getSalesChannelProduct());
  93. }
  94. $this->calculator->calculate($products, $salesChannelContext);
  95. return $bundleParents;
  96. }
  97. }