Skip to content

Commit 6261152

Browse files
committed
Merge remote-tracking branch 'mainline/develop' into cms-team-1-delivery
# Conflicts: # app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderTabsSection.xml # app/code/Magento/PageBuilder/Test/Mftf/Test/AdminPageBuilderBlockTest.xml # app/code/Magento/PageBuilder/Test/Mftf/Test/AdminPageBuilderTabItemConfigurationTests.xml # app/code/Magento/PageBuilder/docs/content-type-configuration.md # app/code/Magento/PageBuilder/view/adminhtml/web/css/source/content-type/slider/_default.less # app/code/Magento/PageBuilder/view/adminhtml/web/css/source/content-type/tabs/_default.less # app/code/Magento/PageBuilder/view/adminhtml/web/js/content-type/preview.js # app/code/Magento/PageBuilder/view/adminhtml/web/template/content-type/tab-item/default/preview.html # app/code/Magento/PageBuilder/view/adminhtml/web/ts/js/content-type/preview.ts
2 parents 4ab1ebf + 59b1ad7 commit 6261152

File tree

83 files changed

+1278
-472
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1278
-472
lines changed

app/code/Magento/PageBuilder/Block/WidgetInitializer.php

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,26 @@ class WidgetInitializer extends Template
2222
*/
2323
private $jsonSerializer;
2424

25+
/**
26+
* @var \Magento\PageBuilder\Model\WidgetInitializerConfig
27+
*/
28+
private $config;
29+
2530
/**
2631
* WidgetInitializer constructor.
2732
* @param Template\Context $context
2833
* @param \Magento\Framework\Serialize\Serializer\Json $jsonEncoder
34+
* @param \Magento\PageBuilder\Model\WidgetInitializerConfig $config
2935
* @param array $data
3036
*/
3137
public function __construct(
3238
\Magento\Framework\View\Element\Template\Context $context,
3339
\Magento\Framework\Serialize\Serializer\Json $jsonEncoder,
40+
\Magento\PageBuilder\Model\WidgetInitializerConfig $config,
3441
array $data = []
3542
) {
3643
$this->jsonSerializer = $jsonEncoder;
44+
$this->config = $config;
3745
parent::__construct($context, $data);
3846
}
3947

