NamespaceResolver.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Code\Reader;
  7. /**
  8. * Class resolve short namespaces to fully qualified namespaces.
  9. */
  10. class NamespaceResolver
  11. {
  12. /**
  13. * Namespace separator
  14. */
  15. const NS_SEPARATOR = '\\';
  16. /**
  17. * @var ScalarTypesProvider
  18. */
  19. private $scalarTypesProvider;
  20. /**
  21. * @var array
  22. */
  23. private $namespaces = [];
  24. /**
  25. * NamespaceResolver constructor.
  26. * @param ScalarTypesProvider $scalarTypesProvider
  27. */
  28. public function __construct(ScalarTypesProvider $scalarTypesProvider = null)
  29. {
  30. $this->scalarTypesProvider = $scalarTypesProvider ?: new ScalarTypesProvider();
  31. }
  32. /**
  33. * Perform namespace resolution if required and return fully qualified name.
  34. *
  35. * @param string $type
  36. * @param array $availableNamespaces
  37. * @return string
  38. */
  39. public function resolveNamespace($type, array $availableNamespaces)
  40. {
  41. if (substr($type, 0, 1) !== self::NS_SEPARATOR
  42. && !in_array($type, $this->scalarTypesProvider->getTypes())
  43. && !empty($type)
  44. ) {
  45. $name = explode(self::NS_SEPARATOR, $type);
  46. $unqualifiedName = $name[0];
  47. $isQualifiedName = count($name) > 1 ? true : false;
  48. if (isset($availableNamespaces[$unqualifiedName])) {
  49. $namespace = $availableNamespaces[$unqualifiedName];
  50. if ($isQualifiedName) {
  51. array_shift($name);
  52. return $namespace . self::NS_SEPARATOR . implode(self::NS_SEPARATOR, $name);
  53. }
  54. return $namespace;
  55. } else {
  56. return self::NS_SEPARATOR . $availableNamespaces[0] . self::NS_SEPARATOR . $type;
  57. }
  58. }
  59. return $type;
  60. }
  61. /**
  62. * Get all imported namespaces from provided class.
  63. *
  64. * @param array $fileContent
  65. * @return array
  66. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  67. */
  68. public function getImportedNamespaces(array $fileContent)
  69. {
  70. $fileContent = implode('', $fileContent);
  71. $cacheKey = sha1($fileContent);
  72. if (isset($this->namespaces[$cacheKey])) {
  73. return $this->namespaces[$cacheKey];
  74. }
  75. $fileContent = token_get_all($fileContent);
  76. $classStart = array_search('{', $fileContent);
  77. $fileContent = array_slice($fileContent, 0, $classStart);
  78. $output = [];
  79. foreach ($fileContent as $position => $token) {
  80. if (is_array($token) && $token[0] === T_USE) {
  81. $import = array_slice($fileContent, $position);
  82. $importEnd = array_search(';', $import);
  83. $import = array_slice($import, 0, $importEnd);
  84. $imports = [];
  85. $importsCount = 0;
  86. foreach ($import as $item) {
  87. if ($item === ',') {
  88. $importsCount++;
  89. continue;
  90. }
  91. $imports[$importsCount][] = $item;
  92. }
  93. foreach ($imports as $import) {
  94. $import = array_filter($import, function ($token) {
  95. $whitelist = [T_NS_SEPARATOR, T_STRING, T_AS];
  96. if (isset($token[0]) && in_array($token[0], $whitelist)) {
  97. return true;
  98. }
  99. return false;
  100. });
  101. $import = array_map(function ($element) {
  102. return $element[1];
  103. }, $import);
  104. $import = array_values($import);
  105. if ($import[0] === self::NS_SEPARATOR) {
  106. array_shift($import);
  107. }
  108. $importName = null;
  109. if (in_array('as', $import)) {
  110. $importName = array_splice($import, -1)[0];
  111. array_pop($import);
  112. }
  113. $useStatement = implode('', $import);
  114. if ($importName) {
  115. $output[$importName] = self::NS_SEPARATOR . $useStatement;
  116. } else {
  117. $key = explode(self::NS_SEPARATOR, $useStatement);
  118. $key = end($key);
  119. $output[$key] = self::NS_SEPARATOR . $useStatement;
  120. }
  121. }
  122. }
  123. }
  124. $this->namespaces[$cacheKey] = $output;
  125. return $this->namespaces[$cacheKey];
  126. }
  127. }