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

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 $a, CmsSectionEntity $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 $a, CmsBlockEntity $b) {
  64. return $a->getPosition() <=> $b->getPosition();
  65. });
  66. foreach ($section->getBlocks() as $block) {
  67. $block->getSlots()->sort(function (CmsSlotEntity $a, CmsSlotEntity $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 $page, ResolverContext $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. }