Skip to content

Commit 4538f2d

Browse files
author
Oleksandr Gorkun
committed
MC-18039: [2.2.x] Require specific suffix for HTML binding
1 parent d1c376e commit 4538f2d

File tree

3 files changed

+77
-30
lines changed

3 files changed

+77
-30
lines changed

dev/tests/static/framework/Magento/Sniffs/Html/HtmlBindingSniff.php

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,39 +23,68 @@ public function register()
2323
}
2424

2525
/**
26-
* @inheritDoc
26+
* Load HTML document to validate.
2727
*
28-
* Find HTML data bindings and check variables used.
28+
* @param int $stackPointer
29+
* @param File $file
30+
* @return \DOMDocument|null
2931
*/
30-
public function process(File $phpcsFile, $stackPtr)
32+
private function loadHtmlDocument(int $stackPointer, File $file)
3133
{
32-
if ($stackPtr === 0) {
33-
$html = $phpcsFile->getTokensAsString($stackPtr, count($phpcsFile->getTokens()));
34+
if ($stackPointer === 0) {
35+
$html = $file->getTokensAsString($stackPointer, count($file->getTokens()));
3436
$dom = new \DOMDocument();
3537
try {
3638
// phpcs:disable Generic.PHP.NoSilencedErrors
3739
@$dom->loadHTML($html);
38-
$loaded = true;
40+
return $dom;
3941
} catch (\Throwable $exception) {
40-
//Invalid HTML, skipping
41-
$loaded = false;
42+
return null;
4243
}
43-
if ($loaded) {
44-
$domXpath = new \DOMXPath($dom);
45-
$dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]');
46-
foreach ($dataBindAttributes as $dataBindAttribute) {
47-
$knockoutBinding = $dataBindAttribute->nodeValue;
48-
preg_match('/^(.+\s*?)?html\s*?\:\s*?([a-z0-9\.\(\)\_]+)/ims', $knockoutBinding, $htmlBinding);
49-
if ($htmlBinding && !preg_match('/UnsanitizedHtml[\(\)]*?$/', $htmlBinding[2])) {
50-
$phpcsFile->addError(
51-
'Variables/functions used for HTML binding must have UnsanitizedHtml suffix'
52-
.' - "' .$htmlBinding[2] .'" doesn\'t,' .PHP_EOL
53-
.'consider using text binding if the value is supposed to be text',
54-
null,
55-
'UIComponentTemplate.KnockoutBinding.HtmlSuffix'
56-
);
57-
}
58-
}
44+
}
45+
46+
return null;
47+
}
48+
49+
/**
50+
* @inheritDoc
51+
*
52+
* Find HTML data bindings and check variables used.
53+
*/
54+
public function process(File $phpcsFile, $stackPtr)
55+
{
56+
if (!$dom = $this->loadHtmlDocument($stackPtr, $phpcsFile)) {
57+
return;
58+
}
59+
60+
/** @var string[] $htmlBindings */
61+
$htmlBindings = [];
62+
$domXpath = new \DOMXPath($dom);
63+
$dataBindAttributes = $domXpath->query('//@*[name() = "data-bind"]');
64+
foreach ($dataBindAttributes as $dataBindAttribute) {
65+
$knockoutBinding = $dataBindAttribute->nodeValue;
66+
preg_match('/^(.+\s*?)?html\s*?\:(.+)/ims', $knockoutBinding, $htmlBindingStart);
67+
if ($htmlBindingStart) {
68+
$htmlBinding = trim(preg_replace('/\,[a-z0-9\_\s]+\:.+/ims', '', $htmlBindingStart[2]));
69+
$htmlBindings[] = $htmlBinding;
70+
}
71+
}
72+
$htmlAttributes = $domXpath->query('//@*[name() = "html"]');
73+
foreach ($htmlAttributes as $htmlAttribute) {
74+
$magentoBinding = $htmlAttribute->nodeValue;
75+
$htmlBindings[] = trim($magentoBinding);
76+
}
77+
foreach ($htmlBindings as $htmlBinding) {
78+
if (!preg_match('/^[0-9\\\'\"]/ims', $htmlBinding)
79+
&& !preg_match('/UnsanitizedHtml(\(.*?\))*?$/', $htmlBinding)
80+
) {
81+
$phpcsFile->addError(
82+
'Variables/functions used for HTML binding must have UnsanitizedHtml suffix'
83+
. ' - "' . $htmlBinding . '" doesn\'t,' . PHP_EOL
84+
. 'consider using text binding if the value is supposed to be text',
85+
null,
86+
'UIComponentTemplate.KnockoutBinding.HtmlSuffix'
87+
);
5988
}
6089
}
6190
}
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2-
FOUND 3 ERRORS AFFECTING 1 LINE
3-
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1+
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2+
FOUND 6 ERRORS AFFECTING 1 LINE
3+
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
44
1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "testError()" doesn't,
55
| | consider using text binding if the value is supposed to be text
66
1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "test.getSomething().value.error()" doesn't,
77
| | consider using text binding if the value is supposed to be text
8+
1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "bind_stuff(1, 2)" doesn't,
9+
| | consider using text binding if the value is supposed to be text
10+
1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "testError()" doesn't,
11+
| | consider using text binding if the value is supposed to be text
12+
1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "test.getSomething().value.error(1)" doesn't,
13+
| | consider using text binding if the value is supposed to be text
814
1 | ERROR | Variables/functions used for HTML binding must have UnsanitizedHtml suffix - "bind_stuff()" doesn't,
915
| | consider using text binding if the value is supposed to be text
10-
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
16+
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1117

1218

dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Html/_files/test-html-binding.html

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,19 @@
1212
attr : tst,
1313
html: test.getSomething().value.error()
1414
"></div>
15-
<p data-bind="html: '<b>Some html</b>'"></p>
15+
<p data-bind="html: '<b>Some html</b>', attr: test"></p>
1616
<div data-bind="html: valueUnsanitizedHtml"></div>
1717
<div data-bind="attr: testhtml, html: valueUnsanitizedHtml()"></div>
18-
<p data-bind="other_html: bind, html: bind_stuff()"></p>
18+
<p data-bind="other_html: bind, html: bind_stuff(1, 2)"></p>
19+
20+
<div style="tst()"></div>
21+
<span html="testError()"></span>
22+
<div html="
23+
test.getSomething().value.error(1)
24+
"></div>
25+
<p html="'<b>Some html</b>'"></p>
26+
<div html="valueUnsanitizedHtml"></div>
27+
<div html="
28+
valueUnsanitizedHtml('test')
29+
"></div>
30+
<p html="bind_stuff()"></p>

0 commit comments

Comments
 (0)