From 1ba56bb139b355477ba323ccd2951f75b449e4db Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 29 Sep 2021 13:10:24 +0200 Subject: [PATCH 01/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 446 +++++++++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 Magento2/Sniffs/Legacy/LayoutSniff.php diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php new file mode 100644 index 00000000..7341e87c --- /dev/null +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -0,0 +1,446 @@ + [ + 'adminhtml.permissions.user.edit.tabs', + 'adminhtml.permission.user.edit.tabs', + 'adminhtml.permissions.user.edit', + 'adminhtml.permission.user.edit', + 'adminhtml.permissions.user.roles.grid.js', + 'adminhtml.permission.user.roles.grid.js', + 'adminhtml.permissions.user.edit.tab.roles', + 'adminhtml.permissions.user.edit.tab.roles.js', + ], + 'adminhtml_user_role_index' => [ + 'adminhtml.permission.role.index', + 'adminhtml.permissions.role.index', + 'adminhtml.permissions.role.grid', + ], + 'adminhtml_user_role_rolegrid' => ['adminhtml.permission.role.grid', 'adminhtml.permissions.role.grid'], + 'adminhtml_user_role_editrole' => [ + 'adminhtml.permissions.editroles', + 'adminhtml.permissions.tab.rolesedit', + 'adminhtml.permission.roles.users.grid.js', + 'adminhtml.permissions.roles.users.grid.js', + 'adminhtml.permission.role.buttons', + 'adminhtml.permissions.role.buttons', + 'adminhtml.permission.role.edit.gws', + ], + 'adminhtml_user_role_editrolegrid' => [ + 'adminhtml.permission.role.grid.user', + 'adminhtml.permissions.role.grid.user', + ], + 'adminhtml_user_index' => ['adminhtml.permission.user.index', 'adminhtml.permissions.user.index'], + 'adminhtml_user_rolegrid' => [ + 'adminhtml.permissions.user.rolegrid', + 'adminhtml.permission.user.rolegrid', + ], + 'adminhtml_user_rolesgrid' => [ + 'adminhtml.permissions.user.rolesgrid', + 'adminhtml.permission.user.rolesgrid', + ], + ]; + + private $allowedActionNodeMethods = [ + 'addBodyClass', + 'addButtons', + 'addColumnCountLayoutDepend', + 'addCrumb', + 'addDatabaseBlock', + 'addInputTypeTemplate', + 'addNotice', + 'addReportTypeOption', + 'addTab', + 'addTabAfter', + 'addText', + 'append', + 'removeTab', + 'setActive', + 'setAddressType', + 'setAfterCondition', + 'setAfterTotal', + 'setAtCall', + 'setAtCode', + 'setAtLabel', + 'setAuthenticationStartMode', + 'setBeforeCondition', + 'setBlockId', + 'setBugreportUrl', + 'setCanLoadExtJs', + 'setCanLoadRulesJs', + 'setCanLoadTinyMce', + 'setClassName', + 'setColClass', + 'setColumnCount', + 'setColumnsLimit', + 'setCssClass', + 'setDefaultFilter', + 'setDefaultStoreName', + 'setDestElementId', + 'setDisplayArea', + 'setDontDisplayContainer', + 'setEmptyGridMessage', + 'setEntityModelClass', + 'setFieldOption', + 'setFieldVisibility', + 'setFormCode', + 'setFormId', + 'setFormPrefix', + 'setGiftRegistryTemplate', + 'setGiftRegistryUrl', + 'setGridHtmlClass', + 'setGridHtmlCss', + 'setGridHtmlId', + 'setHeaderTitle', + 'setHideBalance', + 'setHideLink', + 'setHideRequiredNotice', + 'setHtmlClass', + 'setId', + 'setImageType', + 'setImgAlt', + 'setImgHeight', + 'setImgSrc', + 'setImgWidth', + 'setInList', + 'setInfoTemplate', + 'setIsCollapsed', + 'setIsDisabled', + 'setIsEnabled', + 'setIsGuestNote', + 'setIsHandle', + 'setIsLinkMode', + 'setIsPlaneMode', + 'setIsTitleHidden', + 'setIsViewCurrent', + 'setItemLimit', + 'setLabel', + 'setLabelProperties', + 'setLayoutCode', + 'setLinkUrl', + 'setListCollection', + 'setListModes', + 'setListOrders', + 'setMAPTemplate', + 'setMethodFormTemplate', + 'setMyClass', + 'setPageLayout', + 'setPageTitle', + 'setParentType', + 'setControllerPath', + 'setPosition', + 'setPositioned', + 'setRewardMessage', + 'setRewardQtyLimitationMessage', + 'setShouldPrepareInfoTabs', + 'setShowPart', + 'setSignupLabel', + 'setSourceField', + 'setStoreVarName', + 'setStrong', + 'setTemplate', + 'setText', + 'setThemeName', + 'setTierPriceTemplate', + 'setTitle', + 'setTitleClass', + 'setTitleId', + 'setToolbarBlockName', + 'setType', + 'setUseConfirm', + 'setValueProperties', + 'setViewAction', + 'setViewColumn', + 'setViewLabel', + 'setViewMode', + 'setWrapperClass', + 'unsetChild', + 'unsetChildren', + 'updateButton', + 'setIsProductListingContext', + ]; + + /** + * @inheritdoc + */ + public function register(): array + { + return [ + T_INLINE_HTML + ]; + } + + /** + * @inheritDoc + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($stackPtr > 0) { + return; + } + + $layout = simplexml_load_string($this->getFormattedXML($phpcsFile)); + + if ($layout === false) { + $phpcsFile->addError( + sprintf( + "Couldn't parse contents of '%s', check that they are in valid XML format", + $phpcsFile->getFilename(), + ), + $stackPtr, + self::ERROR_CODE_XML + ); + return; + } + + $this->testObsoleteReferences($layout, $phpcsFile); + $this->testObsoleteAttributes($layout, $phpcsFile); + $this->testHeadBlocks($layout, $phpcsFile); + $this->testOutputAttribute($layout, $phpcsFile); + $this->testHelperAttribute($layout, $phpcsFile); + $this->testListText($layout, $phpcsFile); + $this->testActionNodeMethods($layout, $phpcsFile); + //$this->testWithComponentRegistrar($layout, $phpcsFile); + } + + /** + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile) + { + foreach ($layout as $handle) { + if (!isset($this->_obsoleteReferences[$handle->getName()])) { + continue; + } + foreach ($handle->xpath('reference') as $reference) { + if (strpos((string)$reference['name'], $this->obsoleteReferences[$handle->getName()]) !== false) { + $phpcsFile->addError( + 'The block being referenced is removed.', + dom_import_simplexml($reference)->getLineNo(), + self::ERROR_CODE_OBSOLETE + ); + } + } + } + } + + /** + * Format the incoming XML to avoid tags split into several lines. + * + * @param File $phpcsFile + * @return false|string + */ + private function getFormattedXML(File $phpcsFile) + { + $doc = new DomDocument('1.0'); + $doc->formatOutput = true; + $doc->loadXML($phpcsFile->getTokensAsString(0, 999999)); + return $doc->saveXML(); + } + + /** + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testHeadBlocks(SimpleXMLElement $layout, File $phpcsFile) + { + $selectorHeadBlock = '(name()="block" or name()="referenceBlock") and ' . + '(@name="head" or @name="convert_root_head" or @name="vde_head")'; + $elements = $layout->xpath( + '//block[@class="Magento\Theme\Block\Html\Head\Css" ' . + 'or @class="Magento\Theme\Block\Html\Head\Link" ' . + 'or @class="Magento\Theme\Block\Html\Head\Script"]' . + '/parent::*[not(' . + $selectorHeadBlock . + ')]'); + if (!empty($elements)) { + $phpcsFile->addError( + 'Blocks \Magento\Theme\Block\Html\Head\{Css,Link,Script} ' . + 'are allowed within the "head" block only. ' . + 'Verify integrity of the nodes nesting.', + dom_import_simplexml($elements[0])->getLineNo(), + self::ERROR_CODE_NOT_ALLOWED + ); + }; + } + + /** + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testOutputAttribute(SimpleXMLElement $layout, File $phpcsFile): void + { + $elements = $layout->xpath('/layout//*[@output="toHtml"]'); + if (!empty($elements)) { + $phpcsFile->addError( + 'output="toHtml" is obsolete. Use output="1"', + dom_import_simplexml($elements[0])->getLineNo(), + self::ERROR_CODE_OBSOLETE + ); + }; + } + + /** + * Tests the attributes of the top-level Layout Node. + * Verifies there are no longer attributes of "parent" or "owner" + * + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testObsoleteAttributes(SimpleXMLElement $layout, File $phpcsFile) + { + $type = $layout['type']; + $parent = $layout['parent']; + $owner = $layout['owner']; + + if ((string)$type === 'page') { + if ($parent) { + $phpcsFile->addError( + 'Attribute "parent" is not valid', + dom_import_simplexml($parent)->getLineNo(), + self::ERROR_CODE_ATTRIBUTE_NOT_VALID + ); + } + } + if ((string)$type === 'fragment') { + if ($owner) { + $phpcsFile->addError( + 'Attribute "owner" is not valid', + dom_import_simplexml($owner)->getLineNo(), + self::ERROR_CODE_ATTRIBUTE_NOT_VALID + ); + } + } + } + + /** + * Returns attribute value by attribute name + * + * @param string $name + * @return string|null + */ + private function getAttribute(SimpleXMLElement $element, string $name): string + { + $attrs = $element->attributes(); + return isset($attrs[$name]) ? (string)$attrs[$name] : ''; + } + + /** + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testHelperAttribute(SimpleXMLElement $layout, File $phpcsFile): void + { + foreach ($layout->xpath('@helper') as $action) { + if (strpos($this->getAttribute($action, 'helper'), '/') !== false) { + $phpcsFile->addError( + "'helper' attribute contains '/'", + dom_import_simplexml($action)->getLineNo(), + self::ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_NOT_ALLOWED + ); + } + if (strpos($this->getAttribute($action, 'helper'), '::') === false) { + $phpcsFile->addError( + "'helper' attribute does not contain '::'", + dom_import_simplexml($action)->getLineNo(), + self::ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_EXPECTED + ); + } + } + } + + /** + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testListText(SimpleXMLElement $layout, File $phpcsFile): void + { + $elements = $layout->xpath('/layout//block[@class="Magento\Framework\View\Element\Text\ListText"]'); + if (!empty($elements)) { + $phpcsFile->addError( + 'The class \Magento\Framework\View\Element\Text\ListText' . + ' is not supposed to be used in layout anymore.', + dom_import_simplexml($elements[0])->getLineNo(), + self::ERROR_CODE_OBSOLETE_CLASS + ); + }; + } + + /** + * @param SimpleXMLElement $layout + * @param File $phpcsFile + */ + private function testActionNodeMethods(SimpleXMLElement $layout, File $phpcsFile) + { + $methodFilter = '@method!="' . implode('" and @method!="', $this->allowedActionNodeMethods) . '"'; + foreach ($layout->xpath('//action[' . $methodFilter . ']') as $node) { + $attributes = $node->attributes(); + $phpcsFile->addError( + sprintf( + 'Call of method "%s" via layout instruction is not allowed.', + $attributes['method'] + ), + dom_import_simplexml($node)->getLineNo(), + self::ERROR_CODE_METHOD_NOT_ALLOWED + ); + } + } + + private function testWithComponentRegistrar(SimpleXMLElement $layout, File $phpcsFile) + { + /* + * $componentRegistrar = new ComponentRegistrar(); + if (false !== strpos( + $layoutFile, + $componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Sales') + . '/view/adminhtml/layout/sales_order' + ) || false !== strpos( + $layoutFile, + $componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Shipping') + . '/view/adminhtml/layout/adminhtml_order' + ) + || false !== strpos( + $layoutFile, + $componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Catalog') + . '/view/adminhtml/layout/catalog_product_grid.xml' + ) + ) { + $this->markTestIncomplete( + "The file {$layoutFile} has to use \\Magento\\Core\\Block\\Text\\List, \n" . + 'there is no solution to get rid of it right now.' + ); + } + */ + } +} From cc12906668f01b00ddeaab8e22d42b98b919d0fe Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Thu, 30 Sep 2021 15:20:34 +0200 Subject: [PATCH 02/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 41 +----- Magento2/Tests/Legacy/LayoutUnitTest.1.xml | 157 +++++++++++++++++++++ Magento2/Tests/Legacy/LayoutUnitTest.2.xml | 29 ++++ Magento2/Tests/Legacy/LayoutUnitTest.3.xml | 27 ++++ Magento2/Tests/Legacy/LayoutUnitTest.php | 31 ++++ Magento2/ruleset.xml | 5 + 6 files changed, 256 insertions(+), 34 deletions(-) create mode 100644 Magento2/Tests/Legacy/LayoutUnitTest.1.xml create mode 100644 Magento2/Tests/Legacy/LayoutUnitTest.2.xml create mode 100644 Magento2/Tests/Legacy/LayoutUnitTest.3.xml create mode 100644 Magento2/Tests/Legacy/LayoutUnitTest.php diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index 7341e87c..716b8009 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -21,7 +21,7 @@ class LayoutSniff implements Sniff private const ERROR_CODE_OBSOLETE = 'Obsolete'; private const ERROR_CODE_OBSOLETE_CLASS = 'ObsoleteClass'; private const ERROR_CODE_ATTRIBUTE_NOT_VALID = 'AttributeNotValid'; - private const ERROR_CODE_METHOD_NOT_ALLOWED = 'MethodNot'; + private const ERROR_CODE_METHOD_NOT_ALLOWED = 'MethodNotAllowed'; private const ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_NOT_ALLOWED = 'CharacterNotAllowedInAttribute'; private const ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_EXPECTED = 'CharacterExpectedInAttribute'; @@ -230,14 +230,13 @@ public function process(File $phpcsFile, $stackPtr) $this->testHelperAttribute($layout, $phpcsFile); $this->testListText($layout, $phpcsFile); $this->testActionNodeMethods($layout, $phpcsFile); - //$this->testWithComponentRegistrar($layout, $phpcsFile); } /** * @param SimpleXMLElement $layout * @param File $phpcsFile */ - private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile) + private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile): void { foreach ($layout as $handle) { if (!isset($this->_obsoleteReferences[$handle->getName()])) { @@ -273,7 +272,7 @@ private function getFormattedXML(File $phpcsFile) * @param SimpleXMLElement $layout * @param File $phpcsFile */ - private function testHeadBlocks(SimpleXMLElement $layout, File $phpcsFile) + private function testHeadBlocks(SimpleXMLElement $layout, File $phpcsFile): void { $selectorHeadBlock = '(name()="block" or name()="referenceBlock") and ' . '(@name="head" or @name="convert_root_head" or @name="vde_head")'; @@ -315,10 +314,11 @@ private function testOutputAttribute(SimpleXMLElement $layout, File $phpcsFile): * Tests the attributes of the top-level Layout Node. * Verifies there are no longer attributes of "parent" or "owner" * + * @todo missing test * @param SimpleXMLElement $layout * @param File $phpcsFile */ - private function testObsoleteAttributes(SimpleXMLElement $layout, File $phpcsFile) + private function testObsoleteAttributes(SimpleXMLElement $layout, File $phpcsFile): void { $type = $layout['type']; $parent = $layout['parent']; @@ -362,7 +362,7 @@ private function getAttribute(SimpleXMLElement $element, string $name): string */ private function testHelperAttribute(SimpleXMLElement $layout, File $phpcsFile): void { - foreach ($layout->xpath('@helper') as $action) { + foreach ($layout->xpath('//*[@helper]') as $action) { if (strpos($this->getAttribute($action, 'helper'), '/') !== false) { $phpcsFile->addError( "'helper' attribute contains '/'", @@ -401,7 +401,7 @@ private function testListText(SimpleXMLElement $layout, File $phpcsFile): void * @param SimpleXMLElement $layout * @param File $phpcsFile */ - private function testActionNodeMethods(SimpleXMLElement $layout, File $phpcsFile) + private function testActionNodeMethods(SimpleXMLElement $layout, File $phpcsFile): void { $methodFilter = '@method!="' . implode('" and @method!="', $this->allowedActionNodeMethods) . '"'; foreach ($layout->xpath('//action[' . $methodFilter . ']') as $node) { @@ -416,31 +416,4 @@ private function testActionNodeMethods(SimpleXMLElement $layout, File $phpcsFile ); } } - - private function testWithComponentRegistrar(SimpleXMLElement $layout, File $phpcsFile) - { - /* - * $componentRegistrar = new ComponentRegistrar(); - if (false !== strpos( - $layoutFile, - $componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Sales') - . '/view/adminhtml/layout/sales_order' - ) || false !== strpos( - $layoutFile, - $componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Shipping') - . '/view/adminhtml/layout/adminhtml_order' - ) - || false !== strpos( - $layoutFile, - $componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_Catalog') - . '/view/adminhtml/layout/catalog_product_grid.xml' - ) - ) { - $this->markTestIncomplete( - "The file {$layoutFile} has to use \\Magento\\Core\\Block\\Text\\List, \n" . - 'there is no solution to get rid of it right now.' - ); - } - */ - } } diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.1.xml b/Magento2/Tests/Legacy/LayoutUnitTest.1.xml new file mode 100644 index 00000000..f051284a --- /dev/null +++ b/Magento2/Tests/Legacy/LayoutUnitTest.1.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + Magento\Theme\ViewModel\Block\SessionConfig + + + + + + + + + + welcome + + + + + + + contentarea + + + + + + + + + contentarea + Skip to Content + + + + + Magento\Store\ViewModel\SwitcherUrlProvider + + + + + header links + + + + + + + + + + + + navigation-sections + nav-sections + + + + Menu + + + + + + Account + true + ]]> + + + + + Settings + + + + nav + Magento\Store\ViewModel\SwitcherUrlProvider + + + + + nav + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + footer links + + + + + + + + + + + + + + + + backend_login + + + 226 + + + 50 + + + + + diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.2.xml b/Magento2/Tests/Legacy/LayoutUnitTest.2.xml new file mode 100644 index 00000000..04227a27 --- /dev/null +++ b/Magento2/Tests/Legacy/LayoutUnitTest.2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.3.xml b/Magento2/Tests/Legacy/LayoutUnitTest.3.xml new file mode 100644 index 00000000..bd34978b --- /dev/null +++ b/Magento2/Tests/Legacy/LayoutUnitTest.3.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + Magento_Paypal::hss/review/button.phtml + + + Magento_Paypal::hss/review/button.phtml + + + Magento_Paypal::hss/review/button.phtml + + + + + diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.php b/Magento2/Tests/Legacy/LayoutUnitTest.php new file mode 100644 index 00000000..bca0c7c5 --- /dev/null +++ b/Magento2/Tests/Legacy/LayoutUnitTest.php @@ -0,0 +1,31 @@ +error *\.xml$ + + 10 + error + */view/(adminhtml|frontend|base)/*\/.xml + 9 From 5d04411f841bcf0ecde52414f93aa239d2a6fa3a Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Thu, 30 Sep 2021 15:25:03 +0200 Subject: [PATCH 03/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Tests/Legacy/LayoutUnitTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.php b/Magento2/Tests/Legacy/LayoutUnitTest.php index bca0c7c5..c86ddee0 100644 --- a/Magento2/Tests/Legacy/LayoutUnitTest.php +++ b/Magento2/Tests/Legacy/LayoutUnitTest.php @@ -16,6 +16,21 @@ public function getErrorList($testFile = '') { if ($testFile === 'LayoutUnitTest.1.xml') { return [ + 23 => 1, + 146 => 1, + 149 => 1, + ]; + } + if ($testFile === 'LayoutUnitTest.2.xml') { + return [ + 12 => 1, + 29 => 1, + ]; + } + if ($testFile === 'LayoutUnitTest.3.xml') { + return [ + 16 => 1, + 19 => 1, ]; } return []; From f16142d83448a2af3286139f9fce9f8c45632b0d Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Thu, 30 Sep 2021 15:31:10 +0200 Subject: [PATCH 04/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Magento2/ruleset.xml b/Magento2/ruleset.xml index 4d0aa268..c130fa82 100644 --- a/Magento2/ruleset.xml +++ b/Magento2/ruleset.xml @@ -144,7 +144,7 @@ error *\.xml$ - + 10 error */view/(adminhtml|frontend|base)/*\/.xml From f7f1a0dbdd62083c0315ca123628d02357085813 Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Thu, 30 Sep 2021 15:42:22 +0200 Subject: [PATCH 05/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index 716b8009..1515cc38 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -71,6 +71,11 @@ class LayoutSniff implements Sniff ], ]; + /** + * List of allowed method names + * + * @var string[] + */ private $allowedActionNodeMethods = [ 'addBodyClass', 'addButtons', @@ -233,6 +238,9 @@ public function process(File $phpcsFile, $stackPtr) } /** + * Check for obsolete block references + * + * @todo missing test * @param SimpleXMLElement $layout * @param File $phpcsFile */ @@ -269,6 +277,8 @@ private function getFormattedXML(File $phpcsFile) } /** + * Check that CSS, Link and Script blocks are inside a head block + * * @param SimpleXMLElement $layout * @param File $phpcsFile */ @@ -295,6 +305,8 @@ private function testHeadBlocks(SimpleXMLElement $layout, File $phpcsFile): void } /** + * Check that the output attribute has the right value + * * @param SimpleXMLElement $layout * @param File $phpcsFile */ @@ -347,6 +359,7 @@ private function testObsoleteAttributes(SimpleXMLElement $layout, File $phpcsFil /** * Returns attribute value by attribute name * + * @param SimpleXMLElement $element * @param string $name * @return string|null */ @@ -357,6 +370,8 @@ private function getAttribute(SimpleXMLElement $element, string $name): string } /** + * Check values in helper attributes + * * @param SimpleXMLElement $layout * @param File $phpcsFile */ @@ -381,6 +396,8 @@ private function testHelperAttribute(SimpleXMLElement $layout, File $phpcsFile): } /** + * Check that ListText is not used + * * @param SimpleXMLElement $layout * @param File $phpcsFile */ @@ -398,6 +415,8 @@ private function testListText(SimpleXMLElement $layout, File $phpcsFile): void } /** + * Check that action is calling an allowed method + * * @param SimpleXMLElement $layout * @param File $phpcsFile */ From 98cf89383dfff968d8ed558eafcb8dc83db3f5ab Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Thu, 30 Sep 2021 15:44:56 +0200 Subject: [PATCH 06/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index 1515cc38..d4f3e16f 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -292,7 +292,8 @@ private function testHeadBlocks(SimpleXMLElement $layout, File $phpcsFile): void 'or @class="Magento\Theme\Block\Html\Head\Script"]' . '/parent::*[not(' . $selectorHeadBlock . - ')]'); + ')]' + ); if (!empty($elements)) { $phpcsFile->addError( 'Blocks \Magento\Theme\Block\Html\Head\{Css,Link,Script} ' . @@ -323,8 +324,7 @@ private function testOutputAttribute(SimpleXMLElement $layout, File $phpcsFile): } /** - * Tests the attributes of the top-level Layout Node. - * Verifies there are no longer attributes of "parent" or "owner" + * Tests the attributes of the top-level Layout Node. Verifies there are no longer attributes of "parent" or "owner" * * @todo missing test * @param SimpleXMLElement $layout From 4929b1aeab4885a99e9c894647a1298a6801db4f Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Thu, 30 Sep 2021 17:10:48 +0200 Subject: [PATCH 07/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index d4f3e16f..8731c03a 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -247,7 +247,7 @@ public function process(File $phpcsFile, $stackPtr) private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile): void { foreach ($layout as $handle) { - if (!isset($this->_obsoleteReferences[$handle->getName()])) { + if (!isset($this->obsoleteReferences[$handle->getName()])) { continue; } foreach ($handle->xpath('reference') as $reference) { From e59ca3ff35c0f35afe0ae2e37465f482f1bc454c Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 13 Oct 2021 12:05:43 +0200 Subject: [PATCH 08/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 56 +++++----------------- Magento2/Tests/Legacy/LayoutUnitTest.1.xml | 6 +-- Magento2/Tests/Legacy/LayoutUnitTest.php | 14 +++--- 3 files changed, 22 insertions(+), 54 deletions(-) diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index 8731c03a..2575e2b5 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types = 1); namespace Magento2\Sniffs\Legacy; @@ -20,7 +21,6 @@ class LayoutSniff implements Sniff private const ERROR_CODE_NOT_ALLOWED = 'NotAllowed'; private const ERROR_CODE_OBSOLETE = 'Obsolete'; private const ERROR_CODE_OBSOLETE_CLASS = 'ObsoleteClass'; - private const ERROR_CODE_ATTRIBUTE_NOT_VALID = 'AttributeNotValid'; private const ERROR_CODE_METHOD_NOT_ALLOWED = 'MethodNotAllowed'; private const ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_NOT_ALLOWED = 'CharacterNotAllowedInAttribute'; private const ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_EXPECTED = 'CharacterExpectedInAttribute'; @@ -229,7 +229,6 @@ public function process(File $phpcsFile, $stackPtr) } $this->testObsoleteReferences($layout, $phpcsFile); - $this->testObsoleteAttributes($layout, $phpcsFile); $this->testHeadBlocks($layout, $phpcsFile); $this->testOutputAttribute($layout, $phpcsFile); $this->testHelperAttribute($layout, $phpcsFile); @@ -240,21 +239,21 @@ public function process(File $phpcsFile, $stackPtr) /** * Check for obsolete block references * - * @todo missing test * @param SimpleXMLElement $layout * @param File $phpcsFile */ private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile): void { foreach ($layout as $handle) { - if (!isset($this->obsoleteReferences[$handle->getName()])) { + $attributes = $handle->attributes(); + if (!isset($this->obsoleteReferences[(string)$attributes->handle])) { continue; } - foreach ($handle->xpath('reference') as $reference) { - if (strpos((string)$reference['name'], $this->obsoleteReferences[$handle->getName()]) !== false) { + foreach ($handle->xpath('//reference | //referenceContainer | //referenceBlock') as $reference) { + if (in_array((string)$reference['name'], $this->obsoleteReferences[(string)$attributes->handle]) !== false) { $phpcsFile->addError( 'The block being referenced is removed.', - dom_import_simplexml($reference)->getLineNo(), + dom_import_simplexml($reference)->getLineNo()-1, self::ERROR_CODE_OBSOLETE ); } @@ -317,45 +316,12 @@ private function testOutputAttribute(SimpleXMLElement $layout, File $phpcsFile): if (!empty($elements)) { $phpcsFile->addError( 'output="toHtml" is obsolete. Use output="1"', - dom_import_simplexml($elements[0])->getLineNo(), + dom_import_simplexml($elements[0])->getLineNo()-1, self::ERROR_CODE_OBSOLETE ); }; } - /** - * Tests the attributes of the top-level Layout Node. Verifies there are no longer attributes of "parent" or "owner" - * - * @todo missing test - * @param SimpleXMLElement $layout - * @param File $phpcsFile - */ - private function testObsoleteAttributes(SimpleXMLElement $layout, File $phpcsFile): void - { - $type = $layout['type']; - $parent = $layout['parent']; - $owner = $layout['owner']; - - if ((string)$type === 'page') { - if ($parent) { - $phpcsFile->addError( - 'Attribute "parent" is not valid', - dom_import_simplexml($parent)->getLineNo(), - self::ERROR_CODE_ATTRIBUTE_NOT_VALID - ); - } - } - if ((string)$type === 'fragment') { - if ($owner) { - $phpcsFile->addError( - 'Attribute "owner" is not valid', - dom_import_simplexml($owner)->getLineNo(), - self::ERROR_CODE_ATTRIBUTE_NOT_VALID - ); - } - } - } - /** * Returns attribute value by attribute name * @@ -381,14 +347,14 @@ private function testHelperAttribute(SimpleXMLElement $layout, File $phpcsFile): if (strpos($this->getAttribute($action, 'helper'), '/') !== false) { $phpcsFile->addError( "'helper' attribute contains '/'", - dom_import_simplexml($action)->getLineNo(), + dom_import_simplexml($action)->getLineNo()-1, self::ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_NOT_ALLOWED ); } if (strpos($this->getAttribute($action, 'helper'), '::') === false) { $phpcsFile->addError( "'helper' attribute does not contain '::'", - dom_import_simplexml($action)->getLineNo(), + dom_import_simplexml($action)->getLineNo()-1, self::ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_EXPECTED ); } @@ -408,7 +374,7 @@ private function testListText(SimpleXMLElement $layout, File $phpcsFile): void $phpcsFile->addError( 'The class \Magento\Framework\View\Element\Text\ListText' . ' is not supposed to be used in layout anymore.', - dom_import_simplexml($elements[0])->getLineNo(), + dom_import_simplexml($elements[0])->getLineNo()-1, self::ERROR_CODE_OBSOLETE_CLASS ); }; @@ -430,7 +396,7 @@ private function testActionNodeMethods(SimpleXMLElement $layout, File $phpcsFile 'Call of method "%s" via layout instruction is not allowed.', $attributes['method'] ), - dom_import_simplexml($node)->getLineNo(), + dom_import_simplexml($node)->getLineNo()-1, self::ERROR_CODE_METHOD_NOT_ALLOWED ); } diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.1.xml b/Magento2/Tests/Legacy/LayoutUnitTest.1.xml index f051284a..591b51ae 100644 --- a/Magento2/Tests/Legacy/LayoutUnitTest.1.xml +++ b/Magento2/Tests/Legacy/LayoutUnitTest.1.xml @@ -6,11 +6,11 @@ */ --> - + - + @@ -19,7 +19,7 @@ - + diff --git a/Magento2/Tests/Legacy/LayoutUnitTest.php b/Magento2/Tests/Legacy/LayoutUnitTest.php index c86ddee0..8e7a6551 100644 --- a/Magento2/Tests/Legacy/LayoutUnitTest.php +++ b/Magento2/Tests/Legacy/LayoutUnitTest.php @@ -16,21 +16,23 @@ public function getErrorList($testFile = '') { if ($testFile === 'LayoutUnitTest.1.xml') { return [ + 13 => 1, + 22 => 1, 23 => 1, - 146 => 1, - 149 => 1, + 145 => 1, + 148 => 1, ]; } if ($testFile === 'LayoutUnitTest.2.xml') { return [ - 12 => 1, - 29 => 1, + 11 => 1, + 28 => 1, ]; } if ($testFile === 'LayoutUnitTest.3.xml') { return [ - 16 => 1, - 19 => 1, + 15 => 1, + 18 => 1, ]; } return []; From c30669f41d71e87f9c9d0c3f2b20f3ff84de8e3f Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 13 Oct 2021 12:14:55 +0200 Subject: [PATCH 09/10] AC-670: Create phpcs static check for LayoutTest --- Magento2/Sniffs/Legacy/LayoutSniff.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index 2575e2b5..72cc6345 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -245,12 +245,12 @@ public function process(File $phpcsFile, $stackPtr) private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile): void { foreach ($layout as $handle) { - $attributes = $handle->attributes(); - if (!isset($this->obsoleteReferences[(string)$attributes->handle])) { + $handleAttribute = (string)$handle->attributes()->handle; + if (!isset($this->obsoleteReferences[$handleAttribute])) { continue; } foreach ($handle->xpath('//reference | //referenceContainer | //referenceBlock') as $reference) { - if (in_array((string)$reference['name'], $this->obsoleteReferences[(string)$attributes->handle]) !== false) { + if (in_array((string)$reference['name'], $this->obsoleteReferences[$handleAttribute]) !== false) { $phpcsFile->addError( 'The block being referenced is removed.', dom_import_simplexml($reference)->getLineNo()-1, From a78b21dbdff8873078a44cb16859bc3cbaa16ab6 Mon Sep 17 00:00:00 2001 From: Sergio Vera Date: Wed, 13 Oct 2021 14:58:41 +0200 Subject: [PATCH 10/10] Update Magento2/Sniffs/Legacy/LayoutSniff.php Co-authored-by: Sergii Ivashchenko --- Magento2/Sniffs/Legacy/LayoutSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Magento2/Sniffs/Legacy/LayoutSniff.php b/Magento2/Sniffs/Legacy/LayoutSniff.php index 72cc6345..3a2c2044 100644 --- a/Magento2/Sniffs/Legacy/LayoutSniff.php +++ b/Magento2/Sniffs/Legacy/LayoutSniff.php @@ -271,7 +271,7 @@ private function getFormattedXML(File $phpcsFile) { $doc = new DomDocument('1.0'); $doc->formatOutput = true; - $doc->loadXML($phpcsFile->getTokensAsString(0, 999999)); + $doc->loadXML($phpcsFile->getTokensAsString(0, count($phpcsFile->getTokens()))); return $doc->saveXML(); }