Skip to content

Commit 153e14a

Browse files
authored
Merge pull request #242 from magento-commerce/imported-fredden-magento-coding-standard-458
[Imported] Add sniff for deprecated use of $block->escape... methods
2 parents 6197724 + b8acb6c commit 153e14a

4 files changed

+325
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Magento2\Sniffs\Legacy;
11+
12+
use PHP_CodeSniffer\Files\File;
13+
use PHP_CodeSniffer\Sniffs\Sniff;
14+
use PHP_CodeSniffer\Util\Tokens;
15+
16+
class EscapeMethodsOnBlockClassSniff implements Sniff
17+
{
18+
private const ESCAPER_METHODS = [
19+
'escapeCss' => true,
20+
'escapeHtml' => true,
21+
'escapeHtmlAttr' => true,
22+
'escapeJs' => true,
23+
'escapeJsQuote' => true,
24+
'escapeQuote' => true,
25+
'escapeUrl' => true,
26+
'escapeXssInUrl' => true,
27+
];
28+
29+
/**
30+
* @inheritDoc
31+
*/
32+
public function register()
33+
{
34+
return [
35+
T_OBJECT_OPERATOR,
36+
];
37+
}
38+
39+
/**
40+
* @inheritDoc
41+
*/
42+
public function process(File $phpcsFile, $stackPtr)
43+
{
44+
$tokens = $phpcsFile->getTokens();
45+
46+
if ($stackPtr <= 1 || !isset($tokens[$stackPtr + 2])) {
47+
return;
48+
}
49+
50+
$objectPtr = $stackPtr - 1;
51+
if ($tokens[$objectPtr]['code'] !== T_VARIABLE) {
52+
$objectPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $objectPtr, null, true);
53+
54+
if (!$objectPtr) {
55+
return;
56+
}
57+
}
58+
59+
if ($tokens[$objectPtr]['code'] !== T_VARIABLE
60+
|| $tokens[$objectPtr]['content'] !== '$block'
61+
) {
62+
return;
63+
}
64+
65+
$methodPtr = $stackPtr + 1;
66+
if ($tokens[$methodPtr]['code'] !== T_STRING) {
67+
$methodPtr = $phpcsFile->findNext(Tokens::$emptyTokens, $methodPtr, null, true);
68+
69+
if (!$methodPtr) {
70+
return;
71+
}
72+
}
73+
74+
if ($tokens[$methodPtr]['code'] !== T_STRING
75+
|| !isset(self::ESCAPER_METHODS[$tokens[$methodPtr]['content']])
76+
) {
77+
return;
78+
}
79+
80+
$openParenPtr = $methodPtr + 1;
81+
if ($tokens[$openParenPtr]['code'] !== T_OPEN_PARENTHESIS) {
82+
$openParenPtr = $phpcsFile->findNext(Tokens::$emptyTokens, $openParenPtr, null, true);
83+
84+
if (!$openParenPtr) {
85+
return;
86+
}
87+
}
88+
89+
if ($tokens[$openParenPtr]['code'] !== T_OPEN_PARENTHESIS) {
90+
return;
91+
}
92+
93+
$fix = $phpcsFile->addFixableWarning(
94+
'Using %s on $block is deprecated. Please use equivalent method on $escaper',
95+
$methodPtr,
96+
'Found',
97+
[
98+
$tokens[$methodPtr]['content'], // method name
99+
]
100+
);
101+
102+
if ($fix) {
103+
$phpcsFile->fixer->replaceToken($objectPtr, '$escaper');
104+
}
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/** @var Magento\Framework\View\Element\Template $block */
3+
/** @var Magento\Framework\Escaper $escaper */
4+
?>
5+
6+
<section>
7+
<h1>This unescaped output is fine here; other sniffs will complain about it though.</h1>
8+
9+
<?php echo $block->getSomeString(); ?>
10+
<?= $block->getSomeString(); ?>
11+
<?= /** @noEscape */ $block->getSomeString(); ?>
12+
<?= /** @escapeNotVerified */ $block->getSomeString(); ?>
13+
</section>
14+
15+
<section>
16+
<h1>These should be using equivalent methods on the `$escaper` class, not the `$block` class.</h1>
17+
18+
Note that I couldn't find any use of this method in any templates within Magento.
19+
<?= $block->escapeCss($block->getSomeString()); ?>
20+
21+
<?= $block->escapeHtml(__($block->getSomeString())) ?>
22+
<?= $block->escapeHtml(__($block->getSomeString())); ?>
23+
<?= $block->escapeHtml(__($block->getSomeString()), ['strong', 'em', 'span']) ?>
24+
25+
<div class="<?= $block->escapeHtmlAttr($block->getSomeString()) ?>"></div>
26+
<div class="<?= $block->escapeHtmlAttr($block->getSomeString(), true) ?>"></div>
27+
<div class="<?= $block->escapeHtmlAttr($block->getSomeString(), false); ?>"></div>
28+
29+
<script type="text/x-magento-init">
30+
{
31+
"#chart_<?= $block->escapeJs($block->getData('html_id')) ?>_period": {
32+
"Magento_Backend/js/dashboard/chart": {}
33+
}
34+
}
35+
</script>
36+
37+
The only example of this method being used was in a block class, rather than a template.
38+
<?php
39+
foreach ($block->getItems() as $item) {
40+
$item['sku'] = $block->escapeJsQuote($item['sku']);
41+
}
42+
?>
43+
44+
The only example of this method being used was in a block class, rather than a template.
45+
<?= $block->escapeQuote(__($block->getData('welcome'))); ?>
46+
47+
<a href="<?= $block->escapeUrl($block->getUrl('adminhtml/notification/index')) ?>"> link text </a>
48+
49+
Note that I couldn't find any use of this method in any templates within Magento.
50+
<?= $block->escapeXssInUrl($block->getSomeString()); ?>
51+
</section>
52+
53+
<section>
54+
<h1>These are edge cases for formatting differences</h1>
55+
56+
<?php
57+
$block->escapeHtml('');
58+
$block ->escapeHtml('');
59+
$block-> escapeHtml('');
60+
$block
61+
->escapeHtml('');
62+
$block
63+
64+
->escapeHtml('');
65+
$block->
66+
escapeHtml('');
67+
$block-> // comment
68+
escapeHtml('');
69+
$block /* comment */
70+
->escapeHtml('');
71+
72+
$block /* comment */ -> /* comment */ escapeHtml('');
73+
?>
74+
</section>
75+
76+
<section>
77+
<h1>These close-matches shouldn't be flagged by this sniff.</h1>
78+
79+
<?= $block->escapeHTML(__($block->getSomeString())) ?>
80+
<?= $block->escapeHtmlString(__($block->getSomeString())) ?>
81+
<?= $block->escapeHtmlAttribute($block->getSomeString()) ?>
82+
<?= $block->escapeCSS($block->getSomeString()); ?>
83+
<?= $block->escapeJS($block->getData('html_id')) ?>
84+
<?= $block->escapeJavaScript($block->getData('html_id')) ?>
85+
<?= $block->escapeQuotes(__($block->getData('welcome'))); ?>
86+
<?= $block->escapeURL($block->getUrl('adminhtml/notification/index')) ?>
87+
</section>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/** @var Magento\Framework\View\Element\Template $block */
3+
/** @var Magento\Framework\Escaper $escaper */
4+
?>
5+
6+
<section>
7+
<h1>This unescaped output is fine here; other sniffs will complain about it though.</h1>
8+
9+
<?php echo $block->getSomeString(); ?>
10+
<?= $block->getSomeString(); ?>
11+
<?= /** @noEscape */ $block->getSomeString(); ?>
12+
<?= /** @escapeNotVerified */ $block->getSomeString(); ?>
13+
</section>
14+
15+
<section>
16+
<h1>These should be using equivalent methods on the `$escaper` class, not the `$block` class.</h1>
17+
18+
Note that I couldn't find any use of this method in any templates within Magento.
19+
<?= $escaper->escapeCss($block->getSomeString()); ?>
20+
21+
<?= $escaper->escapeHtml(__($block->getSomeString())) ?>
22+
<?= $escaper->escapeHtml(__($block->getSomeString())); ?>
23+
<?= $escaper->escapeHtml(__($block->getSomeString()), ['strong', 'em', 'span']) ?>
24+
25+
<div class="<?= $escaper->escapeHtmlAttr($block->getSomeString()) ?>"></div>
26+
<div class="<?= $escaper->escapeHtmlAttr($block->getSomeString(), true) ?>"></div>
27+
<div class="<?= $escaper->escapeHtmlAttr($block->getSomeString(), false); ?>"></div>
28+
29+
<script type="text/x-magento-init">
30+
{
31+
"#chart_<?= $escaper->escapeJs($block->getData('html_id')) ?>_period": {
32+
"Magento_Backend/js/dashboard/chart": {}
33+
}
34+
}
35+
</script>
36+
37+
The only example of this method being used was in a block class, rather than a template.
38+
<?php
39+
foreach ($block->getItems() as $item) {
40+
$item['sku'] = $escaper->escapeJsQuote($item['sku']);
41+
}
42+
?>
43+
44+
The only example of this method being used was in a block class, rather than a template.
45+
<?= $escaper->escapeQuote(__($block->getData('welcome'))); ?>
46+
47+
<a href="<?= $escaper->escapeUrl($block->getUrl('adminhtml/notification/index')) ?>"> link text </a>
48+
49+
Note that I couldn't find any use of this method in any templates within Magento.
50+
<?= $escaper->escapeXssInUrl($block->getSomeString()); ?>
51+
</section>
52+
53+
<section>
54+
<h1>These are edge cases for formatting differences</h1>
55+
56+
<?php
57+
$escaper->escapeHtml('');
58+
$escaper ->escapeHtml('');
59+
$escaper-> escapeHtml('');
60+
$escaper
61+
->escapeHtml('');
62+
$escaper
63+
64+
->escapeHtml('');
65+
$escaper->
66+
escapeHtml('');
67+
$escaper-> // comment
68+
escapeHtml('');
69+
$escaper /* comment */
70+
->escapeHtml('');
71+
72+
$escaper /* comment */ -> /* comment */ escapeHtml('');
73+
?>
74+
</section>
75+
76+
<section>
77+
<h1>These close-matches shouldn't be flagged by this sniff.</h1>
78+
79+
<?= $block->escapeHTML(__($block->getSomeString())) ?>
80+
<?= $block->escapeHtmlString(__($block->getSomeString())) ?>
81+
<?= $block->escapeHtmlAttribute($block->getSomeString()) ?>
82+
<?= $block->escapeCSS($block->getSomeString()); ?>
83+
<?= $block->escapeJS($block->getData('html_id')) ?>
84+
<?= $block->escapeJavaScript($block->getData('html_id')) ?>
85+
<?= $block->escapeQuotes(__($block->getData('welcome'))); ?>
86+
<?= $block->escapeURL($block->getUrl('adminhtml/notification/index')) ?>
87+
</section>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento2\Tests\Legacy;
9+
10+
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
11+
12+
class EscapeMethodsOnBlockClassUnitTest extends AbstractSniffUnitTest
13+
{
14+
protected function getErrorList()
15+
{
16+
return [];
17+
}
18+
19+
protected function getWarningList()
20+
{
21+
return [
22+
19 => 1,
23+
21 => 1,
24+
22 => 1,
25+
23 => 1,
26+
25 => 1,
27+
26 => 1,
28+
27 => 1,
29+
31 => 1,
30+
40 => 1,
31+
45 => 1,
32+
47 => 1,
33+
50 => 1,
34+
57 => 1,
35+
58 => 1,
36+
59 => 1,
37+
61 => 1,
38+
64 => 1,
39+
66 => 1,
40+
68 => 1,
41+
70 => 1,
42+
72 => 1,
43+
];
44+
}
45+
}

0 commit comments

Comments
 (0)