vendor/shopware/core/Content/Cms/SalesChannel/SalesChannelCmsPageLoader.php line 43

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Cms\SalesChannel;
  3. use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockEntity;
  4. use Shopware\Core\Content\Cms\Aggregate\CmsSection\CmsSectionEntity;
  5. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
  6. use Shopware\Core\Content\Cms\CmsPageEntity;
  7. use Shopware\Core\Content\Cms\DataResolver\CmsSlotsDataResolver;
  8. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
  9. use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
  10. use Shopware\Core\Content\Cms\Events\CmsPageLoaderCriteriaEvent;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  14. use Shopware\Core\Framework\Log\Package;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  17. use Symfony\Component\HttpFoundation\Request;
  18. #[Package('content')]
  19. class SalesChannelCmsPageLoader implements SalesChannelCmsPageLoaderInterface
  20. {
  21.     private EntityRepositoryInterface $cmsPageRepository;
  22.     private CmsSlotsDataResolver $slotDataResolver;
  23.     private EventDispatcherInterface $eventDispatcher;
  24.     /**
  25.      * @internal
  26.      */
  27.     public function __construct(
  28.         EntityRepositoryInterface $cmsPageRepository,
  29.         CmsSlotsDataResolver $slotDataResolver,
  30.         EventDispatcherInterface $eventDispatcher
  31.     ) {
  32.         $this->cmsPageRepository $cmsPageRepository;
  33.         $this->slotDataResolver $slotDataResolver;
  34.         $this->eventDispatcher $eventDispatcher;
  35.     }
  36.     public function load(
  37.         Request $request,
  38.         Criteria $criteria,
  39.         SalesChannelContext $context,
  40.         ?array $config null,
  41.         ?ResolverContext $resolverContext null
  42.     ): EntitySearchResult {
  43.         $this->eventDispatcher->dispatch(new CmsPageLoaderCriteriaEvent($request$criteria$context));
  44.         $config $config ?? [];
  45.         // ensure sections, blocks and slots are loaded, slots and blocks can be restricted by caller
  46.         $criteria->addAssociation('sections.backgroundMedia');
  47.         $criteria->addAssociation('sections.blocks.backgroundMedia');
  48.         $criteria->addAssociation('sections.blocks.slots');
  49.         // step 1, load cms pages with blocks and slots
  50.         $pages $this->cmsPageRepository->search($criteria$context->getContext());
  51.         foreach ($pages as $page) {
  52.             if ($page->getSections() === null) {
  53.                 continue;
  54.             }
  55.             $page->getSections()->sort(function (CmsSectionEntity $aCmsSectionEntity $b) {
  56.                 return $a->getPosition() <=> $b->getPosition();
  57.             });
  58.             if (!$resolverContext) {
  59.                 $resolverContext = new ResolverContext($context$request);
  60.             }
  61.             // step 2, sort blocks into sectionPositions
  62.             foreach ($page->getSections() as $section) {
  63.                 $section->getBlocks()->sort(function (CmsBlockEntity $aCmsBlockEntity $b) {
  64.                     return $a->getPosition() <=> $b->getPosition();
  65.                 });
  66.                 foreach ($section->getBlocks() as $block) {
  67.                     $block->getSlots()->sort(function (CmsSlotEntity $aCmsSlotEntity $b) {
  68.                         return $a->getSlot() <=> $b->getSlot();
  69.                     });
  70.                 }
  71.             }
  72.             // step 3, find config overwrite
  73.             $overwrite $config[$page->getId()] ?? $config;
  74.             // step 4, overwrite slot config
  75.             $this->overwriteSlotConfig($page$overwrite);
  76.             // step 5, resolve slot data
  77.             $this->loadSlotData($page$resolverContext);
  78.         }
  79.         $this->eventDispatcher->dispatch(new CmsPageLoadedEvent($request$pages->getEntities(), $context));
  80.         return $pages;
  81.     }
  82.     private function loadSlotData(CmsPageEntity $pageResolverContext $resolverContext): void
  83.     {
  84.         $slots $this->slotDataResolver->resolve($page->getSections()->getBlocks()->getSlots(), $resolverContext);
  85.         $page->getSections()->getBlocks()->setSlots($slots);
  86.     }
  87.     private function overwriteSlotConfig(CmsPageEntity $page, array $config): void
  88.     {
  89.         foreach ($page->getSections()->getBlocks()->getSlots() as $slot) {
  90.             if ($slot->getConfig() === null && $slot->getTranslation('config') !== null) {
  91.                 $slot->setConfig($slot->getTranslation('config'));
  92.             }
  93.             if (empty($config)) {
  94.                 continue;
  95.             }
  96.             if (!isset($config[$slot->getId()])) {
  97.                 continue;
  98.             }
  99.             $defaultConfig $slot->getConfig() ?? [];
  100.             $merged array_replace_recursive(
  101.                 $defaultConfig,
  102.                 $config[$slot->getId()]
  103.             );
  104.             $slot->setConfig($merged);
  105.             $slot->addTranslated('config'$merged);
  106.         }
  107.     }
  108. }