| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 | 
							- <?php
 
- /**
 
-  * Rule for searching dependencies in layout files
 
-  *
 
-  * Copyright © Magento, Inc. All rights reserved.
 
-  * See COPYING.txt for license details.
 
-  */
 
- namespace Magento\TestFramework\Dependency;
 
- class LayoutRule implements \Magento\TestFramework\Dependency\RuleInterface
 
- {
 
-     /**
 
-      * Default modules list.
 
-      *
 
-      * @var array
 
-      */
 
-     protected $_defaultModules = [
 
-         'frontend' => 'Magento\Theme',
 
-         'adminhtml' => 'Magento\Adminhtml',
 
-     ];
 
-     /**
 
-      * Namespaces to analyze
 
-      *
 
-      * Format: {Namespace}|{Namespace}|...
 
-      *
 
-      * @var string
 
-      */
 
-     protected $_namespaces;
 
-     /**
 
-      * List of routers
 
-      *
 
-      * Format: array(
 
-      *  '{Router}' => '{Module_Name}'
 
-      * )
 
-      *
 
-      * @var array
 
-      */
 
-     protected $_mapRouters = [];
 
-     /**
 
-      * List of layout blocks
 
-      *
 
-      * Format: array(
 
-      *  '{Area}' => array(
 
-      *   '{Block_Name}' => array('{Module_Name}' => '{Module_Name}')
 
-      * ))
 
-      *
 
-      * @var array
 
-      */
 
-     protected $_mapLayoutBlocks = [];
 
-     /**
 
-      * List of layout handles
 
-      *
 
-      * Format: array(
 
-      *  '{Area}' => array(
 
-      *   '{Handle_Name}' => array('{Module_Name}' => '{Module_Name}')
 
-      * ))
 
-      *
 
-      * @var array
 
-      */
 
-     protected $_mapLayoutHandles = [];
 
-     /**
 
-      * Unknown layout handle
 
-      */
 
-     const EXCEPTION_TYPE_UNKNOWN_HANDLE = 'UNKNOWN_HANDLE';
 
-     /**
 
-      * Unknown layout block
 
-      */
 
-     const EXCEPTION_TYPE_UNKNOWN_BLOCK = 'UNKNOWN_BLOCK';
 
-     /**
 
-      * Undefined dependency
 
-      */
 
-     const EXCEPTION_TYPE_UNDEFINED_DEPENDENCY = 'UNDEFINED_DEPENDENCY';
 
-     /**
 
-      * Constructor
 
-      *
 
-      * @param array $mapRouters
 
-      * @param array $mapLayoutBlocks
 
-      * @param array $mapLayoutHandles
 
-      */
 
-     public function __construct(array $mapRouters, array $mapLayoutBlocks, array $mapLayoutHandles)
 
-     {
 
-         $this->_mapRouters = $mapRouters;
 
-         $this->_mapLayoutBlocks = $mapLayoutBlocks;
 
-         $this->_mapLayoutHandles = $mapLayoutHandles;
 
-         $this->_namespaces = implode('|', \Magento\Framework\App\Utility\Files::init()->getNamespaces());
 
-     }
 
-     /**
 
-      * Retrieve dependencies information for current module
 
-      *
 
-      * @param string $currentModule
 
-      * @param string $fileType
 
-      * @param string $file
 
-      * @param string $contents
 
-      * @return array
 
-      */
 
-     public function getDependencyInfo($currentModule, $fileType, $file, &$contents)
 
-     {
 
-         if ('layout' != $fileType) {
 
-             return [];
 
-         }
 
-         $attributes = $this->_caseAttributeModule($currentModule, $contents);
 
-         $blocks = $this->_caseElementBlock($currentModule, $contents);
 
-         $actions = $this->_caseElementAction($currentModule, $contents);
 
-         $handle = $this->_caseLayoutHandle($currentModule, $file, $contents);
 
-         $handleParents = $this->_caseLayoutHandleParent($currentModule, $file, $contents);
 
-         $handleUpdates = $this->_caseLayoutHandleUpdate($currentModule, $file, $contents);
 
-         $references = $this->_caseLayoutReference($currentModule, $file, $contents);
 
-         $dependencies = array_merge(
 
-             $attributes,
 
-             $blocks,
 
-             $actions,
 
-             $handle,
 
-             $handleParents,
 
-             $handleUpdates,
 
-             $references
 
-         );
 
-         return $dependencies;
 
-     }
 
-     /**
 
-      * Check dependencies for 'module' attribute
 
-      *
 
-      * Ex.: <element module="{module}">
 
-      *
 
-      * @param $currentModule
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseAttributeModule($currentModule, &$contents)
 
-     {
 
-         $patterns = [
 
-             '/(?<source><.+module\s*=\s*[\'"](?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)[\'"].*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-         ];
 
-         return $this->_checkDependenciesByRegexp($currentModule, $contents, $patterns);
 
-     }
 
-     /**
 
-      * Check dependencies for <block> element
 
-      *
 
-      * Ex.: <block class="{name}">
 
-      *      <block template="{path}">
 
-      *
 
-      * @param $currentModule
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseElementBlock($currentModule, &$contents)
 
-     {
 
-         $patterns = [
 
-             '/(?<source><block.*class\s*=\s*[\'"](?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)[_\\\\]' .
 
-             '(?:[A-Z][a-zA-Z]+[_\\\\]?){1,}[\'"].*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_HARD,
 
-             '/(?<source><block.*template\s*=\s*[\'"](?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)::[\w\/\.]+[\'"].*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-         ];
 
-         return $this->_checkDependenciesByRegexp($currentModule, $contents, $patterns);
 
-     }
 
-     /**
 
-      * Check dependencies for <action> element
 
-      *
 
-      * Ex.: <block>{name}
 
-      *      <template>{path}
 
-      *      <file>{path}
 
-      *      <element helper="{name}">
 
-      *
 
-      * @param $currentModule
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseElementAction($currentModule, &$contents)
 
-     {
 
-         $patterns = [
 
-             '/(?<source><block\s*>(?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)[_\\\\]' .
 
-             '(?:[A-Z][a-zA-Z]+[_\\\\]?){1,}<\/block\s*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-             '/(?<source><template\s*>(?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)::[\w\/\.]+' .
 
-             '<\/template\s*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-             '/(?<source><file\s*>(?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)::[\w\/\.-]+' .
 
-             '<\/file\s*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-             '/(?<source><.*helper\s*=\s*[\'"](?<namespace>' .
 
-             $this->_namespaces .
 
-             ')[_\\\\]' .
 
-             '(?<module>[A-Z][a-zA-Z]+)[_\\\\](?:[A-Z][a-z]+[_\\\\]?){1,}::[\w]+' .
 
-             '[\'"].*>)/' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-         ];
 
-         return $this->_checkDependenciesByRegexp($currentModule, $contents, $patterns);
 
-     }
 
-     /**
 
-      * Check layout handles
 
-      *
 
-      * Ex.: <layout><{name}>...</layout>
 
-      *
 
-      * @param $currentModule
 
-      * @param $file
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseLayoutHandle($currentModule, $file, &$contents)
 
-     {
 
-         $xml = simplexml_load_string($contents);
 
-         if (!$xml) {
 
-             return [];
 
-         }
 
-         $area = $this->_getAreaByFile($file);
 
-         $result = [];
 
-         foreach ((array)$xml->xpath('/layout/child::*') as $element) {
 
-             $check = $this->_checkDependencyLayoutHandle($currentModule, $area, $element->getName());
 
-             $modules = isset($check['module']) ? $check['module'] : null;
 
-             if ($modules) {
 
-                 if (!is_array($modules)) {
 
-                     $modules = [$modules];
 
-                 }
 
-                 foreach ($modules as $module) {
 
-                     $result[$module] = [
 
-                         'type' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-                         'source' => $element->getName(),
 
-                     ];
 
-                 }
 
-             }
 
-         }
 
-         return $this->_getUniqueDependencies($result);
 
-     }
 
-     /**
 
-      * Check layout handles parents
 
-      *
 
-      * Ex.: <layout_name  parent="{name}">
 
-      *
 
-      * @param $currentModule
 
-      * @param $file
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseLayoutHandleParent($currentModule, $file, &$contents)
 
-     {
 
-         $xml = simplexml_load_string($contents);
 
-         if (!$xml) {
 
-             return [];
 
-         }
 
-         $area = $this->_getAreaByFile($file);
 
-         $result = [];
 
-         foreach ((array)$xml->xpath('/layout/child::*/@parent') as $element) {
 
-             $check = $this->_checkDependencyLayoutHandle($currentModule, $area, (string)$element);
 
-             $modules = isset($check['module']) ? $check['module'] : null;
 
-             if ($modules) {
 
-                 if (!is_array($modules)) {
 
-                     $modules = [$modules];
 
-                 }
 
-                 foreach ($modules as $module) {
 
-                     $result[$module] = [
 
-                         'type' => \Magento\Test\Integrity\DependencyTest::TYPE_HARD,
 
-                         'source' => (string)$element,
 
-                     ];
 
-                 }
 
-             }
 
-         }
 
