/src/Utility/DrupalInspector.php

https://github.com/grasmash/composerize-drupal · PHP · 180 lines · 99 code · 20 blank · 61 comment · 15 complexity · 2803ac51b8c921e50ce3e1ec37ed4865 MD5 · raw file

  1. <?php
  2. namespace Grasmash\ComposerConverter\Utility;
  3. use Composer\Semver\Semver;
  4. use Symfony\Component\Finder\Finder;
  5. use Symfony\Component\Yaml\Yaml;
  6. class DrupalInspector
  7. {
  8. /**
  9. * @param $drupal_root
  10. * @param $subdir
  11. * @param $composer_json
  12. *
  13. * @return array
  14. */
  15. public static function findContribProjects($drupal_root, $subdir, $composer_json)
  16. {
  17. if (!file_exists($drupal_root . "/" . $subdir)) {
  18. return [];
  19. }
  20. $finder = new Finder();
  21. $finder->in([$drupal_root . "/" . $subdir])
  22. ->name('*.info.yml')
  23. ->depth('== 1')
  24. ->files();
  25. $projects = [];
  26. foreach ($finder as $fileInfo) {
  27. $path = $fileInfo->getPathname();
  28. $filename_parts = explode('.', $fileInfo->getFilename());
  29. $machine_name = $filename_parts[0];
  30. $module_info = Yaml::parseFile($path);
  31. $semantic_version = false;
  32. // Grab version from module yaml file.
  33. if (array_key_exists('version', $module_info)) {
  34. $semantic_version = self::getSemanticVersion($module_info['version']);
  35. } else {
  36. // Dev versions of modules do not include version info in yaml files.
  37. // Look in composer.json for a version constraint.
  38. if (array_key_exists('drupal/' . $machine_name, $composer_json->require)) {
  39. $version_constraint = $composer_json['require']['drupal/' . $machine_name];
  40. $semantic_version = self::getSemanticVersion($version_constraint);
  41. }
  42. }
  43. if ($semantic_version === false) {
  44. $semantic_version = null;
  45. }
  46. $projects[$machine_name]["version"] = $semantic_version;
  47. $projects[$machine_name]["dir"] = dirname($path);
  48. }
  49. return $projects;
  50. }
  51. /**
  52. * Finds all *.patch files contrib projects listed in $projects.
  53. *
  54. * @param array $projects
  55. * An array of contrib projects returned by self::findContribProjects().
  56. *
  57. * @return array
  58. */
  59. public static function findProjectPatches($projects)
  60. {
  61. foreach ($projects as $project_name => $project) {
  62. $finder = new Finder();
  63. $finder->in([$project['dir']])
  64. ->name('*.patch')
  65. ->files();
  66. foreach ($finder as $fileInfo) {
  67. $pathname = $fileInfo->getPathname();
  68. $projects[$project_name]['patches'][] = $pathname;
  69. }
  70. }
  71. return $projects;
  72. }
  73. /**
  74. * Generates a semantic version for a Drupal project.
  75. *
  76. * 3.0
  77. * 3.0-alpha1
  78. * 3.12-beta2
  79. * 4.0-rc12
  80. * 3.12
  81. * 1.0-unstable3
  82. * 0.1-rc2
  83. * 2.10-rc2
  84. *
  85. * {major}.{minor}.0-{stability}{#}
  86. *
  87. * @return string
  88. */
  89. public static function getSemanticVersion($drupal_version)
  90. {
  91. // Strip the 8.x prefix from the version.
  92. $version = preg_replace('/^8\.x-/', null, $drupal_version);
  93. if (preg_match('/-dev$/', $version)) {
  94. return preg_replace('/^(\d).+-dev$/', '$1.x-dev', $version);
  95. }
  96. $matches = [];
  97. preg_match('/^(\d{1,2})\.(\d{0,2})(\-(alpha|beta|rc|unstable)\d{1,2})?$/i', $version, $matches);
  98. $version = false;
  99. if (!empty($matches)) {
  100. $version = "{$matches[1]}.{$matches[2]}.0";
  101. if (array_key_exists(3, $matches)) {
  102. $version .= $matches[3];
  103. }
  104. }
  105. // Reject 'unstable'.
  106. return $version;
  107. }
  108. /**
  109. * @param $version
  110. *
  111. * @return string
  112. */
  113. public static function getVersionConstraint($version, $exact_versions)
  114. {
  115. if ($version == null) {
  116. return "*";
  117. } elseif (strstr($version, '-dev') !== false) {
  118. return $version;
  119. } elseif ($exact_versions) {
  120. return $version;
  121. } else {
  122. return "^" . $version;
  123. }
  124. }
  125. /**
  126. * Determines the version of Drupal core by looking at Drupal.php contents.
  127. *
  128. * @param string $file_contents
  129. * The contents of Drupal.php.
  130. *
  131. * @return mixed|string
  132. */
  133. public static function determineDrupalCoreVersionFromDrupalPhp($file_contents)
  134. {
  135. /**
  136. * Matches:
  137. * const VERSION = '8.0.0';
  138. * const VERSION = '8.0.0-beta1';
  139. * const VERSION = '8.0.0-rc2';
  140. * const VERSION = '8.5.11';
  141. * const VERSION = '8.5.x-dev';
  142. * const VERSION = '8.6.11-dev';
  143. */
  144. preg_match('#(const VERSION = \')(\d\.\d\.(\d{1,}|x)(-(beta|alpha|rc)[0-9])?(-dev)?)\';#', $file_contents, $matches);
  145. if (array_key_exists(2, $matches)) {
  146. $version = $matches[2];
  147. // Matches 8.6.11-dev. This is not actually a valid semantic
  148. // version. We fix it to become 8.6.x-dev before returning.
  149. if (strstr($version, '-dev') !== false
  150. && substr_count($version, '.') == 2) {
  151. // Matches (core) version 8.6.11-dev.
  152. $version = str_replace('-dev', '', $version);
  153. $pos1 = strpos($version, '.');
  154. $pos2 = strpos($version, '.', $pos1 + 1);
  155. $version = substr($version, 0, $pos1 + $pos2) . 'x-dev';
  156. }
  157. return $version;
  158. }
  159. }
  160. }