Skip to content

Commit 50be832

Browse files
committed
MC-16152: Login Only B2B breaks Page Builder preview
- Use emulated storefront route for preview in admin
1 parent a681d20 commit 50be832

File tree

7 files changed

+298
-3
lines changed

7 files changed

+298
-3
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\PageBuilder\Controller\Adminhtml\Stage;
10+
11+
use Magento\Framework\Controller\ResultFactory;
12+
use Magento\Framework\App\Action\HttpPostActionInterface;
13+
14+
/**
15+
* Preview controller to render blocks preview on Stage
16+
*
17+
* This isn't placed within the adminhtml folder as it has to extend from the front-end controllers app action to
18+
* ensure the content is rendered in the storefront scope.
19+
*
20+
* @api
21+
*/
22+
class Preview extends \Magento\Backend\App\Action implements HttpPostActionInterface
23+
{
24+
/**
25+
* @var \Magento\PageBuilder\Model\Stage\RendererPool
26+
*/
27+
private $rendererPool;
28+
29+
/**
30+
* @var \Magento\Framework\App\State
31+
*/
32+
private $appState;
33+
34+
/**
35+
* @var \Magento\Theme\Model\View\Design
36+
*/
37+
private $design;
38+
39+
/**
40+
* @var \Magento\Framework\View\Design\Theme\ThemeProviderInterface
41+
*/
42+
private $themeProvider;
43+
44+
/**
45+
* @var \Magento\Store\Model\StoreManagerInterface
46+
*/
47+
private $storeManager;
48+
49+
/**
50+
* @var \Magento\Framework\App\Config\ScopeConfigInterface
51+
*/
52+
private $scopeConfig;
53+
54+
/**
55+
* @var \Magento\Store\Model\App\Emulation
56+
*/
57+
private $emulation;
58+
59+
/**
60+
* @var \Magento\PageBuilder\Model\Stage\PreviewRegistry
61+
*/
62+
private $previewRegistry;
63+
64+
/**
65+
* @param \Magento\Backend\App\Action\Context $context
66+
* @param \Magento\PageBuilder\Model\Stage\RendererPool $rendererPool
67+
* @param \Magento\Store\Model\App\Emulation $emulation
68+
* @param \Magento\Framework\App\State $appState
69+
* @param \Magento\Theme\Model\View\Design $design
70+
* @param \Magento\PageBuilder\Model\Stage\PreviewRegistry $previewRegistry
71+
*/
72+
public function __construct(
73+
\Magento\Backend\App\Action\Context $context,
74+
\Magento\PageBuilder\Model\Stage\RendererPool $rendererPool,
75+
\Magento\Store\Model\App\Emulation $emulation,
76+
\Magento\Framework\App\State $appState,
77+
\Magento\Framework\View\DesignInterface $design,
78+
\Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider,
79+
\Magento\Store\Model\StoreManagerInterface $storeManager,
80+
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
81+
\Magento\PageBuilder\Model\Stage\PreviewRegistry $previewRegistry
82+
) {
83+
parent::__construct($context);
84+
85+
$this->rendererPool = $rendererPool;
86+
$this->emulation = $emulation;
87+
$this->appState = $appState;
88+
$this->design = $design;
89+
$this->themeProvider = $themeProvider;
90+
$this->storeManager = $storeManager;
91+
$this->scopeConfig = $scopeConfig;
92+
$this->previewRegistry = $previewRegistry;
93+
}
94+
95+
/**
96+
* Generates an HTML preview for the stage
97+
*
98+
* @return \Magento\Framework\Controller\ResultInterface
99+
*/
100+
public function execute()
101+
{
102+
$defaultStore = $this->storeManager->getDefaultStoreView();
103+
$this->previewRegistry->setIsPreview(true);
104+
$this->emulation->startEnvironmentEmulation($defaultStore->getId());
105+
106+
return $this->appState->emulateAreaCode(
107+
$this->previewRegistry->getPreviewArea(),
108+
function () {
109+
$themeId = $this->scopeConfig->getValue(
110+
'design/theme/theme_id',
111+
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
112+
);
113+
$theme = $this->themeProvider->getThemeById($themeId);
114+
$this->design->setDesignTheme($theme, $this->previewRegistry->getPreviewArea());
115+
116+
$pageResult = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
117+
// Some template filters and directive processors expect this to be called in order to function.
118+
$pageResult->initLayout();
119+
120+
$params = $this->getRequest()->getParams();
121+
$renderer = $this->rendererPool->getRenderer($params['role']);
122+
$result = ['data' => $renderer->render($params)];
123+
124+
$response = $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
125+
$this->emulation->stopEnvironmentEmulation();
126+
$this->previewRegistry->setIsPreview(false);
127+
return $response;
128+
}
129+
);
130+
}
131+
}

app/code/Magento/PageBuilder/Controller/ContentType/Preview.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* This isn't placed within the adminhtml folder as it has to extend from the front-end controllers app action to
1818
* ensure the content is rendered in the storefront scope.
1919
*
20+
* @deprecated use \Magento\PageBuilder\Controller\Adminhtml\Stage\Preview
21+
*
2022
* @api
2123
*/
2224
class Preview extends \Magento\Framework\App\Action\Action implements HttpPostActionInterface

