Skip to content

Commit 8ce148e

Browse files
Merge pull request #10 from magento-performance/MC-37459
[performance] MC-37459: Support by Magento Catalog
2 parents e56edfd + cd854b2 commit 8ce148e

File tree

467 files changed

+26545
-3594
lines changed

Some content is hidden

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

467 files changed

+26545
-3594
lines changed

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
*/
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+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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\Setup\Converters;
10+
11+
use Magento\Framework\DB\DataConverter\DataConverterInterface;
12+
use Magento\PageBuilder\Model\Dom\Adapter\ElementInterface;
13+
use Magento\PageBuilder\Model\Dom\HtmlDocumentFactory;
14+
15+
/**
16+
* Convert Inline Styles to Internal
17+
*/
18+
class PageBuilderStripStyles implements DataConverterInterface
19+
{
20+
private const BODY_ID = 'html-body';
21+
private const DATA_ATTRIBUTE = 'data-pb-style';
22+
private const QUERY_SELECTOR = '[style]';
23+
24+
/**
25+
* @var HtmlDocumentFactory
26+
*/
27+
private $htmlDocumentFactory;
28+
29+
/**
30+
* @param HtmlDocumentFactory $htmlDocumentFactory
31+
*/
32+
public function __construct(HtmlDocumentFactory $htmlDocumentFactory)
33+
{
34+
$this->htmlDocumentFactory = $htmlDocumentFactory;
35+
}
36+
37+
/**
38+
* Generates `mageUtils.uniqueid()` Naming Convention
39+
*
40+
* @return string
41+
*/
42+
private function generateDataAttribute(): string
43+
{
44+
return \strtoupper(\uniqid());
45+
}
46+
47+
/**
48+
* Converts Inline Styles to Internal Styles
49+
*
50+
* @param array $styleMap
51+
* @return string
52+
*/
53+
private function generateInternalStyles(array $styleMap): string
54+
{
55+
$output = '';
56+
57+
foreach ($styleMap as $selector => $styles) {
58+
$output .= '#' . self::BODY_ID . ' [' . self::DATA_ATTRIBUTE . '="' . $selector . '"]';
59+
$output .= '{' . $styles . '}';
60+
}
61+
62+
return $output;
63+
}
64+
65+
/**
66+
* @inheritDoc
67+
*/
68+
public function convert($value): string
69+
{
70+
$document = $this->htmlDocumentFactory->create([ 'document' => $value ]);
71+
$body = $document->querySelector('body');
72+
$nodes = $document->querySelectorAll(self::QUERY_SELECTOR);
73+
74+
if ($nodes->count() > 0) {
75+
$styleMap = [];
76+
77+
foreach ($nodes as $node) {
78+
/* @var ElementInterface $node */
79+
$styleAttr = $node->getAttribute('style');
80+
81+
if ($styleAttr) {
82+
$generatedDataAttribute = $this->generateDataAttribute();
83+
$node->setAttribute(self::DATA_ATTRIBUTE, $generatedDataAttribute);
84+
$styleMap[$generatedDataAttribute] = $styleAttr; // Amend Array for Internal Style Generation
85+
$node->removeAttribute('style');
86+
}
87+
}
88+
89+
if (count($styleMap) > 0) {
90+
// Style Block Generation
91+
$style = $document->createElement(
92+
'style',
93+
$this->generateInternalStyles($styleMap)
94+
);
95+
$body->appendChild($style);
96+
97+
return $document->stripHtmlWrapperTags();
98+
} else {
99+
return $value;
100+
}
101+
}
102+
103+
return $value;
104+
}
105+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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\Setup\Patch\Data;
10+
11+
use Magento\Framework\DB\FieldDataConversionException;
12+
use Magento\Framework\Setup\Patch\DataPatchInterface;
13+
use Magento\PageBuilder\Setup\Converters\PageBuilderStripStyles;
14+
use Magento\PageBuilder\Setup\UpgradeContentHelper;
15+
16+
/**
17+
* Patch Upgrade Mechanism for Converting Inline Styles to Internal
18+
*/
19+
class UpgradePageBuilderStripStyles implements DataPatchInterface
20+
{
21+
/**
22+
* @var UpgradeContentHelper
23+
*/
24+
private $helper;
25+
26+
/**
27+
* @param UpgradeContentHelper $helper
28+
*/
29+
public function __construct(UpgradeContentHelper $helper)
30+
{
31+
$this->helper = $helper;
32+
}
33+
34+
/**
35+
* Upgrade
36+
*
37+
* @return void
38+
* @throws FieldDataConversionException
39+
*/
40+
public function apply(): void
41+
{
42+
$this->helper->upgrade([
43+
PageBuilderStripStyles::class
44+
]);
45+
}
46+
47+
/**
48+
* @inheritdoc
49+
*/
50+
public function getAliases(): array
51+
{
52+
return [];
53+
}
54+
55+
/**
56+
* @inheritdoc
57+
*/
58+
public static function getDependencies(): array
59+
{
60+
return [];
61+
}
62+
}

0 commit comments

Comments
 (0)