@@ -44,21 +52,6 @@ public function __construct(
4452
*/
4553
public function getConfig() : string
4654
{
47-
$widgetsConfig = $this->getData('config');
48-
$resultConfig = [];
49-
foreach ($widgetsConfig as $contentTypeName => $config) {
50-
$selector = sprintf('div[data-role="%s"]', $contentTypeName);
51-
foreach ($config as $item) {
52-
if (!isset($item['component'])) {
53-
continue;
54-
}
55-
if (isset($item['appearance'])) {
56-
$selector .= sprintf('[data-appearance="%s"]', $item['appearance']);
57-
}
58-
$componentConfig = isset($item['config']) ? $item['config'] : '{}';
59-
$resultConfig[$selector] = [$item['component'] => $componentConfig];
60-
}
61-
}
62-
return $this->jsonSerializer->serialize($resultConfig);
55+
return $this->jsonSerializer->serialize($this->config->getConfig());
6356
}
6457
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ class Config
6868
*/
6969
private $inlineEditingChecker;
7070

71+
/**
72+
* @var \Magento\PageBuilder\Model\WidgetInitializerConfig
73+
*/
74+
private $widgetInitializerConfig;
75+
7176
/**
7277
* Config constructor.
7378
* @param \Magento\PageBuilder\Model\ConfigInterface $config
@@ -78,6 +83,7 @@ class Config
7883
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
7984
* @param \Magento\Ui\Block\Wysiwyg\ActiveEditor $activeEditor
8085
* @param \Magento\PageBuilder\Model\Wysiwyg\InlineEditingSupportedAdapterList $inlineEditingChecker
86+
* @param \Magento\PageBuilder\Model\WidgetInitializerConfig $widgetInitializerConfig
8187
* @param array $data
8288
*/
8389
public function __construct(
@@ -89,6 +95,7 @@ public function __construct(
8995
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
9096
\Magento\Ui\Block\Wysiwyg\ActiveEditor $activeEditor,
9197
\Magento\PageBuilder\Model\Wysiwyg\InlineEditingSupportedAdapterList $inlineEditingChecker,
98+
\Magento\PageBuilder\Model\WidgetInitializerConfig $widgetInitializerConfig,
9299
array $data = []
93100
) {
94101
$this->config = $config;
@@ -99,6 +106,7 @@ public function __construct(
99106
$this->scopeConfig = $scopeConfig;
100107
$this->activeEditor = $activeEditor;
101108
$this->inlineEditingChecker = $inlineEditingChecker;
109+
$this->widgetInitializerConfig = $widgetInitializerConfig;
102110
$this->data = $data;
103111
}
104112

@@ -117,7 +125,8 @@ public function getConfig()
117125
'preview_url' => $this->frontendUrlBuilder->getUrl('pagebuilder/contenttype/preview'),
118126
'column_grid_default' => $this->scopeConfig->getValue(self::XML_PATH_COLUMN_GRID_DEFAULT),
119127
'column_grid_max' => $this->scopeConfig->getValue(self::XML_PATH_COLUMN_GRID_MAX),
120-
'can_use_inline_editing_on_stage' => $this->isWysiwygProvisionedForEditingOnStage()
128+
'can_use_inline_editing_on_stage' => $this->isWysiwygProvisionedForEditingOnStage(),
129+
'widgets' => $this->widgetInitializerConfig->getConfig(),
121130
];
122131
}
123132

app/code/Magento/PageBuilder/Model/Stage/Renderer/CmsStaticBlock.php

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace Magento\PageBuilder\Model\Stage\Renderer;
1010

11+
use Psr\Log\LoggerInterface;
12+
1113
/**
1214
* Renders a CMS Block for the stage
1315
*
@@ -26,18 +28,25 @@ class CmsStaticBlock implements \Magento\PageBuilder\Model\Stage\RendererInterfa
2628
private $widgetDirectiveRenderer;
2729

2830
/**
29-
* Constructor
31+
* @var LoggerInterface
32+
*/
33+
private $loggerInterface;
34+
35+
/**
36+
* CmsStaticBlock constructor.
3037
*
31-
* @param WidgetDirective $widgetDirectiveRenderer
3238
* @param \Magento\Cms\Model\ResourceModel\Block\CollectionFactory $blockCollectionFactory
39+
* @param WidgetDirective $widgetDirectiveRenderer
40+
* @param LoggerInterface $loggerInterface
3341
*/
3442
public function __construct(
43+
\Magento\Cms\Model\ResourceModel\Block\CollectionFactory $blockCollectionFactory,
3544
WidgetDirective $widgetDirectiveRenderer,
36-
\Magento\Cms\Model\ResourceModel\Block\CollectionFactory $blockCollectionFactory
45+
LoggerInterface $loggerInterface
3746
) {
38-
3947
$this->blockCollectionFactory = $blockCollectionFactory;
4048
$this->widgetDirectiveRenderer = $widgetDirectiveRenderer;
49+
$this->loggerInterface = $loggerInterface;
4150
}
4251

4352
/**
@@ -55,7 +64,7 @@ public function render(array $params): array
5564
];
5665

5766
// Short-circuit if needed fields aren't present
58-
if (empty($params['directive']) || empty($params['block_id'])) {
67+
if (empty($params['directive']) && empty($params['block_id'])) {
5968
return $result;
6069
}
6170

@@ -79,12 +88,34 @@ public function render(array $params): array
7988

8089
if ($block->isActive()) {
8190
$directiveResult = $this->widgetDirectiveRenderer->render($params);
82-
$result['content'] = $directiveResult['content'];
83-
$result['error'] = $directiveResult['error'];
91+
$result['content'] = $this->removeScriptTags($directiveResult['content']);
8492
} else {
8593
$result['error'] = __('Block disabled');
8694
}
8795

8896
return $result;
8997
}
98+
99+
/**
100+
* Remove script tag from html
101+
*
102+
* @param string $content
103+
* @return string
104+
*/
105+
private function removeScriptTags(string $content): string
106+
{
107+
$dom = new \DOMDocument();
108+
try {
109+
//this code is required because of https://bugs.php.net/bug.php?id=60021
110+
$previous = libxml_use_internal_errors(true);
111+
$dom->loadHTML($content);
112+
} catch (\Exception $e) {
113+
$this->loggerInterface->critical($e->getMessage());
114+
}
115+
libxml_use_internal_errors($previous);
116+
foreach (iterator_to_array($dom->getElementsByTagName('script')) as $item) {
117+
$item->parentNode->removeChild($item);
118+
}
119+
return $dom->saveHTML();
120+
}
90121
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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\Model;
10+
11+
/**
12+
* Container for the configuration related to the widget initializer mechanism
13+
*/
14+
class WidgetInitializerConfig
15+
{
16+
/**
17+
* @var array The provided configuration
18+
*/
19+
private $config;
20+
21+
/**
22+
* @param array $config
23+
*/
24+
public function __construct(array $config)
25+
{
26+
$this->config = $config;
27+
}
28+
29+
/**
30+
* Retrieves the component-ready configuration for the widget initializer
31+
* @return array
32+
*/
33+
public function getConfig(): array
34+
{
35+
$resultConfig = [];
36+
foreach ($this->config as $contentTypeName => $config) {
37+
$selector = sprintf('div[data-role="%s"]', $contentTypeName);
38+
foreach ($config as $item) {
39+
if (!isset($item['component'])) {
40+
continue;
41+
}
42+
if (isset($item['appearance'])) {
43+
$selector .= sprintf('[data-appearance="%s"]', $item['appearance']);
44+
}
45+
$componentConfig = isset($item['config']) ? $item['config'] : '{}';
46+
$resultConfig[$selector] = [$item['component'] => $componentConfig];
47+
}
48+
}
49+
return $resultConfig;
50+
}
51+
}

app/code/Magento/PageBuilder/Test/Mftf/ActionGroup/OptionsMenuActionGroup.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@
4242
<see userInput="Edit {{contentType.name}}" selector="{{EditPanelForm.editFormTitle}}" stepKey="seeContentTypeNameInEditFormTitle"/>
4343
<waitForPageLoad stepKey="waitForAnimation2" time="30"/>
4444
</actionGroup>
45+
<actionGroup name="openOptionsMenu">
46+
<arguments>
47+
<argument name="contentType"/>
48+
<argument name="contentTypeIndex" defaultValue="1" type="string"/>
49+
<argument name="contentTypeXCoordinate" defaultValue="null" type="string"/>
50+
<argument name="contentTypeYCoordinate" defaultValue="null" type="string"/>
51+
</arguments>
52+
<waitForElementVisible time="20" selector="{{PageBuilderStage.contentTypeInStageByIndex(contentType.role, contentTypeIndex)}}" stepKey="waitForContentTypeInStageVisible"/>
53+
<moveMouseOver selector="{{PageBuilderStage.contentTypeInStageByIndex(contentType.role, contentTypeIndex)}}" x="{{contentTypeXCoordinate}}" y="{{contentTypeYCoordinate}}" stepKey="onMouseOverContentTypeStage"/>
54+
<waitForPageLoad stepKey="waitForPageLoad"/>
55+
<waitForElementVisible time="10" selector="{{PageBuilderContentTypeOptionsMenu.contentTypeOptionsMenuByIndex(contentType.role, contentTypeIndex)}}" stepKey="waitForOptions"/>
56+
<waitForElementVisible selector="{{PageBuilderContentTypeOptionsMenu.contentTypeEditByIndex(contentType.role, contentTypeIndex)}}" stepKey="waitForEditButton"/>
57+
</actionGroup>
4558
<actionGroup name="openPageBuilderEditPanelSmallByIndex">
4659
<arguments>
4760
<argument name="section"/>

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderBlockSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<element name="noCssClasses" type="text" selector="(//div[contains(@class,'pagebuilder-block')])[{{arg1}}]//div[not(@class)]" parameterized="true"/>
3131
<element name="margins" type="text" selector="(//div[contains(@class,'pagebuilder-block')])[{{arg1}}]//div[contains(@style,'margin: {{arg2}}px;')]" parameterized="true"/>
3232
<element name="padding" type="text" selector="(//div[contains(@class,'pagebuilder-block')])[{{arg1}}]//div[contains(@style,'padding: {{arg2}}px;')]" parameterized="true"/>
33+
<element name="overlay" type="text" selector=".pagebuilder-content-type-hidden"/>
3334
</section>
3435
<section name="BlockOnGrid">
3536
<element name="searchBox" type="text" selector="//input[contains(@class,'data-grid-search-control')]"/>

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderSliderSection.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
<element name="firstSlideNavigationDot" type="button" selector="(//div[contains(@class, 'navigation-dot')])[1]"/>
4040
<element name="activeSlideTooltip" type="button" selector="//div[contains(@class, 'navigation-dot')]//span[contains(@role, 'tooltip')]"/>
4141
<element name="slideNavigationDot" type="button" selector="(//div[contains(@class, 'navigation-dot')])[{{arg1}}]" parameterized="true"/>
42+
<element name="slideNavigationDragHandle" type="button" selector="a.navigation-dot-anchor"/>
43+
<element name="slideNavigationDragHandleByIndex" type="button" selector="(//a[contains(@class, 'navigation-dot-anchor')])[{{arg1}}]" parameterized="true"/>
4244
<element name="allNavigationDots" type="button" selector="(//div[contains(@class, 'navigation-dot')])"/>
4345
<element name="activeSlideNavigationDot" type="button" selector="//div[contains(@class, 'navigation-dot active')]"/>
4446
<element name="slideNavigationDotNameTooltip" type="button" selector="(//span[contains(@class, 'tooltip-content')])"/>

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderStageSection.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
<element name="contentTypeWithIcon" type="button" selector="//ul[@class='pagebuilder-panel-groups']//span[@class='content-type-icon']//i[@class='icon-pagebuilder-{{arg2}}']/../following-sibling::span[text()='{{arg1}}']" parameterized="true"/>
6464
</section>
6565
<section name="PageBuilderContentTypeOptionsMenu">
66-
<element name="contentTypeOptionsMenu" type="button" selector='div.pagebuilder-{{arg1}}.pagebuilder-content-type > div.pagebuilder-options' parameterized="true"/>
66+
<element name="contentTypeOptionsMenu" type="button" selector='(//div[contains(@class, "pagebuilder-{{arg1}}")]//div[contains(@class, "pagebuilder-options")])[1]' parameterized="true"/>
6767
<element name="contentTypeOptionsMenuByIndex" type="button" selector='(//div[contains(@class, "pagebuilder-content-type") and contains(@class, "pagebuilder-{{arg1}}")])[{{arg2}}]//div[contains(@class,"pagebuilder-options-visible")]' parameterized="true"/>
6868
<element name="contentTypeMove" type="button" selector='(//div[contains(@class, "pagebuilder-content-type") and contains(@class, "pagebuilder-{{arg1}}")])[1]/div[contains(@class,"pagebuilder-options-visible")]/descendant::*[@class="move-structural"]' parameterized="true"/>
6969
<element name="contentTypeMoveByIndex" type="button" selector='(//div[contains(@class, "pagebuilder-content-type") and contains(@class, "pagebuilder-{{arg1}}")])[{{arg2}}]/div[contains(@class,"pagebuilder-options-visible")]/descendant::*[@class="move-structural"]' parameterized="true"/>

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderTabsSection.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@
8686
<element name="tabHeader" type="button" selector="(//li[contains(@role, 'tab')])[{{arg1}}]" parameterized="true"/>
8787
<element name="tabHeaderItemActive" type="button" selector="(//div[@data-role='tabs']//descendant::*[@role='tablist'])/li[{{arg1}}][contains(@class, 'ui-state-active')]" parameterized="true"/>
8888
<element name="tabPanel" type="button" selector="(//div[@class='tabs-content']//div[@role='tabpanel'])[{{arg1}}]" parameterized="true"/>
89+
<element name="tabContent" type="button" selector="div.tabs-content div[data-role=tab-item]:nth-child({{arg1}})" parameterized="true"/>
90+
<element name="tabContentAdvancedStyles" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][@style='border-radius: 0px 12px 12px; border: 10px solid rgb(0, 0, 0);']" parameterized="true"/>
91+
<element name="tabContentMinimumHeight" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'min-height: {{arg2}}px')]" parameterized="true"/>
92+
<element name="tabContentBackgroundColor" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'background-color: {{arg2}}')]" parameterized="true"/>
93+
<element name="tabContentBackgroundImage" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'background-image: url') and contains(@style, '{{arg2}}') and contains(@style, '{{arg3}}')]" parameterized="true"/>
94+
<element name="tabContentBackgroundAttachment" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'background-attachment: {{arg2}}')]" parameterized="true"/>
95+
<element name="tabContentBackgroundPosition" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'background-position: {{arg2}}')]" parameterized="true"/>
96+
<element name="tabContentBackgroundSize" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'background-size: {{arg2}}')]" parameterized="true"/>
97+
<element name="tabContentBackgroundRepeat" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style, 'background-repeat: {{arg2}}')]" parameterized="true"/>
8998
<element name="container" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}]" parameterized="true"/>
9099
<element name="containerStyle" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][contains(@style,'{{arg2}}')]" parameterized="true"/>
91100
<element name="noMinHeight" type="button" selector="(//div[@class='tabs-content']//div[@data-role='tab-item'])[{{arg1}}][not(contains(@style,'min-height:'))]" parameterized="true"/>

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderTextSection.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<element name="notHidden" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg1}}]/div/ancestor::*[contains(@class, 'pagebuilder-content-type-wrapper') and not(contains(@class, 'pagebuilder-content-type-hidden'))][1]" parameterized="true"/>
1515
<element name="textAreaTextContains" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg1}}]/div[contains(.,'{{arg2}}')]" parameterized="true"/>
1616
<element name="text" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg1}}]/div//*[contains(.,'{{arg2}}')]" parameterized="true"/>
17+
<element name="directive" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg1}}]/div//span[contains(.,'{{arg2}}')]" parameterized="true"/>
1718
<element name="mcePlaceholder" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg1}}]/div//*[starts-with(@id, '{{arg2}}')]" parameterized="true"/>
1819
<element name="placeholder" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg1}}]//div[contains(@class, 'placeholder-text') and text()='Edit Text']" parameterized="true"/>
1920
<element name="tinymce" type="text" selector="(//div[contains(@class,'pagebuilder-text')])[{{arg}}]//div[contains(@class, 'inline-wysiwyg')]" parameterized="true"/>
@@ -58,7 +59,8 @@
5859
<element name="notHidden" type="text" selector="(//div[@data-role='text'])[{{arg1}}][not(contains(@style, 'display: none'))]" parameterized="true"/>
5960
<element name="baseJs" type="text" selector="document.querySelectorAll('[data-role=\'text\']')[{{arg1}}]" parameterized="true"/>
6061
<element name="textAreaText" type="text" selector="(//div[@data-role='text'])[{{arg1}}][.='{{arg2}}']" parameterized="true"/>
61-
<element name="textAreaWidget" type="text" selector="(//div[@data-role='text'])[{{arg1}}]//a[contains(@href,'{{arg2}}{{arg3}}')]" parameterized="true"/>
62+
<element name="textAreaWidget" type="text" selector="(//div[@data-role='text'])[{{arg1}}]//a[contains(@href,'{{arg2}}{{arg3}}{{arg4}}')]" parameterized="true"/>
63+
<element name="textWidget" type="text" selector="(//div[@data-role='text'])[{{arg1}}]//a[contains(@href,'{{arg2}}{{arg3}}')]" parameterized="true"/>
6264
<element name="textAreaVariable" type="text" selector="(//div[@data-role='text'])[{{arg1}}]//a[contains(@href,'{{arg2}}{{arg3}}')]" parameterized="true"/>
6365
<element name="text" type="text" selector="(//div[@data-role='text'])[{{arg1}}]//*[contains(text(),'{{arg2}}')]" parameterized="true"/>
6466
<element name="empty" type="text" selector="//div[@data-role='text'][{{arg1}}][not(*)]" parameterized="true"/>
@@ -81,6 +83,7 @@
8183
<element name="noMargins" type="text" selector="(//div[@data-role='text'])[{{arg1}}][not(contains(@style,'margin:'))]" parameterized="true"/>
8284
<element name="padding" type="text" selector="(//div[@data-role='text'])[{{arg1}}][contains(@style,'padding: {{arg2}}px;')]" parameterized="true"/>
8385
<element name="noPadding" type="text" selector="(//div[@data-role='text'])[{{arg1}}][not(contains(@style,'padding:'))]" parameterized="true"/>
86+
<element name="emptyText" type="text" selector="//div[@data-role='text']/p[not(text())]"/>
8487
</section>
8588
<section name="TextOnBackend">
8689
<element name="textInstance" type="button" selector='//div[contains(@class, "pagebuilder-text")][1]/div[1]'/>

0 commit comments

Comments
 (0)