app/code/Magento/PageBuilder/Model/Stage/Config.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,7 @@ public function getConfig()
135135
'content_types' => $this->getContentTypes(),
136136
'stage_config' => $this->data,
137137
'media_url' => $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]),
138-
'preview_url' => $this->frontendUrlBuilder
139-
->addSessionParam()
140-
->getUrl('pagebuilder/contenttype/preview'),
138+
'preview_url' => $this->urlBuilder->getUrl('pagebuilder/stage/preview'),
141139
'render_url' => $this->urlBuilder->getUrl('pagebuilder/stage/render'),
142140
'column_grid_default' => $this->scopeConfig->getValue(self::XML_PATH_COLUMN_GRID_DEFAULT),
143141
'column_grid_max' => $this->scopeConfig->getValue(self::XML_PATH_COLUMN_GRID_MAX),
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\PageBuilder\Model\Stage;
9+
10+
/**
11+
* PreviewRegistry to determine if Page Builder is in preview mode
12+
*/
13+
class PreviewRegistry
14+
{
15+
/**
16+
* @var bool
17+
*/
18+
private $isPreview;
19+
20+
/**
21+
* Retrieve the area in which the preview needs to be ran in
22+
*
23+
* @return string
24+
*/
25+
public function getPreviewArea()
26+
{
27+
return \Magento\Framework\App\Area::AREA_FRONTEND;
28+
}
29+
30+
/**
31+
* Set if the system is in Page Builder preview mode
32+
*
33+
* @param bool $isPreview
34+
*/
35+
public function setIsPreview(bool $isPreview)
36+
{
37+
$this->isPreview = $isPreview;
38+
}
39+
40+
/**
41+
* Determine if the system is in preview mode
42+
*
43+
* @return bool
44+
*/
45+
public function getIsPreview()
46+
{
47+
return $this->isPreview;
48+
}
49+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\PageBuilder\Plugin;
9+
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Framework\Message\MessageInterface;
12+
13+
/**
14+
* Load necessary design files for GraphQL
15+
*/
16+
class DesignLoader
17+
{
18+
/**
19+
* @var \Magento\Framework\View\DesignLoader
20+
*/
21+
private $designLoader;
22+
23+
/**
24+
* @var \Magento\Framework\Message\ManagerInterface
25+
*/
26+
private $messageManager;
27+
28+
/**
29+
* @var \Magento\Framework\App\State
30+
*/
31+
private $appState;
32+
33+
/**
34+
* @var \Magento\PageBuilder\Model\Stage\PreviewRegistry
35+
*/
36+
private $previewRegistry;
37+
38+
/**
39+
* @param \Magento\Framework\View\DesignLoader $designLoader
40+
* @param \Magento\Framework\Message\ManagerInterface $messageManager
41+
* @param \Magento\Framework\App\State $appState
42+
* @param \Magento\PageBuilder\Model\Stage\PreviewRegistry $previewRegistry
43+
*/
44+
public function __construct(
45+
\Magento\Framework\View\DesignLoader $designLoader,
46+
\Magento\Framework\Message\ManagerInterface $messageManager,
47+
\Magento\Framework\App\State $appState,
48+
\Magento\PageBuilder\Model\Stage\PreviewRegistry $previewRegistry
49+
) {
50+
$this->designLoader = $designLoader;
51+
$this->messageManager = $messageManager;
52+
$this->appState = $appState;
53+
$this->previewRegistry = $previewRegistry;
54+
}
55+
56+
/**
57+
* Before create load the design files
58+
*
59+
* @param \Magento\Catalog\Block\Product\ImageFactory $subject
60+
* @param Product $product
61+
* @param string $imageId
62+
* @param array|null $attributes
63+
* @throws \Exception
64+
*
65+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
66+
*/
67+
public function beforeCreate(
68+
\Magento\Catalog\Block\Product\ImageFactory $subject,
69+
Product $product,
70+
string $imageId,
71+
array $attributes = null
72+
) {
73+
if ($this->previewRegistry->getIsPreview()) {
74+
$this->appState->emulateAreaCode(
75+
$this->previewRegistry->getPreviewArea(),
76+
[$this, 'loadDesignConfig']
77+
);
78+
}
79+
}
80+
81+
/**
82+
* Load the design config
83+
*/
84+
public function loadDesignConfig()
85+
{
86+
try {
87+
$this->designLoader->load();
88+
} catch (\Magento\Framework\Exception\LocalizedException $e) {
89+
if ($e->getPrevious() instanceof \Magento\Framework\Config\Dom\ValidationException) {
90+
/** @var MessageInterface $message */
91+
$message = $this->messageManager
92+
->createMessage(MessageInterface::TYPE_ERROR)
93+
->setText($e->getMessage());
94+
$this->messageManager->addUniqueMessages([$message]);
95+
}
96+
}
97+
}
98+
}

app/code/Magento/PageBuilder/etc/adminhtml/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\Catalog\Block\Product\ImageFactory">
10+
<plugin name="designLoader" type="Magento\PageBuilder\Plugin\DesignLoader" />
11+
</type>
912
<virtualType name="Magento\PageBuilder\Block\Adminhtml\ContentType\Edit\ModalCloseButton" type="Magento\PageBuilder\Block\Adminhtml\ContentType\Edit\CloseButton">
1013
<arguments>
1114
<argument name="targetName" xsi:type="string">ns = pagebuilder_modal_form, index = modal</argument>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
9+
<body>
10+
<referenceContainer name="content">
11+
<block class="Magento\Framework\View\Element\FormKey" name="formkey"/>
12+
</referenceContainer>
13+
</body>
14+
</page>

0 commit comments

Comments
 (0)