getPaths(ComponentRegistrar::LANGUAGE); $validationStateMock = $this->createMock(\Magento\Framework\Config\ValidationStateInterface::class); $validationStateMock->method('isValidationRequired') ->willReturn(true); $domFactoryMock = $this->createMock(\Magento\Framework\Config\DomFactory::class); $domFactoryMock->expects($this->any()) ->method('createDom') ->willReturnCallback( function ($arguments) use ($validationStateMock) { return new \Magento\Framework\Config\Dom( $arguments['xml'], $validationStateMock, [], null, $arguments['schemaFile'] ); } ); $packs = []; foreach ($declaredLanguages as $language) { $languageConfig = $objectManager->getObject( \Magento\Framework\App\Language\Config::class, [ 'source' => file_get_contents($language . '/language.xml'), 'domFactory' => $domFactoryMock ] ); $this->packs[$languageConfig->getVendor()][$languageConfig->getPackage()] = $languageConfig; $packs[] = $languageConfig; } /** @var $languageConfig Config */ foreach ($packs as $languageConfig) { $languages = []; /** @var $config Config */ foreach ($this->collectCircularInheritance($languageConfig) as $config) { $languages[] = $config->getVendor() . '/' . $config->getPackage(); } if (!empty($languages)) { $this->fail("Circular dependency detected:\n" . implode(' -> ', $languages)); } } } /** * @param Config $languageConfig * @param array $languageList * @param bool $isCircular * @return array|null */ private function collectCircularInheritance(Config $languageConfig, &$languageList = [], &$isCircular = false) { $packKey = implode('|', [$languageConfig->getVendor(), $languageConfig->getPackage()]); if (isset($languageList[$packKey])) { $isCircular = true; } else { $languageList[$packKey] = $languageConfig; foreach ($languageConfig->getUses() as $reuse) { if (isset($this->packs[$reuse['vendor']][$reuse['package']])) { $this->collectCircularInheritance( $this->packs[$reuse['vendor']][$reuse['package']], $languageList, $isCircular ); } } } return $isCircular ? $languageList : []; } }