-         return $this->_getUniqueDependencies($result);
 
-     }
 
-     /**
 
-      * Check layout handles updates
 
-      *
 
-      * Ex.: <update handle="{name}" />
 
-      *
 
-      * @param $currentModule
 
-      * @param $file
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseLayoutHandleUpdate($currentModule, $file, &$contents)
 
-     {
 
-         $xml = simplexml_load_string($contents);
 
-         if (!$xml) {
 
-             return [];
 
-         }
 
-         $area = $this->_getAreaByFile($file);
 
-         $result = [];
 
-         foreach ((array)$xml->xpath('//update/@handle') as $element) {
 
-             $check = $this->_checkDependencyLayoutHandle($currentModule, $area, (string)$element);
 
-             $modules = isset($check['module']) ? $check['module'] : null;
 
-             if ($modules) {
 
-                 if (!is_array($modules)) {
 
-                     $modules = [$modules];
 
-                 }
 
-                 foreach ($modules as $module) {
 
-                     $result[$module] = [
 
-                         'type' => \Magento\Test\Integrity\DependencyTest::TYPE_SOFT,
 
-                         'source' => (string)$element,
 
-                     ];
 
-                 }
 
-             }
 
-         }
 
-         return $this->_getUniqueDependencies($result);
 
-     }
 
-     /**
 
-      * Check layout references
 
-      *
 
-      * Ex.: <reference name="{name}">
 
-      *
 
-      * @param $currentModule
 
-      * @param $file
 
-      * @param $contents
 
-      * @return array
 
-      */
 
