Skip to content

Commit 082e6b8

Browse files
authored
Merge pull request #86 from magento-commerce/imported-svera-magento-coding-standard-300
[Imported] AC-682: Create phpcs static check for RestrictedCodeTest
2 parents 72bd288 + 6057057 commit 082e6b8

File tree

7 files changed

+362
-0
lines changed

7 files changed

+362
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types = 1);
7+
8+
namespace Magento2\Sniffs\Legacy;
9+
10+
use PHP_CodeSniffer\Sniffs\Sniff;
11+
use PHP_CodeSniffer\Files\File;
12+
13+
/**
14+
* Tests to find usage of restricted code
15+
*/
16+
class RestrictedCodeSniff implements Sniff
17+
{
18+
private const ERROR_MESSAGE = "Class '%s' is restricted in %s. Suggested replacement: %s";
19+
private const ERROR_CODE = "restrictedClass";
20+
21+
/**
22+
* List of fixtures that contain restricted classes and should not be tested
23+
*
24+
* @var array
25+
*/
26+
private $fixtureFiles = [];
27+
28+
/**
29+
* Restricted classes
30+
*
31+
* @var array
32+
*/
33+
private $classes = [];
34+
35+
/**
36+
* RestrictedCodeSniff constructor.
37+
*/
38+
public function __construct()
39+
{
40+
$this->loadData('restricted_classes*.php');
41+
}
42+
43+
/**
44+
* @inheritdoc
45+
*/
46+
public function register()
47+
{
48+
return [
49+
T_STRING,
50+
T_CONSTANT_ENCAPSED_STRING
51+
];
52+
}
53+
54+
/**
55+
* @inheritdoc
56+
*/
57+
public function process(File $phpcsFile, $stackPtr)
58+
{
59+
// phpcs:ignore
60+
if (array_key_exists(basename($phpcsFile->getFilename()), $this->fixtureFiles)) {
61+
return;
62+
}
63+
64+
$tokens = $phpcsFile->getTokens();
65+
$token = $tokens[$stackPtr]['content'];
66+
if (array_key_exists($token, $this->classes)) {
67+
if ($this->isExcluded($token, $phpcsFile)) {
68+
return;
69+
}
70+
$phpcsFile->addError(
71+
sprintf(
72+
self::ERROR_MESSAGE,
73+
$token,
74+
$phpcsFile->getFilename(),
75+
$this->classes[$token]['replacement']
76+
),
77+
$stackPtr,
78+
self::ERROR_CODE,
79+
);
80+
}
81+
}
82+
83+
/**
84+
* Checks if currently parsed file should be excluded from analysis
85+
*
86+
* @param string $token
87+
* @param File $phpcsFile
88+
* @return bool
89+
*/
90+
private function isExcluded(string $token, File $phpcsFile): bool
91+
{
92+
if (in_array($phpcsFile->getFilename(), $this->fixtureFiles)) {
93+
return true;
94+
}
95+
foreach ($this->classes[$token]['exclude'] as $exclude) {
96+
if (strpos($phpcsFile->getFilename(), $exclude) !== false) {
97+
return true;
98+
}
99+
}
100+
return false;
101+
}
102+
103+
/**
104+
* Loads and merges data from fixtures
105+
*
106+
* @param string $filePattern
107+
* @return void
108+
*/
109+
private function loadData(string $filePattern)
110+
{
111+
// phpcs:ignore
112+
foreach (glob(__DIR__ . '/_files/' . $filePattern) as $file) {
113+
$relativePath = str_replace(
114+
'\\',
115+
'/',
116+
str_replace(__DIR__ . DIRECTORY_SEPARATOR, '', $file)
117+
);
118+
array_push($this->fixtureFiles, $relativePath);
119+
$this->classes = array_merge_recursive($this->classes, $this->readList($file));
120+
}
121+
}
122+
123+
/**
124+
* Isolate including a file into a method to reduce scope
125+
*
126+
* @param string $file
127+
* @return array
128+
*/
129+
private function readList($file)
130+
{
131+
// phpcs:ignore
132+
return include $file;
133+
}
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/**
8+
* Classes that are restricted to use directly.
9+
* A <replacement> will be suggested to be used instead.
10+
* Use <whitelist> to specify files and directories that are allowed to use restricted classes.
11+
*
12+
* Format: array(<class_name>, <replacement>[, array(<whitelist>)]])
13+
*/
14+
return [
15+
'Zend_Db_Select' => [
16+
'replacement' => '\Magento\Framework\DB\Select',
17+
'exclude' => [
18+
'Magento/Framework/DB/Select.php',
19+
'Magento/Framework/DB/Adapter/Pdo/Mysql.php',
20+
'Magento/Framework/Model/ResourceModel/Iterator.php'
21+
]
22+
],
23+
'Zend_Db_Adapter_Pdo_Mysql' => [
24+
'replacement' => '\Magento\Framework\DB\Adapter\Pdo\Mysql',
25+
'exclude' => [
26+
'Magento/Framework/DB/Adapter/Pdo/Mysql.php'
27+
]
28+
],
29+
'Magento\Framework\Serialize\Serializer\Serialize' => [
30+
'replacement' => 'Magento\Framework\Serialize\SerializerInterface',
31+
'exclude' => [
32+
'Magento/Framework/App/ObjectManager/ConfigLoader/Compiled.php',
33+
'Magento/Framework/App/Config/ScopePool.php',
34+
'Magento/Framework/App/ObjectManager/ConfigCache.php',
35+
'Magento/Framework/App/ObjectManager/ConfigLoader.php',
36+
'Magento/Framework/DB/Adapter/Pdo/Mysql.php',
37+
'Magento/Framework/DB/DataConverter/SerializedToJson.php',
38+
'Magento/Framework/DB/Test/Unit/DataConverter/SerializedToJsonTest.php',
39+
'Magento/Framework/ObjectManager/Config/Compiled.php',
40+
'Magento/Framework/Interception/Config/Config.php',
41+
'Magento/Framework/Interception/PluginList/PluginList.php',
42+
'Magento/Framework/App/Router/ActionList.php',
43+
'Magento/Framework/Serialize/Test/Unit/Serializer/SerializeTest.php',
44+
'src/Magento/Setup/Module/Di/Compiler/Config/Writer/Filesystem.php',
45+
'Magento/Sales/Setup/SerializedDataConverter.php',
46+
'Magento/Sales/Test/Unit/Setup/SerializedDataConverterTest.php',
47+
'Magento/Sales/Test/Unit/Setup/SalesOrderPaymentDataConverterTest.php',
48+
'Magento/Framework/Flag.php',
49+
'Magento/Widget/Setup/LayoutUpdateConverter.php',
50+
'Magento/Cms/Setup/ContentConverter.php',
51+
'Magento/Framework/Unserialize/Test/Unit/UnserializeTest.php'
52+
]
53+
],
54+
'ArrayObject' => [
55+
'replacement' => 'Custom class, extended from ArrayObject with overwritten serialize/unserialize methods',
56+
'exclude' => [
57+
'Magento/Theme/Model/Indexer/Design/Config.php',
58+
'Magento/Ui/Model/Manager.php',
59+
'Magento/Ui/Test/Unit/Model/ManagerTest.php',
60+
'Magento/Backend/Model/Menu.php',
61+
'Magento/CatalogSearch/Model/Indexer/Fulltext.php',
62+
'Magento/CatalogSearch/Test/Unit/Model/Indexer/FulltextTest.php',
63+
'Magento/Catalog/Test/Unit/Model/ProductTest.php',
64+
'Magento/CatalogSearch/Model/Indexer/Fulltext.php',
65+
'Magento/Framework/Test/Unit/FlagTest.php',
66+
'Magento/Framework/Validator/Test/Unit/Constraint/PropertyTest.php',
67+
'Magento/Framework/Indexer/Test/Unit/BatchTest.php',
68+
'Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php',
69+
'Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php',
70+
'Magento/Framework/Indexer/Action/Base.php'
71+
]
72+
],
73+
'Magento\Framework\View\Element\UiComponent\ArrayObjectFactory' => [
74+
'replacement' => 'Factory that creates custom class, extended from ArrayObject with overwritten '
75+
. 'serialize/unserialize methods',
76+
'exclude' => [
77+
'Magento/Ui/Model/Manager.php',
78+
'Magento/Ui/Test/Unit/Model/ManagerTest.php',
79+
'Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php',
80+
]
81+
]
82+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
/**
3+
* Classes that are restricted to use directly.
4+
* A <replacement> will be suggested to be used instead.
5+
* Use <whitelist> to specify files and directories that are allowed to use restricted classes.
6+
*
7+
* Format: array(<class_name>, <replacement>[, array(<whitelist>)]])
8+
*
9+
* Copyright © Magento, Inc. All rights reserved.
10+
* See COPYING.txt for license details.
11+
*/
12+
return [
13+
'Zend_Db_Select' => [
14+
'exclude' => [
15+
'Magento/ResourceConnections/DB/Adapter/Pdo/MysqlProxy.php'
16+
],
17+
],
18+
'Magento\Framework\Serialize\Serializer\Serialize' => [
19+
'exclude' => [
20+
'Magento/Framework/Test/Unit/FlagTest.php',
21+
'Magento/Staging/Test/Unit/Model/Update/FlagTest.php',
22+
'Magento/Logging/Test/Unit/Setup/ObjectConverterTest.php'
23+
]
24+
],
25+
'ArrayObject' => [
26+
'exclude' => [
27+
'Magento/MultipleWishlist/Test/Unit/Model/Search/Strategy/EmailTest.php',
28+
'Magento/Rma/Test/Unit/Model/RmaRepositoryTest.php',
29+
'Magento/Rma/Test/Unit/Model/Status/HistoryRepositoryTest.php'
30+
]
31+
]
32+
];
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+
namespace Magento2\Tests\Legacy;
7+
8+
use DirectoryIterator;
9+
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
10+
use RecursiveDirectoryIterator;
11+
use RecursiveIteratorIterator;
12+
13+
class RestrictedCodeUnitTest extends AbstractSniffUnitTest
14+
{
15+
16+
/**
17+
* @inheritdoc
18+
*/
19+
protected function getTestFiles($testFileBase): array
20+
{
21+
$testFiles = [];
22+
23+
$dir = __DIR__.'/_files/RestrictedCodeUnitTest';
24+
$di = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
25+
26+
/**
27+
* @var DirectoryIterator $file
28+
*/
29+
foreach ($di as $file) {
30+
if ($file->isDir()) {
31+
continue;
32+
}
33+
$testFiles[] = $file->getPathname();
34+
}
35+
36+
// Put them in order.
37+
sort($testFiles);
38+
39+
return $testFiles;
40+
}
41+
42+
/**
43+
* @inheritdoc
44+
*/
45+
public function getErrorList($testFile = '')
46+
{
47+
if ($testFile === 'FileWithRestrictedClass.inc') {
48+
return [
49+
5 => 1,
50+
];
51+
}
52+
return [];
53+
}
54+
55+
/**
56+
* @inheritdoc
57+
*/
58+
public function getWarningList()
59+
{
60+
return [];
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
function getCheckSql($expression, $true, $false)
4+
{
5+
if ($expression instanceof \Zend_Db_Expr || $expression instanceof \Zend_Db_Select) {
6+
$expression = sprintf("IF((%s), %s, %s)", $expression, $true, $false);
7+
} else {
8+
$expression = sprintf("IF(%s, %s, %s)", $expression, $true, $false);
9+
}
10+
11+
return new \Zend_Db_Expr($expression);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
4+
5+
/**
6+
* Copyright © Magento, Inc. All rights reserved.
7+
* See COPYING.txt for license details.
8+
*/
9+
10+
/**
11+
* This is NOT actually a test, but a file that must be ignored by RestrictedCodeSniff
12+
* when doing its analysis, even if it contains restricted classes.
13+
* We need this file to have the exact expected path, even with the PHP extension that makes AbstractSniffUnitTest
14+
* to recognize this as an actual test file instead of a fixture.
15+
*/
16+
class IteratorDummyFile extends AbstractSniffUnitTest
17+
{
18+
protected function shouldSkipTest()
19+
{
20+
return true;
21+
}
22+
23+
protected function getErrorList() {
24+
return [];
25+
}
26+
27+
protected function getWarningList() {
28+
return [];
29+
}
30+
31+
private function withProtectedClass() {
32+
return new \Zend_Db_Expr();
33+
}
34+
}

Magento2/ruleset.xml

+6
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@
142142
<type>error</type>
143143
<exclude-pattern>*\.xml$</exclude-pattern>
144144
</rule>
145+
<rule ref="Magento2.Legacy.RestrictedCode">
146+
<severity>10</severity>
147+
<type>error</type>
148+
<exclude-pattern>*\.xml$</exclude-pattern>
149+
<exclude-pattern>*\.js$</exclude-pattern>
150+
</rule>
145151
<!-- Severity 9 warnings: Possible security and issues that may cause bugs. -->
146152
<rule ref="Generic.Files.ByteOrderMark">
147153
<severity>9</severity>

0 commit comments

Comments
 (0)