![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/magento-coding-standard/Magento2/Sniffs/Legacy/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ declare(strict_types = 1); namespace Magento2\Sniffs\Legacy; use DOMDocument; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use SimpleXMLElement; /** * Test for obsolete nodes/attributes in layouts */ class LayoutSniff implements Sniff { private const ERROR_CODE_XML = 'WrongXML'; private const ERROR_CODE_OBSOLETE_BLOCK = 'ObsoleteBlock'; private const ERROR_CODE_OBSOLETE_CLASS = 'ObsoleteClass'; private const ERROR_CODE_OBSOLETE_TOHTML_ATTRIBUTE = 'ObsoleteToHtmlAttribute'; 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'; /** * List of obsolete references per handle * * @var array */ private $obsoleteReferences = [ 'adminhtml_user_edit' => [ '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', ], ]; /** * List of allowed method names * * @var string[] */ 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->testOutputAttribute($layout, $phpcsFile); $this->testHelperAttribute($layout, $phpcsFile); $this->testListText($layout, $phpcsFile); $this->testActionNodeMethods($layout, $phpcsFile); } /** * Check for obsolete block references * * @param SimpleXMLElement $layout * @param File $phpcsFile */ private function testObsoleteReferences(SimpleXMLElement $layout, File $phpcsFile): void { foreach ($layout as $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[$handleAttribute]) !== false) { $phpcsFile->addError( 'The block being referenced is removed.', dom_import_simplexml($reference)->getLineNo()-1, self::ERROR_CODE_OBSOLETE_BLOCK ); } } } } /** * 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, count($phpcsFile->getTokens()))); return $doc->saveXML(); } /** * Check that the output attribute has the right value * * @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()-1, self::ERROR_CODE_OBSOLETE_TOHTML_ATTRIBUTE ); }; } /** * Returns attribute value by attribute name * * @param SimpleXMLElement $element * @param string $name * @return string|null */ private function getAttribute(SimpleXMLElement $element, string $name): string { $attrs = $element->attributes(); return isset($attrs[$name]) ? (string)$attrs[$name] : ''; } /** * Check values in helper attributes * * @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()-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()-1, self::ERROR_CODE_HELPER_ATTRIBUTE_CHARACTER_EXPECTED ); } } } /** * Check that ListText is not used * * @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()-1, self::ERROR_CODE_OBSOLETE_CLASS ); } } /** * Check that action is calling an allowed method * * @param SimpleXMLElement $layout * @param File $phpcsFile */ private function testActionNodeMethods(SimpleXMLElement $layout, File $phpcsFile): void { $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 <action> is not allowed.', $attributes['method'] ), dom_import_simplexml($node)->getLineNo()-1, self::ERROR_CODE_METHOD_NOT_ALLOWED ); } } }