-     protected function _caseLayoutReference($currentModule, $file, &$contents)
 
-     {
 
-         $xml = simplexml_load_string($contents);
 
-         if (!$xml) {
 
-             return [];
 
-         }
 
-         $area = $this->_getAreaByFile($file);
 
-         $result = [];
 
-         foreach ((array)$xml->xpath('//reference/@name') as $element) {
 
-             $check = $this->_checkDependencyLayoutBlock($currentModule, $area, (string)$element);
 
-             $module = isset($check['module']) ? $check['module'] : null;
 
-             if ($module) {
 
-                 $result[$module] = [
 
-                     'type' => \Magento\TestFramework\Dependency\RuleInterface::TYPE_SOFT,
 
-                     'source' => (string)$element,
 
-                 ];
 
-             }
 
-         }
 
-         return $this->_getUniqueDependencies($result);
 
-     }
 
-     /**
 
-      * Search dependencies by defined regexp patterns
 
-      *
 
-      * @param $currentModule
 
-      * @param $contents
 
-      * @param array $patterns
 
-      * @return array
 
-      */
 
-     protected function _checkDependenciesByRegexp($currentModule, &$contents, $patterns = [])
 
-     {
 
-         $result = [];
 
-         foreach ($patterns as $pattern => $type) {
 
-             if (preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER)) {
 
-                 foreach ($matches as $match) {
 
-                     $module = $match['namespace'] . '\\' . $match['module'];
 
-                     if ($currentModule != $module) {
 
-                         $result[$module] = ['type' => $type, 'source' => $match['source']];
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         return $this->_getUniqueDependencies($result);
 
-     }
 
-     /**
 
-      * Check layout handle dependency
 
-      *
 
-      * Return: array(
 
-      *  'module'  // dependent module
 
-      *  'source'  // source text
 
-      * )
 
-      *
 
-      * @param $currentModule
 
-      * @param $area
 
-      * @param $handle
 
-      * @return array
 
-      */
 
-     protected function _checkDependencyLayoutHandle($currentModule, $area, $handle)
 
-     {
 
-         $chunks = explode('_', $handle);
 
-         if (count($chunks) > 1) {
 
-             // Remove 'action' part from handle name
 
-             array_pop($chunks);
 
-         }
 
-         $router = implode('_', $chunks);
 
-         if (isset($this->_mapRouters[$router])) {
 
-             // CASE 1: Single dependency
 
-             $modules = $this->_mapRouters[$router];
 
-             if (!in_array($currentModule, $modules)) {
 
-                 return ['module' => $modules];
 
-             }
 
-         }
 
-         if (isset($this->_mapLayoutHandles[$area][$handle])) {
 
-             // CASE 2: No dependencies
 
-             $modules = $this->_mapLayoutHandles[$area][$handle];
 
-             if (isset($modules[$currentModule])) {
 
-                 return ['module' => null];
 
-             }
 
-             // CASE 3: Single dependency
 
-             if (1 == count($modules)) {
 
-                 return ['module' => current($modules)];
 
-             }
 
-             // CASE 4: Default module dependency
 
-             $defaultModule = $this->_getDefaultModuleName($area);
 
-             if (isset($modules[$defaultModule])) {
 
-                 return ['module' => $defaultModule];
 
-             }
 
-         }
 
-         return [];
 
-     }
 
-     /**
 
-      * Check layout block dependency
 
-      *
 
-      * Return: array(
 
-      *  'module'  // dependent module
 
-      *  'source'  // source text
 
-      * )
 
-      *
 
-      * @param $currentModule
 
-      * @param $area
 
-      * @param $block
 
-      * @return array
 
-      */
 
-     protected function _checkDependencyLayoutBlock($currentModule, $area, $block)
 
-     {
 
-         if (isset($this->_mapLayoutBlocks[$area][$block])) {
 
-             // CASE 1: No dependencies
 
-             $modules = $this->_mapLayoutBlocks[$area][$block];
 
-             if (isset($modules[$currentModule])) {
 
-                 return ['module' => null];
 
-             }
 
-             // CASE 2: Single dependency
 
-             if (1 == count($modules)) {
 
-                 return ['module' => current($modules)];
 
-             }
 
-             // CASE 3: Default module dependency
 
-             $defaultModule = $this->_getDefaultModuleName($area);
 
-             if (isset($modules[$defaultModule])) {
 
-                 return ['module' => $defaultModule];
 
-             }
 
-         }
 
-         return [];
 
-     }
 
-     /**
 
-      * Get area from file path
 
-      *
 
-      * @param $file
 
-      * @return string
 
-      */
 
-     protected function _getAreaByFile($file)
 
-     {
 
-         $area = 'default';
 
-         if (preg_match('/\/(?<area>adminhtml|frontend)\//', $file, $matches)) {
 
-             $area = $matches['area'];
 
-         }
 
-         return $area;
 
-     }
 
-     /**
 
-      * Retrieve unique dependencies
 
-      *
 
-      * @param array $dependencies
 
-      * @return array
 
-      */
 
-     protected function _getUniqueDependencies($dependencies = [])
 
-     {
 
-         $result = [];
 
-         foreach ($dependencies as $module => $value) {
 
-             $result[] = ['module' => $module, 'type' => $value['type'], 'source' => $value['source']];
 
-         }
 
-         return $result;
 
-     }
 
-     /**
 
-      * Retrieve default module name (by area)
 
-      *
 
-      * @param string $area
 
-      * @return null
 
-      */
 
-     protected function _getDefaultModuleName($area = 'default')
 
-     {
 
-         if (isset($this->_defaultModules[$area])) {
 
-             return $this->_defaultModules[$area];
 
-         }
 
-         return null;
 
-     }
 
- }
 
 
  |