1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Test\Integrity\App\Language;
use Magento\Framework\App\Language\Config;
use Magento\Framework\Component\ComponentRegistrar;
class CircularDependencyTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Config[][]
*/
private $packs;
/**
* Test circular dependencies between languages
*/
public function testCircularDependencies()
{
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$componentRegistrar = new ComponentRegistrar();
$declaredLanguages = $componentRegistrar->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 : [];
}
}