You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

270 lines
8.8KB

  1. <?php
  2. /*
  3. * This file is part of the Fxp Composer Asset Plugin package.
  4. *
  5. * (c) François Pluchino <francois.pluchino@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Fxp\Composer\AssetPlugin\Converter;
  11. use Composer\Config;
  12. use Composer\IO\NullIO;
  13. use Composer\Repository\Vcs\VcsDriverInterface;
  14. use Fxp\Composer\AssetPlugin\Assets;
  15. use Fxp\Composer\AssetPlugin\Type\AssetTypeInterface;
  16. use Fxp\Composer\AssetPlugin\Util\Validator;
  17. /**
  18. * Utils for package converter.
  19. *
  20. * @author François Pluchino <francois.pluchino@gmail.com>
  21. */
  22. abstract class PackageUtil
  23. {
  24. /**
  25. * Checks if the version is a URL version.
  26. *
  27. * @param AssetTypeInterface $assetType The asset type
  28. * @param string $dependency The dependency
  29. * @param string $version The version
  30. * @param array $vcsRepos The list of new vcs configs
  31. * @param array $composer The partial composer data
  32. *
  33. * @return string[] The new dependency and the new version
  34. */
  35. public static function checkUrlVersion(AssetTypeInterface $assetType, $dependency, $version, array &$vcsRepos = array(), array $composer)
  36. {
  37. if (preg_match('/(\:\/\/)|\@/', $version)) {
  38. list($url, $version) = static::splitUrlVersion($version);
  39. if (static::hasUrlDependencySupported($url)) {
  40. $vcsRepos[] = array(
  41. 'type' => sprintf('%s-vcs', $assetType->getName()),
  42. 'url' => $url,
  43. );
  44. } else {
  45. $dependency = static::getUrlFileDependencyName($assetType, $composer, $dependency);
  46. $vcsRepos[] = array(
  47. 'type' => 'package',
  48. 'package' => array(
  49. 'name' => $assetType->formatComposerName($dependency),
  50. 'type' => $assetType->getComposerType(),
  51. 'version' => static::getUrlFileDependencyVersion($assetType, $url, $version),
  52. 'dist' => array(
  53. 'url' => $url,
  54. 'type' => 'file',
  55. ),
  56. ),
  57. );
  58. }
  59. }
  60. return array($dependency, $version);
  61. }
  62. /**
  63. * Checks if the version is a alias version.
  64. *
  65. * @param AssetTypeInterface $assetType The asset type
  66. * @param string $dependency The dependency
  67. * @param string $version The version
  68. *
  69. * @return string[] The new dependency and the new version
  70. */
  71. public static function checkAliasVersion(AssetTypeInterface $assetType, $dependency, $version)
  72. {
  73. $pos = strpos($version, '#');
  74. if ($pos > 0 && !preg_match('{[0-9a-f]{40}$}', $version)) {
  75. $dependency = substr($version, 0, $pos);
  76. $version = substr($version, $pos);
  77. $searchVerion = substr($version, 1);
  78. if (false === strpos($version, '*') && Validator::validateTag($searchVerion, $assetType)) {
  79. $dependency .= '-'.str_replace('#', '', $version);
  80. }
  81. }
  82. return array($dependency, $version);
  83. }
  84. /**
  85. * Convert the dependency version.
  86. *
  87. * @param AssetTypeInterface $assetType The asset type
  88. * @param string $dependency The dependency
  89. * @param string $version The version
  90. *
  91. * @return string[] The new dependency and the new version
  92. */
  93. public static function convertDependencyVersion(AssetTypeInterface $assetType, $dependency, $version)
  94. {
  95. $version = str_replace('#', '', $version);
  96. $version = empty($version) ? '*' : $version;
  97. $version = trim($version);
  98. $searchVersion = str_replace(array(' ', '<', '>', '=', '^', '~'), '', $version);
  99. // sha version or branch verison
  100. if (preg_match('{^[0-9a-f]{40}$}', $version)) {
  101. $version = 'dev-default#'.$version;
  102. } elseif ('*' !== $version && !Validator::validateTag($searchVersion, $assetType) && !static::depIsRange($version)) {
  103. $oldVersion = $version;
  104. $version = 'dev-'.$assetType->getVersionConverter()->convertVersion($version);
  105. if (!Validator::validateBranch($oldVersion)) {
  106. $version .= ' || '.$oldVersion;
  107. }
  108. }
  109. return array($dependency, $version);
  110. }
  111. /**
  112. * Converts the simple key of package.
  113. *
  114. * @param array $asset The asset data
  115. * @param string $assetKey The asset key
  116. * @param array $composer The composer data
  117. * @param string $composerKey The composer key
  118. */
  119. public static function convertStringKey(array $asset, $assetKey, array &$composer, $composerKey)
  120. {
  121. if (isset($asset[$assetKey])) {
  122. $composer[$composerKey] = $asset[$assetKey];
  123. }
  124. }
  125. /**
  126. * Converts the simple key of package.
  127. *
  128. * @param array $asset The asset data
  129. * @param string $assetKey The asset key
  130. * @param array $composer The composer data
  131. * @param array $composerKey The array with composer key name and closure
  132. *
  133. * @throws \InvalidArgumentException When the 'composerKey' argument of asset packager converter is not an string or an array with the composer key and closure
  134. */
  135. public static function convertArrayKey(array $asset, $assetKey, array &$composer, $composerKey)
  136. {
  137. if (2 !== count($composerKey)
  138. || !is_string($composerKey[0]) || !$composerKey[1] instanceof \Closure) {
  139. throw new \InvalidArgumentException('The "composerKey" argument of asset packager converter must be an string or an array with the composer key and closure');
  140. }
  141. $closure = $composerKey[1];
  142. $composerKey = $composerKey[0];
  143. $data = isset($asset[$assetKey]) ? $asset[$assetKey] : null;
  144. $previousData = isset($composer[$composerKey]) ? $composer[$composerKey] : null;
  145. $data = $closure($data, $previousData);
  146. if (null !== $data) {
  147. $composer[$composerKey] = $data;
  148. }
  149. }
  150. /**
  151. * Split the URL and version.
  152. *
  153. * @param string $version The url and version (in the same string)
  154. *
  155. * @return string[] The url and version
  156. */
  157. protected static function splitUrlVersion($version)
  158. {
  159. $pos = strpos($version, '#');
  160. // number version or empty version
  161. if (false !== $pos) {
  162. $url = substr($version, 0, $pos);
  163. $version = substr($version, $pos);
  164. } else {
  165. $url = $version;
  166. $version = '#';
  167. }
  168. return array($url, $version);
  169. }
  170. /**
  171. * Get the name of url file dependency.
  172. *
  173. * @param AssetTypeInterface $assetType The asset type
  174. * @param array $composer The partial composer
  175. * @param string $dependency The dependency name
  176. *
  177. * @return string The dependency name
  178. */
  179. protected static function getUrlFileDependencyName(AssetTypeInterface $assetType, array $composer, $dependency)
  180. {
  181. $prefix = isset($composer['name'])
  182. ? substr($composer['name'], strlen($assetType->getComposerVendorName()) + 1).'-'
  183. : '';
  184. return $prefix.$dependency.'-file';
  185. }
  186. /**
  187. * Get the version of url file dependency.
  188. *
  189. * @param AssetTypeInterface $assetType The asset type
  190. * @param string $url The url
  191. * @param string $version The version
  192. *
  193. * @return string The version
  194. */
  195. protected static function getUrlFileDependencyVersion(AssetTypeInterface $assetType, $url, $version)
  196. {
  197. if ('#' !== $version) {
  198. return substr($version, 1);
  199. }
  200. if (preg_match('/(\d+)(\.\d+)(\.\d+)?(\.\d+)?/', $url, $match)) {
  201. return $assetType->getVersionConverter()->convertVersion($match[0]);
  202. }
  203. return '0.0.0.0';
  204. }
  205. /**
  206. * Check if url is supported by vcs drivers.
  207. *
  208. * @param string $url The url
  209. *
  210. * @return bool
  211. */
  212. protected static function hasUrlDependencySupported($url)
  213. {
  214. $io = new NullIO();
  215. $config = new Config();
  216. /* @var VcsDriverInterface $driver */
  217. foreach (Assets::getVcsDrivers() as $driver) {
  218. $supported = $driver::supports($io, $config, $url);
  219. if ($supported) {
  220. return true;
  221. }
  222. }
  223. return false;
  224. }
  225. /**
  226. * Check if the version of dependency is a range version.
  227. *
  228. * @param string $version
  229. *
  230. * @return bool
  231. */
  232. protected static function depIsRange($version)
  233. {
  234. $version = trim($version);
  235. return (bool) preg_match('/[\<\>\=\^\~\ ]/', $version);
  236. }
  237. }