From bf6420569a35a1905996e7585159a7cd71e3ce51 Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 6 Oct 2021 15:12:23 +0200 Subject: [PATCH 1/5] AC-683: Create phpcs static check for TableTest --- Magento2/Sniffs/Legacy/TableNameSniff.php | 234 ++++++++++++++++++++ Magento2/Tests/Legacy/TableNameUnitTest.inc | 39 ++++ Magento2/Tests/Legacy/TableNameUnitTest.php | 32 +++ 3 files changed, 305 insertions(+) create mode 100644 Magento2/Sniffs/Legacy/TableNameSniff.php create mode 100644 Magento2/Tests/Legacy/TableNameUnitTest.inc create mode 100644 Magento2/Tests/Legacy/TableNameUnitTest.php diff --git a/Magento2/Sniffs/Legacy/TableNameSniff.php b/Magento2/Sniffs/Legacy/TableNameSniff.php new file mode 100644 index 00000000..9181909f --- /dev/null +++ b/Magento2/Sniffs/Legacy/TableNameSniff.php @@ -0,0 +1,234 @@ + [0], + '_setMainTable' => [0], + 'setMainTable' => [0], + 'getTable' => [0], + 'setTable' => [0], + 'getTableRow' => [0], + 'deleteTableRow' => [0], + 'updateTableRow' => [0], + 'updateTable' => [0], + 'tableExists' => [0], + 'joinField' => [1], + 'joinTable' => [0], + 'getFkName' => [0, 2], + 'getIdxName' => [0], + 'addVirtualGridColumn' => [1], + ]; + + /** + * String representation of error. + * + * @var string + */ + private const ERROR_MESSAGE = 'Legacy table names with slash must be fixed to direct table names. Found: %s'; + + /** + * Error violation code. + * + * @var string + */ + private const ERROR_CODE = 'FoundLegacyTableName'; + + /** + * @inheritdoc + */ + public function register() + { + return [ + T_OBJECT_OPERATOR, + T_VARIABLE, + T_DOUBLE_ARROW + ]; + } + + /** + * @inheritdoc + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if ($tokens[$stackPtr]['code'] === T_OBJECT_OPERATOR) { + $this->checkOccurrencesInMethods($phpcsFile, $stackPtr, $tokens); + } elseif ($tokens[$stackPtr]['code'] === T_DOUBLE_ARROW) { + $this->checkOccurrencesInArray($phpcsFile, $stackPtr, $tokens); + } else { + $this->checkOccurrencesInProperty($phpcsFile, $stackPtr, $tokens); + } + } + + /** + * Check if passed file is a resource but not a collection + * + * @param string $filePath + * @return bool + */ + private function isResourceButNotCollection(string $filePath): bool + { + $filePath = str_replace('\\', '/', $filePath); + $parts = explode('/', $filePath); + return array_search('Resource', $parts) !== false && array_search('Collection.php', $parts) === false; + } + + /** + * Check references to table names in methods + * + * @param File $phpcsFile + * @param int $stackPtr + * @param array $tokens + */ + private function checkOccurrencesInMethods(File $phpcsFile, int $stackPtr, array $tokens): void + { + $methodNamePos = $phpcsFile->findNext(T_STRING, $stackPtr + 1); + $methodName = $tokens[$methodNamePos]['content']; + if (array_key_exists($methodName, $this->argPositionInMethods) === false) { + return; + } + $firstArgumentPos = $phpcsFile->findNext([T_CONSTANT_ENCAPSED_STRING, T_VARIABLE], $methodNamePos + 1); + + foreach ($this->argPositionInMethods[$methodName] as $argPosition) { + $paramPos = $firstArgumentPos; + for ($i = 0; $i < $argPosition; $i++) { + $paramPos = $phpcsFile->findNext( + [T_CONSTANT_ENCAPSED_STRING, T_VARIABLE], + $paramPos + 1, + $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $paramPos + 1) + ); + } + if (strpos($tokens[$paramPos]['content'], '/') !== false) { + $phpcsFile->addError( + sprintf( + self::ERROR_MESSAGE, + $tokens[$paramPos]['content'], + ), + $paramPos, + self::ERROR_CODE + ); + } + } + + if ($this->isResourceButNotCollection($phpcsFile->getFilename())) { + if ($tokens[$stackPtr]['content'] !== '_init') { + return; + } + + $paramPos = $phpcsFile->findNext(T_PARAM_NAME, $stackPtr + 1); + if (strpos($tokens[$paramPos]['content'], '/') !== false) { + $phpcsFile->addError( + sprintf( + self::ERROR_MESSAGE, + $tokens[$paramPos]['content'], + ), + $paramPos, + self::ERROR_CODE + ); + } + } + } + + /** + * Check references to table names in the $_aggregationTable property + * + * @param File $phpcsFile + * @param int $stackPtr + * @param array $tokens + */ + private function checkOccurrencesInProperty(File $phpcsFile, int $stackPtr, array $tokens): void + { + if ($methodName = $tokens[$stackPtr]['content'] !== '$_aggregationTable') { + return; + } + + $tableNamePos = $phpcsFile->findNext( + T_CONSTANT_ENCAPSED_STRING, + $stackPtr + 1, + $phpcsFile->findEndOfStatement($stackPtr + 1) + ); + + if (strpos($tokens[$tableNamePos]['content'], '/') !== false) { + $phpcsFile->addError( + sprintf( + self::ERROR_MESSAGE, + $tokens[$tableNamePos]['content'], + ), + $tableNamePos, + self::ERROR_CODE + ); + } + } + + /** + * Check references to table names in arrays + * + * @param File $phpcsFile + * @param int $stackPtr + * @param array $tokens + */ + private function checkOccurrencesInArray(File $phpcsFile, int $stackPtr, array $tokens): void + { + $aliasPos = $phpcsFile->findPrevious( + T_CONSTANT_ENCAPSED_STRING, + $stackPtr -1 + ); + + $alias = trim($tokens[$aliasPos]['content'], '\'"'); + + if ($this->endsWith($alias, '_table') === false) { + return; + } + + $tableNamePos = $phpcsFile->findNext( + T_CONSTANT_ENCAPSED_STRING, + $aliasPos + 1 + ); + + if (strpos($tokens[$tableNamePos]['content'], '/') !== false) { + $phpcsFile->addError( + sprintf( + self::ERROR_MESSAGE, + $tokens[$tableNamePos]['content'], + ), + $tableNamePos, + self::ERROR_CODE + ); + } + } + + /** + * Checks if $haystack ends with $needle + * + * @param string $haystack + * @param string $needle + * @return bool + */ + private function endsWith(string $haystack, string $needle): bool + { + $length = strlen($needle); + if ($length === 0) { + return true; + } + return substr($haystack, -$length) === $needle; + } +} diff --git a/Magento2/Tests/Legacy/TableNameUnitTest.inc b/Magento2/Tests/Legacy/TableNameUnitTest.inc new file mode 100644 index 00000000..a1f2520e --- /dev/null +++ b/Magento2/Tests/Legacy/TableNameUnitTest.inc @@ -0,0 +1,39 @@ +_resource->getTableName('/catalog_category_product'); + +$collection->joinField( + 'inventory_in_stock', + '/cataloginventory_stock_item', + 'is_in_stock', + 'product_id=entity_id', + '(' . join(') OR (', $cond) . ')' +); + +$collection->getFkName( + 'inventory_in_stock', + $collection, + '/is_in_stock' +); + +$select = $connection->select()->from( + ['main_table' => 'magento/sample_table'] +); + +$select = $connection->select()->from( + ['main_table_name' => 'magento/sample_table'] +); + +$select = $connection->select()->from( + ['main_table' => 'magento_sample_table'] +); + +class Collection extends \Magento\Sales\Model\ResourceModel\Report\Order\Collection +{ + /** + * Aggregated Data Table + * + * @var string + */ + protected $_aggregationTable = 'magento/sales_order_aggregated_updated'; +} \ No newline at end of file diff --git a/Magento2/Tests/Legacy/TableNameUnitTest.php b/Magento2/Tests/Legacy/TableNameUnitTest.php new file mode 100644 index 00000000..94eb10bc --- /dev/null +++ b/Magento2/Tests/Legacy/TableNameUnitTest.php @@ -0,0 +1,32 @@ + 1, + 7 => 1, + 14 => 1, + 28 => 1,*/ + ]; + } + + /** + * @inheritdoc + */ + public function getWarningList($testFile = '') + { + return []; + } +} From eb3ad4749a6f9fa56548ade1804dd281d186fdac Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 6 Oct 2021 15:44:19 +0200 Subject: [PATCH 2/5] AC-683: Create phpcs static check for TableTest --- Magento2/Tests/Legacy/TableNameUnitTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Magento2/Tests/Legacy/TableNameUnitTest.php b/Magento2/Tests/Legacy/TableNameUnitTest.php index 94eb10bc..4cfade20 100644 --- a/Magento2/Tests/Legacy/TableNameUnitTest.php +++ b/Magento2/Tests/Legacy/TableNameUnitTest.php @@ -15,10 +15,11 @@ class TableNameUnitTest extends AbstractSniffUnitTest public function getErrorList($testFile = '') { return [ - /*3 => 1, + 3 => 1, 7 => 1, 14 => 1, - 28 => 1,*/ + 20 => 1, + 28 => 1, ]; } From a1c933a4c19c0c4a5f06df818475aa8067f136be Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 6 Oct 2021 15:47:09 +0200 Subject: [PATCH 3/5] AC-683: Create phpcs static check for TableTest --- Magento2/Tests/Legacy/TableNameUnitTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Magento2/Tests/Legacy/TableNameUnitTest.php b/Magento2/Tests/Legacy/TableNameUnitTest.php index 4cfade20..eec07bfe 100644 --- a/Magento2/Tests/Legacy/TableNameUnitTest.php +++ b/Magento2/Tests/Legacy/TableNameUnitTest.php @@ -17,9 +17,9 @@ public function getErrorList($testFile = '') return [ 3 => 1, 7 => 1, - 14 => 1, + 16 => 1, 20 => 1, - 28 => 1, + 38 => 1, ]; } From 1452ed3dd49f11b2b7743048595e19e02e45f402 Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 6 Oct 2021 16:03:05 +0200 Subject: [PATCH 4/5] AC-683: Create phpcs static check for TableTest --- Magento2/Sniffs/Legacy/TableNameSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Magento2/Sniffs/Legacy/TableNameSniff.php b/Magento2/Sniffs/Legacy/TableNameSniff.php index 9181909f..b9a9081f 100644 --- a/Magento2/Sniffs/Legacy/TableNameSniff.php +++ b/Magento2/Sniffs/Legacy/TableNameSniff.php @@ -114,7 +114,7 @@ private function checkOccurrencesInMethods(File $phpcsFile, int $stackPtr, array $paramPos = $phpcsFile->findNext( [T_CONSTANT_ENCAPSED_STRING, T_VARIABLE], $paramPos + 1, - $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $paramPos + 1) + $phpcsFile->findNext(T_CLOSE_PARENTHESIS, $paramPos + 1) ); } if (strpos($tokens[$paramPos]['content'], '/') !== false) { From ceeba5613137c69a0ec0d8f86af56b5948c7a873 Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 6 Oct 2021 17:02:31 +0200 Subject: [PATCH 5/5] AC-683: Create phpcs static check for TableTest --- Magento2/Tests/Legacy/TableNameUnitTest.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Magento2/Tests/Legacy/TableNameUnitTest.inc b/Magento2/Tests/Legacy/TableNameUnitTest.inc index a1f2520e..d3b46079 100644 --- a/Magento2/Tests/Legacy/TableNameUnitTest.inc +++ b/Magento2/Tests/Legacy/TableNameUnitTest.inc @@ -36,4 +36,4 @@ class Collection extends \Magento\Sales\Model\ResourceModel\Report\Order\Collect * @var string */ protected $_aggregationTable = 'magento/sales_order_aggregated_updated'; -} \ No newline at end of file +}