Skip to content

Commit edb6e31

Browse files
Merge pull request #658 from joweecaquicla/viewport-switcher-update
[WIP] Viewport switcher update
2 parents ddb9baf + dd12f7b commit edb6e31

File tree

464 files changed

+26698
-3438
lines changed

Some content is hidden

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

464 files changed

+26698
-3438
lines changed

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@ Welcome to the Magento 2 Page Builder project!
66

77
Page Builder introduces an intuitive, drag-and-drop interface for creating digital content, powered by content types like images, videos, banners, etc. with instant preview capabilities that enable non-technical users to take control of their content. It allows to create new pages, enrich products and categories, and launch content updates quickly and easily without the help of a front-end web developer.
88

9+
## Wiki
10+
11+
Public access to the Page Builder wiki is found here:
12+
13+
https://github.com/magento/magento2-page-builder-docs/wiki.
14+
15+
The wiki provides more information on the Page Builder project, such as:
16+
17+
- [Links to User Guide tutorials](https://github.com/magento/magento2-page-builder-docs/wiki#page-builder-tutorials)
18+
- [Page Builder roadmaps](https://github.com/magento/magento2-page-builder-docs/wiki#roadmap)
19+
- [MFTF best practices](https://github.com/magento/magento2-page-builder-docs/wiki/%5BRough-Draft%5D-MFTF-Best-Practices)
20+
- [Partners Acceleration Program](https://github.com/magento/magento2-page-builder-docs/wiki/Partners-Acceleration-Program-Team)
21+
922
## Documentation
10-
Complete documentation located on the [Magento DevDocs](https://devdocs.magento.com/page-builder/docs/):
11-
- Project [roadmap](https://github.com/magento/magento2-page-builder/wiki#roadmap) contains information about project phases
12-
- How to start local development described in the [installation guide](https://devdocs.magento.com/page-builder/docs/getting-started/install-pagebuilder.html)
23+
Complete documentation located on the [Magento DevDocs](https://devdocs.magento.com/page-builder/docs/), including what you need to know to start local development as described in the [installation guide](https://devdocs.magento.com/page-builder/docs/getting-started/install-pagebuilder.html).
1324

1425
## Community Engineering Slack
1526

16-
To connect with Magento team and the Community, join us on the [Magento Community Engineering Slack](https://magentocommeng.slack.com).
27+
To connect with Magento team and the Community, join us on the [Magento Community Engineering Slack](https://magentocommeng.slack.com).
1728
If you are interested in joining Slack, or a specific channel, use our [self signup](https://opensource.magento.com/slack) link.
1829

1930
Magento 2 Page Builder project slack channel: [#pagebuilder](https://magentocommeng.slack.com/archives/CHB455HPF)

app/code/Magento/PageBuilder/Model/Dom/Adapter/DocumentInterface.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ public function __toString(): string;
2929
*/
3030
public function createDocumentFragment(): DocumentFragmentInterface;
3131

32+
/**
33+
* Create new document element
34+
*
35+
* @param string $name
36+
* @param string $value [optional]
37+
* @return ElementInterface
38+
*/
39+
public function createElement(string $name, string $value = null);
40+
3241
/**
3342
* Returns the first element matching the specified selector.
3443
*

app/code/Magento/PageBuilder/Model/Dom/Adapter/ElementInterface.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,28 @@
77

88
namespace Magento\PageBuilder\Model\Dom\Adapter;
99

10+
use Gt\Dom\Element as GtDomElement;
11+
1012
/**
1113
* Interface for Element wrappers
1214
*/
1315
interface ElementInterface
1416
{
17+
/**
18+
* Return original element.
19+
*
20+
* @return GtDomElement
21+
*/
22+
public function getOriginalElement(): GtDomElement;
23+
24+
/**
25+
* Adds new child at the end of the children.
26+
*
27+
* @param ElementInterface $element
28+
* @return ElementInterface
29+
*/
30+
public function appendChild(ElementInterface $element): ElementInterface;
31+
1532
/**
1633
* Returns true if the element would be selected by the specified selector string; otherwise, returns false.
1734
*
@@ -45,6 +62,14 @@ public function closest(string $selectors): ?ElementInterface;
4562
*/
4663
public function getAttribute($name): ?string;
4764

65+
/**
66+
* Removes the Specified Attribute
67+
*
68+
* @param string $name
69+
* @return bool|null
70+
*/
71+
public function removeAttribute($name): ?bool;
72+
4873
/**
4974
* Sets the value of the specified attribute
5075
*

app/code/Magento/PageBuilder/Model/Dom/Document.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ public function createDocumentFragment(): DocumentFragmentInterface
6262
);
6363
}
6464

65+
/**
66+
* @inheritDoc
67+
*/
68+
public function createElement(string $name, string $value = null): ElementInterface
69+
{
70+
return $this->objectManager->create(
71+
ElementInterface::class,
72+
[ 'element' => $this->document->createElement($name, $value) ]
73+
);
74+
}
75+
6576
/**
6677
* @inheritDoc
6778
*/

app/code/Magento/PageBuilder/Model/Dom/Element.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,25 @@ public function __construct(
4141
$this->element = $element;
4242
}
4343

44+
/**
45+
* @inheritDoc
46+
*/
47+
public function getOriginalElement(): GtDomElement
48+
{
49+
return $this->element;
50+
}
51+
52+
/**
53+
* @inheritDoc
54+
*/
55+
public function appendChild(ElementInterface $element): ElementInterface
56+
{
57+
return $this->objectManager->create(
58+
ElementInterface::class,
59+
[ 'element' => $this->element->appendChild($element->getOriginalElement()) ]
60+
);
61+
}
62+
4463
/**
4564
* @inheritDoc
4665
*/
@@ -79,6 +98,14 @@ public function getAttribute($name): ?string
7998
return $this->element->getAttribute($name);
8099
}
81100

101+
/**
102+
* @inheritDoc
103+
*/
104+
public function removeAttribute($name): ?bool
105+
{
106+
return $this->element->removeAttribute($name);
107+
}
108+
82109
/**
83110
* @inheritDoc
84111
*/

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

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,47 @@
77

88
namespace Magento\PageBuilder\Model\Stage;
99

10+
use Magento\Framework\App\Area;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
12+
use Magento\Framework\App\State;
13+
use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
14+
use Magento\Framework\View\DesignInterface;
15+
use Magento\Store\Model\App\Emulation;
16+
use Magento\Store\Model\ScopeInterface;
17+
use Magento\Store\Model\StoreManagerInterface;
18+
1019
/**
1120
* Handle placing Magento into Page Builder Preview mode and emulating the store front
1221
*/
1322
class Preview
1423
{
1524
/**
16-
* @var \Magento\Store\Model\App\Emulation
25+
* @var Emulation
1726
*/
1827
private $emulation;
1928

2029
/**
21-
* @var \Magento\Framework\App\State
30+
* @var State
2231
*/
2332
private $appState;
2433

2534
/**
26-
* @var \Magento\Framework\View\DesignInterface
35+
* @var DesignInterface
2736
*/
2837
private $design;
2938

3039
/**
31-
* @var \Magento\Framework\View\Design\Theme\ThemeProviderInterface
40+
* @var ThemeProviderInterface
3241
*/
3342
private $themeProvider;
3443

3544
/**
36-
* @var \Magento\Store\Model\StoreManagerInterface
45+
* @var StoreManagerInterface
3746
*/
3847
private $storeManager;
3948

4049
/**
41-
* @var \Magento\Framework\App\Config\ScopeConfigInterface
50+
* @var ScopeConfigInterface
4251
*/
4352
private $scopeConfig;
4453

@@ -49,20 +58,20 @@ class Preview
4958

5059
/**
5160
* Preview constructor.
52-
* @param \Magento\Store\Model\App\Emulation $emulation
53-
* @param \Magento\Framework\App\State $appState
54-
* @param \Magento\Framework\View\DesignInterface $design
55-
* @param \Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider
56-
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
57-
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
61+
* @param Emulation $emulation
62+
* @param State $appState
63+
* @param DesignInterface $design
64+
* @param ThemeProviderInterface $themeProvider
65+
* @param StoreManagerInterface $storeManager
66+
* @param ScopeConfigInterface $scopeConfig
5867
*/
5968
public function __construct(
60-
\Magento\Store\Model\App\Emulation $emulation,
61-
\Magento\Framework\App\State $appState,
62-
\Magento\Framework\View\DesignInterface $design,
63-
\Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider,
64-
\Magento\Store\Model\StoreManagerInterface $storeManager,
65-
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
69+
Emulation $emulation,
70+
State $appState,
71+
DesignInterface $design,
72+
ThemeProviderInterface $themeProvider,
73+
StoreManagerInterface $storeManager,
74+
ScopeConfigInterface $scopeConfig
6675
) {
6776
$this->emulation = $emulation;
6877
$this->appState = $appState;
@@ -79,7 +88,7 @@ public function __construct(
7988
*/
8089
public function getPreviewArea() : string
8190
{
82-
return \Magento\Framework\App\Area::AREA_FRONTEND;
91+
return Area::AREA_FRONTEND;
8392
}
8493

8594
/**
@@ -95,7 +104,7 @@ public function startPreviewMode($callback, $storeId = null)
95104
$this->isPreview = true;
96105

97106
if (!$storeId) {
98-
$storeId = $this->storeManager->getDefaultStoreView()->getId();
107+
$storeId = $this->getStoreId();
99108
}
100109
$this->emulation->startEnvironmentEmulation($storeId);
101110

@@ -104,7 +113,7 @@ public function startPreviewMode($callback, $storeId = null)
104113
function () use ($callback) {
105114
$themeId = $this->scopeConfig->getValue(
106115
'design/theme/theme_id',
107-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
116+
ScopeInterface::SCOPE_STORE
108117
);
109118
$theme = $this->themeProvider->getThemeById($themeId);
110119
$this->design->setDesignTheme($theme, $this->getPreviewArea());
@@ -131,4 +140,26 @@ public function isPreviewMode() : bool
131140
{
132141
return $this->isPreview;
133142
}
143+
144+
/**
145+
* Returns store id by default store view or store id from the available store if default store view is null
146+
*
147+
* @return int|null
148+
*/
149+
private function getStoreId(): ?int
150+
{
151+
$storeId = null;
152+
$store = $this->storeManager->getDefaultStoreView();
153+
if ($store) {
154+
$storeId = (int) $store->getId();
155+
} else {
156+
$stores = $this->storeManager->getStores();
157+
if (count($stores)) {
158+
$store = array_shift($stores);
159+
$storeId = (int) $store->getId();
160+
}
161+
}
162+
163+
return $storeId;
164+
}
134165
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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\Validator;
10+
11+
use Magento\Framework\Validation\ValidationException;
12+
use Magento\Framework\Validator\HTML\AttributeValidatorInterface;
13+
14+
/**
15+
* Validates "src" of iframes.
16+
*/
17+
class IframeSrcAttributeValidator implements AttributeValidatorInterface
18+
{
19+
/**
20+
* @var string[]
21+
*/
22+
private $allowedHosts;
23+
24+
/**
25+
* IframeSrcAttributeValidator constructor.
26+
*
27+
* @param string[] $allowedHosts
28+
*/
29+
public function __construct(array $allowedHosts)
30+
{
31+
$this->allowedHosts = $allowedHosts;
32+
}
33+
34+
/**
35+
* @inheritDoc
36+
*/
37+
public function validate(string $tag, string $attributeName, string $value): void
38+
{
39+
if ($tag !== 'iframe' || $attributeName !== 'src') {
40+
return;
41+
}
42+
43+
if (mb_strpos($value, 'http') !== 0) {
44+
//Relative link
45+
return;
46+
}
47+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
48+
$srcHost = parse_url($value, PHP_URL_HOST);
49+
if (!$srcHost || !$this->allowedHosts) {
50+
//Either the link is invalid or we do not have the allowed list.
51+
return;
52+
}
53+
$srcHostLength = mb_strlen($srcHost);
54+
foreach ($this->allowedHosts as $host) {
55+
$hostLength = mb_strlen($host);
56+
$foundIndex = mb_strpos($srcHost, $host);
57+
if ($foundIndex !== false && ($foundIndex + $hostLength) === $srcHostLength) {
58+
return;
59+
}
60+
}
61+
62+
throw new ValidationException(__('Invalid IFRAME source provided'));
63+
}
64+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\Validator;
10+
11+
use Magento\Framework\Validator\HTML\TagValidatorInterface;
12+
use Magento\Framework\Validator\HTML\WYSIWYGValidatorInterface;
13+
14+
/**
15+
* Validates HTML elements.
16+
*/
17+
class InnerHtmlValidator implements TagValidatorInterface
18+
{
19+
private const HTML_TYPE_ATTRIBUTE = 'data-content-type';
20+
21+
/**
22+
* @inheritDoc
23+
*/
24+
public function validate(
25+
string $tag,
26+
array $attributes,
27+
string $value,
28+
WYSIWYGValidatorInterface $recursiveValidator
29+
): void {
30+
if (!array_key_exists(self::HTML_TYPE_ATTRIBUTE, $attributes)
31+
|| strtolower($attributes[self::HTML_TYPE_ATTRIBUTE]) !== 'html'
32+
) {
33+
return;
34+
}
35+
36+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
37+
$recursiveValidator->validate(html_entity_decode($value));
38+
}
39+
}

0 commit comments

Comments
 (0)