Skip to content

Commit 6ad9553

Browse files
committed
Fix loading custom page layouts in AJAX calls
1 parent 99b4ecc commit 6ad9553

2 files changed

Lines changed: 79 additions & 6 deletions

File tree

Util/Controller/LayoutLoader.php

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
use Loki\Components\Layout\LayoutHandlerComposite;
66
use Magento\Framework\View\Layout\BuilderFactory;
7+
use Magento\Framework\View\Layout\ProcessorInterface;
78
use Magento\Framework\View\LayoutFactory;
89
use Magento\Framework\View\LayoutInterface;
10+
use Magento\Framework\View\Model\PageLayout\Config\BuilderInterface as PageLayoutConfigBuilder;
911
use Magento\Framework\View\Page\Config as PageConfig;
1012
use Magento\Framework\View\Page\ConfigFactory as PageConfigFactory;
1113
use Magento\Framework\View\Page\Layout\Reader as PageLayoutReader;
@@ -20,22 +22,26 @@ public function __construct(
2022
private readonly PageConfig $pageConfig,
2123
private readonly PageConfigFactory $pageConfigFactory,
2224
private readonly PageLayoutReader $pageLayoutReader,
25+
private readonly PageLayoutConfigBuilder $pageLayoutConfigBuilder,
2326
) {
2427
}
2528

2629
public function load(array $handles = [], array $pageHandles = [], bool $isolated = false): LayoutInterface
2730
{
2831
if ($isolated) {
32+
$handles = $this->layoutHandlerComposite->getHandles($handles);
2933
$layout = $this->layoutFactory->create();
3034
$update = $layout->getUpdate();
31-
$update->addHandle('default');
3235

33-
$update->addPageHandles($pageHandles);
36+
$this->applyPageHandles($update, $pageHandles);
37+
38+
$update->addHandle('default');
3439
foreach ($handles as $handle) {
3540
$update->addHandle($this->sanitizeHandle($handle));
3641
}
3742

3843
$pageConfig = $this->pageConfigFactory->create(); // important: fresh instance
44+
$this->applyPageLayout($pageConfig, $pageHandles);
3945

4046
$builder = $this->layoutBuilderFactory->create(
4147
BuilderFactory::TYPE_PAGE,
@@ -53,12 +59,16 @@ public function load(array $handles = [], array $pageHandles = [], bool $isolate
5359

5460
$handles = $this->layoutHandlerComposite->getHandles($handles);
5561
$update = $this->layout->getUpdate();
56-
$update->addPageHandles($pageHandles);
5762

63+
$this->applyPageHandles($update, $pageHandles);
64+
65+
$update->addHandle('default');
5866
foreach ($handles as $handle) {
5967
$update->addHandle($this->sanitizeHandle($handle));
6068
}
6169

70+
$this->applyPageLayout($this->pageConfig, $pageHandles);
71+
6272
$builder = $this->layoutBuilderFactory->create(
6373
BuilderFactory::TYPE_PAGE,
6474
[
@@ -73,6 +83,38 @@ public function load(array $handles = [], array $pageHandles = [], bool $isolate
7383
return $this->layout;
7484
}
7585

86+
private function applyPageHandles(ProcessorInterface $update, array $pageHandles): void
87+
{
88+
if (empty($pageHandles)) {
89+
return;
90+
}
91+
92+
$update->addPageHandles($pageHandles);
93+
94+
$pageLayoutsConfig = $this->pageLayoutConfigBuilder->getPageLayoutsConfig();
95+
foreach ($pageHandles as $pageHandle) {
96+
$sanitized = $this->sanitizeHandle($pageHandle);
97+
if ($pageLayoutsConfig->hasPageLayout($sanitized)) {
98+
$update->addHandle($sanitized);
99+
}
100+
}
101+
}
102+
103+
private function applyPageLayout(PageConfig $pageConfig, array $pageHandles): void
104+
{
105+
if (empty($pageHandles)) {
106+
return;
107+
}
108+
109+
$pageLayoutsConfig = $this->pageLayoutConfigBuilder->getPageLayoutsConfig();
110+
foreach ($pageHandles as $pageHandle) {
111+
$sanitized = $this->sanitizeHandle($pageHandle);
112+
if ($pageLayoutsConfig->hasPageLayout($sanitized)) {
113+
$pageConfig->setPageLayout($sanitized);
114+
}
115+
}
116+
}
117+
76118
private function sanitizeHandle(string $handle): string
77119
{
78120
return preg_replace('/([^a-z0-9\-_]+)/', '', $handle);

Util/Controller/TargetRenderer.php

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,56 @@
77
use Magento\Framework\Event\Manager as EventManager;
88
use Magento\Framework\View\Element\AbstractBlock;
99
use Magento\Framework\View\LayoutInterface;
10+
use Magento\Framework\View\Model\PageLayout\Config\BuilderInterface as PageLayoutConfigBuilder;
1011

1112
class TargetRenderer
1213
{
1314
public function __construct(
1415
private readonly EventManager $eventManager,
1516
private readonly IdConvertor $idConvertor,
1617
private readonly LayoutHandlerComposite $layoutHandlerComposite,
17-
private readonly LayoutLoader $layoutLoader
18+
private readonly LayoutLoader $layoutLoader,
19+
private readonly PageLayoutConfigBuilder $pageLayoutConfigBuilder,
1820
) {
1921
}
2022

2123
public function render(LayoutInterface $originalLayout, array $targetNames, bool $isolated = false): array
2224
{
23-
$handles = $this->layoutHandlerComposite->getHandles($originalLayout->getUpdate()->getHandles());
24-
$newLayout = $this->layoutLoader->load($handles, [], $isolated);
25+
$originalUpdate = $originalLayout->getUpdate();
26+
$originalHandles = $originalUpdate->getHandles();
27+
$pageHandles = $this->extractPageHandles($originalUpdate, $originalHandles);
28+
$handles = $this->layoutHandlerComposite->getHandles(
29+
array_values(array_diff($originalHandles, $pageHandles))
30+
);
31+
$newLayout = $this->layoutLoader->load($handles, $pageHandles, $isolated);
2532

2633
return $this->renderBlocks($newLayout, $this->getTargetBlockNames($newLayout, $targetNames));
2734
}
2835

36+
private function extractPageHandles($update, array $originalHandles): array
37+
{
38+
$pageHandles = [];
39+
if (method_exists($update, 'getPageHandles')) {
40+
$pageHandles = (array)$update->getPageHandles();
41+
}
42+
if (method_exists($update, 'getPageLayout')) {
43+
$pageLayout = $update->getPageLayout();
44+
if ($pageLayout) {
45+
$pageHandles[] = $pageLayout;
46+
}
47+
}
48+
49+
// Detect page_layout names that were promoted into the handles list by LayoutLoader
50+
$pageLayoutsConfig = $this->pageLayoutConfigBuilder->getPageLayoutsConfig();
51+
foreach ($originalHandles as $handle) {
52+
if ($pageLayoutsConfig->hasPageLayout($handle)) {
53+
$pageHandles[] = $handle;
54+
}
55+
}
56+
57+
return array_values(array_unique(array_filter($pageHandles)));
58+
}
59+
2960
private function renderBlocks(LayoutInterface $layout, array $blockNames): array
3061
{
3162
$blocks = [];

0 commit comments

Comments
 (0)