vendor/store.shopware.com/dreisccmspro/src/Subscriber/CmsEvents/ParentBlockIdRepairerSubscriber.php line 59

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace DreiscCmsPro\Subscriber\CmsEvents;
  3. use DreiscCmsPro\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockRepository;
  4. use DreiscCmsPro\Core\Content\Cms\CmsPageRepository;
  5. use DreiscCmsPro\DreiscCmsPro;
  6. use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockEntity;
  7. use Shopware\Core\Content\Cms\Aggregate\CmsSection\CmsSectionEntity;
  8. use Shopware\Core\Content\Cms\CmsPageEntity;
  9. use Shopware\Core\Framework\Context;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. class ParentBlockIdRepairerSubscriber implements EventSubscriberInterface
  17. {
  18.     /**
  19.      * @var array
  20.      */
  21.     protected static $repairerInProgress = [];
  22.     /**
  23.      * @var CmsPageRepository
  24.      */
  25.     protected $cmsPageRepository;
  26.     /**
  27.      * @var CmsBlockRepository
  28.      */
  29.     protected $cmsBlockRepository;
  30.     /**
  31.      * @param CmsPageRepository $cmsPageRepository
  32.      * @param CmsBlockRepository $cmsBlockRepository
  33.      */
  34.     public function __construct(CmsPageRepository $cmsPageRepositoryCmsBlockRepository $cmsBlockRepository)
  35.     {
  36.         $this->cmsPageRepository $cmsPageRepository;
  37.         $this->cmsBlockRepository $cmsBlockRepository;
  38.     }
  39.     public static function getSubscribedEvents()
  40.     {
  41.         return [
  42.             EntityWrittenContainerEvent::class => 'onEntityWrittenContainerEvent'
  43.         ];
  44.     }
  45.     /**
  46.      * See also:
  47.      * @see DreiscCmsPro::activate()
  48.      * @see DreiscCmsPro::postUpdate()
  49.      */
  50.     public function onEntityWrittenContainerEvent(EntityWrittenContainerEvent $entityWrittenContainerEvent)
  51.     {
  52.         /** cms_page */
  53.         $cmsPageEntityWrittenEvent $entityWrittenContainerEvent->getEventByEntityName('cms_page');
  54.         if(null !== $cmsPageEntityWrittenEvent) {
  55.             foreach($cmsPageEntityWrittenEvent->getWriteResults() as $writeResult) {
  56.                 $operation $writeResult->getOperation();
  57.                 if (in_array($operation, ['insert''update'])) {
  58.                     $primaryKey $writeResult->getPrimaryKey();
  59.                     if (is_array($primaryKey)) {
  60.                         foreach($primaryKey as $key) {
  61.                             $this->handleCmsPage($key$operation);
  62.                         }
  63.                     } else {
  64.                         $this->handleCmsPage($primaryKey$operation);
  65.                     }
  66.                 }
  67.             }
  68.         }
  69.     }
  70.     private function handleCmsPage(string $clonedCmsPageIdstring $operation)
  71.     {
  72.         /**
  73.          * Since we are also updating the cms_page entity in the updateCmsPageParentBlockIds method,
  74.          * we need to make sure that we are not creating a loop.
  75.          */
  76.         if (in_array($clonedCmsPageIdself::$repairerInProgress)) {
  77.             return;
  78.         }
  79.         self::$repairerInProgress[$clonedCmsPageId] = $clonedCmsPageId;
  80.         
  81.         /** Load the original and cloned cms page */
  82.         $clonedCmsPage $this->getWithAssociations($clonedCmsPageId);
  83.         if ('insert' === $operation) {
  84.             /**
  85.              * At first, we set the parent block id to the right ids
  86.              *
  87.              * This only in an insert operation. For a duplication of the selection, the correct values are already set via JavaScript.
  88.              * Executing the updateCmsPageParentBlockIds method would destroy the construct in this case.
  89.              */
  90.             $this->updateCmsPageParentBlockIds($clonedCmsPage);
  91.         }
  92.         
  93.         /** Next, we correct the stored block ids */
  94.         $this->setCmsPageBlockIds($clonedCmsPage);
  95.         unset(self::$repairerInProgress[$clonedCmsPageId]);
  96.     }
  97.     /**
  98.      * @param CmsPageEntity|null $clonedCmsPage
  99.      * @return array
  100.      */
  101.     private function updateCmsPageParentBlockIds(?CmsPageEntity $clonedCmsPage): void
  102.     {
  103.         /** @var CmsSectionEntity $clonedSection */
  104.         foreach ($clonedCmsPage->getSections() as $clonedSection) {
  105.             /** @var CmsBlockEntity $clonedBlock */
  106.             foreach ($clonedSection->getBlocks() as $clonedBlock) {
  107.                 $customFields $clonedBlock->getCustomFields();
  108.                 if (null !== $customFields && !empty($customFields['dreisc_cms_parent_block_id'])) {
  109.                     /** Fetching the referenced cms parent block */
  110.                     /** @var CmsBlockEntity $referencedBlockEntity */
  111.                     $referencedBlockEntity $this->cmsBlockRepository->get($customFields['dreisc_cms_parent_block_id']);
  112.                     /** Fetch the cloned parent block */
  113.                     /** We can identify the block by the fact that the block id stored in the custom fields does not match the actual id. */
  114.                     $criteria = new Criteria();
  115.                     $criteria->addFilter(
  116.                         new MultiFilter(
  117.                             MultiFilter::CONNECTION_AND,
  118.                             [
  119.                                 new EqualsFilter('customFields.dreisc_cms_block_id'$referencedBlockEntity->getId()),
  120.                                 new NotFilter(
  121.                                     NotFilter::CONNECTION_AND,
  122.                                     [
  123.                                         new EqualsFilter('id'$referencedBlockEntity->getId())
  124.                                     ]
  125.                                 )
  126.                             ]
  127.                         )
  128.                     );
  129.                     /** @var CmsBlockEntity $clonedParentBlock */
  130.                     $clonedParentBlock $this->cmsBlockRepository->search($criteria)->first();
  131.                     if (null !== $clonedParentBlock) {
  132.                         $this->cmsBlockRepository->update([[
  133.                             'id' => $clonedBlock->getId(),
  134.                             'customFields' => [
  135.                                 'dreisc_cms_parent_block_id' => $clonedParentBlock->getId()
  136.                             ]
  137.                         ]]);
  138.                     }
  139.                 }
  140.             }
  141.         }
  142.     }
  143.     /**
  144.      * @param CmsPageEntity|null $clonedCmsPage
  145.      * @return array
  146.      */
  147.     public function setCmsPageBlockIds(?CmsPageEntity $clonedCmsPage): void
  148.     {
  149.         /** @var CmsSectionEntity $clonedSection */
  150.         foreach ($clonedCmsPage->getSections() as $clonedSection) {
  151.             /** @var CmsBlockEntity $clonedBlock */
  152.             foreach ($clonedSection->getBlocks() as $clonedBlock) {
  153.                 $this->cmsBlockRepository->update([[
  154.                     'id' => $clonedBlock->getId(),
  155.                     'customFields' => [
  156.                         'dreisc_cms_block_id' => $clonedBlock->getId()
  157.                     ]
  158.                 ]]);
  159.             }
  160.         }
  161.     }
  162.     private function getWithAssociations($id): ?CmsPageEntity
  163.     {
  164.         $criteria = new Criteria([ $id ]);
  165.         $criteria->addAssociations([
  166.             'sections',
  167.             'sections.blocks'
  168.         ]);
  169.         return $this->cmsPageRepository->search(
  170.             $criteria,
  171.             Context::createDefaultContext()
  172.         )->first();
  173.     }
  174. }