Skip to content

Commit b8d2c96

Browse files
authored
Merge pull request #95 from magento-commerce/imported-svera-magento-coding-standard-309
[Imported] AC-683: Create phpcs static check for TableTest
2 parents fbd5b1d + ceeba56 commit b8d2c96

File tree

3 files changed

+306
-0
lines changed

3 files changed

+306
-0
lines changed
+234
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
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+
* Coverage of obsolete table names usage
15+
*/
16+
class TableNameSniff implements Sniff
17+
{
18+
/**
19+
* Methods which receive table names as parameters, with the argument position in which table names are passed
20+
*
21+
* @var array
22+
*/
23+
private $argPositionInMethods = [
24+
'getTableName' => [0],
25+
'_setMainTable' => [0],
26+
'setMainTable' => [0],
27+
'getTable' => [0],
28+
'setTable' => [0],
29+
'getTableRow' => [0],
30+
'deleteTableRow' => [0],
31+
'updateTableRow' => [0],
32+
'updateTable' => [0],
33+
'tableExists' => [0],
34+
'joinField' => [1],
35+
'joinTable' => [0],
36+
'getFkName' => [0, 2],
37+
'getIdxName' => [0],
38+
'addVirtualGridColumn' => [1],
39+
];
40+
41+
/**
42+
* String representation of error.
43+
*
44+
* @var string
45+
*/
46+
private const ERROR_MESSAGE = 'Legacy table names with slash must be fixed to direct table names. Found: %s';
47+
48+
/**
49+
* Error violation code.
50+
*
51+
* @var string
52+
*/
53+
private const ERROR_CODE = 'FoundLegacyTableName';
54+
55+
/**
56+
* @inheritdoc
57+
*/
58+
public function register()
59+
{
60+
return [
61+
T_OBJECT_OPERATOR,
62+
T_VARIABLE,
63+
T_DOUBLE_ARROW
64+
];
65+
}
66+
67+
/**
68+
* @inheritdoc
69+
*/
70+
public function process(File $phpcsFile, $stackPtr)
71+
{
72+
$tokens = $phpcsFile->getTokens();
73+
if ($tokens[$stackPtr]['code'] === T_OBJECT_OPERATOR) {
74+
$this->checkOccurrencesInMethods($phpcsFile, $stackPtr, $tokens);
75+
} elseif ($tokens[$stackPtr]['code'] === T_DOUBLE_ARROW) {
76+
$this->checkOccurrencesInArray($phpcsFile, $stackPtr, $tokens);
77+
} else {
78+
$this->checkOccurrencesInProperty($phpcsFile, $stackPtr, $tokens);
79+
}
80+
}
81+
82+
/**
83+
* Check if passed file is a resource but not a collection
84+
*
85+
* @param string $filePath
86+
* @return bool
87+
*/
88+
private function isResourceButNotCollection(string $filePath): bool
89+
{
90+
$filePath = str_replace('\\', '/', $filePath);
91+
$parts = explode('/', $filePath);
92+
return array_search('Resource', $parts) !== false && array_search('Collection.php', $parts) === false;
93+
}
94+
95+
/**
96+
* Check references to table names in methods
97+
*
98+
* @param File $phpcsFile
99+
* @param int $stackPtr
100+
* @param array $tokens
101+
*/
102+
private function checkOccurrencesInMethods(File $phpcsFile, int $stackPtr, array $tokens): void
103+
{
104+
$methodNamePos = $phpcsFile->findNext(T_STRING, $stackPtr + 1);
105+
$methodName = $tokens[$methodNamePos]['content'];
106+
if (array_key_exists($methodName, $this->argPositionInMethods) === false) {
107+
return;
108+
}
109+
$firstArgumentPos = $phpcsFile->findNext([T_CONSTANT_ENCAPSED_STRING, T_VARIABLE], $methodNamePos + 1);
110+
111+
foreach ($this->argPositionInMethods[$methodName] as $argPosition) {
112+
$paramPos = $firstArgumentPos;
113+
for ($i = 0; $i < $argPosition; $i++) {
114+
$paramPos = $phpcsFile->findNext(
115+
[T_CONSTANT_ENCAPSED_STRING, T_VARIABLE],
116+
$paramPos + 1,
117+
$phpcsFile->findNext(T_CLOSE_PARENTHESIS, $paramPos + 1)
118+
);
119+
}
120+
if (strpos($tokens[$paramPos]['content'], '/') !== false) {
121+
$phpcsFile->addError(
122+
sprintf(
123+
self::ERROR_MESSAGE,
124+
$tokens[$paramPos]['content'],
125+
),
126+
$paramPos,
127+
self::ERROR_CODE
128+
);
129+
}
130+
}
131+
132+
if ($this->isResourceButNotCollection($phpcsFile->getFilename())) {
133+
if ($tokens[$stackPtr]['content'] !== '_init') {
134+
return;
135+
}
136+
137+
$paramPos = $phpcsFile->findNext(T_PARAM_NAME, $stackPtr + 1);
138+
if (strpos($tokens[$paramPos]['content'], '/') !== false) {
139+
$phpcsFile->addError(
140+
sprintf(
141+
self::ERROR_MESSAGE,
142+
$tokens[$paramPos]['content'],
143+
),
144+
$paramPos,
145+
self::ERROR_CODE
146+
);
147+
}
148+
}
149+
}
150+
151+
/**
152+
* Check references to table names in the $_aggregationTable property
153+
*
154+
* @param File $phpcsFile
155+
* @param int $stackPtr
156+
* @param array $tokens
157+
*/
158+
private function checkOccurrencesInProperty(File $phpcsFile, int $stackPtr, array $tokens): void
159+
{
160+
if ($methodName = $tokens[$stackPtr]['content'] !== '$_aggregationTable') {
161+
return;
162+
}
163+
164+
$tableNamePos = $phpcsFile->findNext(
165+
T_CONSTANT_ENCAPSED_STRING,
166+
$stackPtr + 1,
167+
$phpcsFile->findEndOfStatement($stackPtr + 1)
168+
);
169+
170+
if (strpos($tokens[$tableNamePos]['content'], '/') !== false) {
171+
$phpcsFile->addError(
172+
sprintf(
173+
self::ERROR_MESSAGE,
174+
$tokens[$tableNamePos]['content'],
175+
),
176+
$tableNamePos,
177+
self::ERROR_CODE
178+
);
179+
}
180+
}
181+
182+
/**
183+
* Check references to table names in arrays
184+
*
185+
* @param File $phpcsFile
186+
* @param int $stackPtr
187+
* @param array $tokens
188+
*/
189+
private function checkOccurrencesInArray(File $phpcsFile, int $stackPtr, array $tokens): void
190+
{
191+
$aliasPos = $phpcsFile->findPrevious(
192+
T_CONSTANT_ENCAPSED_STRING,
193+
$stackPtr -1
194+
);
195+
196+
$alias = trim($tokens[$aliasPos]['content'], '\'"');
197+
198+
if ($this->endsWith($alias, '_table') === false) {
199+
return;
200+
}
201+
202+
$tableNamePos = $phpcsFile->findNext(
203+
T_CONSTANT_ENCAPSED_STRING,
204+
$aliasPos + 1
205+
);
206+
207+
if (strpos($tokens[$tableNamePos]['content'], '/') !== false) {
208+
$phpcsFile->addError(
209+
sprintf(
210+
self::ERROR_MESSAGE,
211+
$tokens[$tableNamePos]['content'],
212+
),
213+
$tableNamePos,
214+
self::ERROR_CODE
215+
);
216+
}
217+
}
218+
219+
/**
220+
* Checks if $haystack ends with $needle
221+
*
222+
* @param string $haystack
223+
* @param string $needle
224+
* @return bool
225+
*/
226+
private function endsWith(string $haystack, string $needle): bool
227+
{
228+
$length = strlen($needle);
229+
if ($length === 0) {
230+
return true;
231+
}
232+
return substr($haystack, -$length) === $needle;
233+
}
234+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
$productTable = $this->_resource->getTableName('/catalog_category_product');
4+
5+
$collection->joinField(
6+
'inventory_in_stock',
7+
'/cataloginventory_stock_item',
8+
'is_in_stock',
9+
'product_id=entity_id',
10+
'(' . join(') OR (', $cond) . ')'
11+
);
12+
13+
$collection->getFkName(
14+
'inventory_in_stock',
15+
$collection,
16+
'/is_in_stock'
17+
);
18+
19+
$select = $connection->select()->from(
20+
['main_table' => 'magento/sample_table']
21+
);
22+
23+
$select = $connection->select()->from(
24+
['main_table_name' => 'magento/sample_table']
25+
);
26+
27+
$select = $connection->select()->from(
28+
['main_table' => 'magento_sample_table']
29+
);
30+
31+
class Collection extends \Magento\Sales\Model\ResourceModel\Report\Order\Collection
32+
{
33+
/**
34+
* Aggregated Data Table
35+
*
36+
* @var string
37+
*/
38+
protected $_aggregationTable = 'magento/sales_order_aggregated_updated';
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
/**
3+
* Copyright © Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento2\Tests\Legacy;
7+
8+
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
9+
10+
class TableNameUnitTest extends AbstractSniffUnitTest
11+
{
12+
/**
13+
* @inheritdoc
14+
*/
15+
public function getErrorList($testFile = '')
16+
{
17+
return [
18+
3 => 1,
19+
7 => 1,
20+
16 => 1,
21+
20 => 1,
22+
38 => 1,
23+
];
24+
}
25+
26+
/**
27+
* @inheritdoc
28+
*/
29+
public function getWarningList($testFile = '')
30+
{
31+
return [];
32+
}
33+
}

0 commit comments

Comments
 (0)