CircularDependencyTest.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Test\Integrity\App\Language;
  7. use Magento\Framework\App\Language\Config;
  8. use Magento\Framework\Component\ComponentRegistrar;
  9. class CircularDependencyTest extends \PHPUnit\Framework\TestCase
  10. {
  11. /**
  12. * @var Config[][]
  13. */
  14. private $packs;
  15. /**
  16. * Test circular dependencies between languages
  17. */
  18. public function testCircularDependencies()
  19. {
  20. $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  21. $componentRegistrar = new ComponentRegistrar();
  22. $declaredLanguages = $componentRegistrar->getPaths(ComponentRegistrar::LANGUAGE);
  23. $validationStateMock = $this->createMock(\Magento\Framework\Config\ValidationStateInterface::class);
  24. $validationStateMock->method('isValidationRequired')
  25. ->willReturn(true);
  26. $domFactoryMock = $this->createMock(\Magento\Framework\Config\DomFactory::class);
  27. $domFactoryMock->expects($this->any())
  28. ->method('createDom')
  29. ->willReturnCallback(
  30. function ($arguments) use ($validationStateMock) {
  31. return new \Magento\Framework\Config\Dom(
  32. $arguments['xml'],
  33. $validationStateMock,
  34. [],
  35. null,
  36. $arguments['schemaFile']
  37. );
  38. }
  39. );
  40. $packs = [];
  41. foreach ($declaredLanguages as $language) {
  42. $languageConfig = $objectManager->getObject(
  43. \Magento\Framework\App\Language\Config::class,
  44. [
  45. 'source' => file_get_contents($language . '/language.xml'),
  46. 'domFactory' => $domFactoryMock
  47. ]
  48. );
  49. $this->packs[$languageConfig->getVendor()][$languageConfig->getPackage()] = $languageConfig;
  50. $packs[] = $languageConfig;
  51. }
  52. /** @var $languageConfig Config */
  53. foreach ($packs as $languageConfig) {
  54. $languages = [];
  55. /** @var $config Config */
  56. foreach ($this->collectCircularInheritance($languageConfig) as $config) {
  57. $languages[] = $config->getVendor() . '/' . $config->getPackage();
  58. }
  59. if (!empty($languages)) {
  60. $this->fail("Circular dependency detected:\n" . implode(' -> ', $languages));
  61. }
  62. }
  63. }
  64. /**
  65. * @param Config $languageConfig
  66. * @param array $languageList
  67. * @param bool $isCircular
  68. * @return array|null
  69. */
  70. private function collectCircularInheritance(Config $languageConfig, &$languageList = [], &$isCircular = false)
  71. {
  72. $packKey = implode('|', [$languageConfig->getVendor(), $languageConfig->getPackage()]);
  73. if (isset($languageList[$packKey])) {
  74. $isCircular = true;
  75. } else {
  76. $languageList[$packKey] = $languageConfig;
  77. foreach ($languageConfig->getUses() as $reuse) {
  78. if (isset($this->packs[$reuse['vendor']][$reuse['package']])) {
  79. $this->collectCircularInheritance(
  80. $this->packs[$reuse['vendor']][$reuse['package']],
  81. $languageList,
  82. $isCircular
  83. );
  84. }
  85. }
  86. }
  87. return $isCircular ? $languageList : [];
  88. }
  89. }