PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/internal/Magento/Framework/Composer/ComposerInformation.php

https://gitlab.com/crazybutterfly815/magento2
PHP | 379 lines | 191 code | 38 blank | 150 comment | 18 complexity | a45deaa1ac6b0ceb5f3701a30bae20c6 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright © 2016 Magento. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Composer;
  7. use Composer\Package\Link;
  8. use Composer\Package\CompletePackageInterface;
  9. use Magento\Framework\App\ObjectManager;
  10. /**
  11. * Class ComposerInformation uses Composer to determine dependency information.
  12. */
  13. class ComposerInformation
  14. {
  15. /**
  16. * Magento2 theme type
  17. */
  18. const THEME_PACKAGE_TYPE = 'magento2-theme';
  19. /**
  20. * Magento2 module type
  21. */
  22. const MODULE_PACKAGE_TYPE = 'magento2-module';
  23. /**
  24. * Magento2 language type
  25. */
  26. const LANGUAGE_PACKAGE_TYPE = 'magento2-language';
  27. /**
  28. * Magento2 metapackage type
  29. */
  30. const METAPACKAGE_PACKAGE_TYPE = 'metapackage';
  31. /**
  32. * Magento2 library type
  33. */
  34. const LIBRARY_PACKAGE_TYPE = 'magento2-library';
  35. /**
  36. * Magento2 component type
  37. */
  38. const COMPONENT_PACKAGE_TYPE = 'magento2-component';
  39. /**
  40. * Default composer repository key
  41. */
  42. const COMPOSER_DEFAULT_REPO_KEY = 'packagist';
  43. /**#@+
  44. * Composer command
  45. */
  46. const COMPOSER_SHOW = 'show';
  47. /**#@-*/
  48. /**#@+
  49. * Composer command params and options
  50. */
  51. const PARAM_COMMAND = 'command';
  52. const PARAM_PACKAGE = 'package';
  53. const PARAM_AVAILABLE = '--available';
  54. /**#@-*/
  55. /**
  56. * @var \Composer\Composer
  57. */
  58. private $composer;
  59. /**
  60. * @var \Composer\Package\Locker
  61. */
  62. private $locker;
  63. /** @var array */
  64. private static $packageTypes = [
  65. self::THEME_PACKAGE_TYPE,
  66. self::LANGUAGE_PACKAGE_TYPE,
  67. self::MODULE_PACKAGE_TYPE,
  68. self::LIBRARY_PACKAGE_TYPE,
  69. self::COMPONENT_PACKAGE_TYPE,
  70. self::METAPACKAGE_PACKAGE_TYPE
  71. ];
  72. /**
  73. * @var ComposerFactory
  74. */
  75. private $composerFactory;
  76. /**
  77. * @param ComposerFactory $composerFactory
  78. *
  79. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  80. */
  81. public function __construct(ComposerFactory $composerFactory)
  82. {
  83. $this->composerFactory = $composerFactory;
  84. }
  85. /**
  86. * Retrieves required php version
  87. *
  88. * @return string
  89. * @throws \Exception If attributes are missing in composer.lock file.
  90. */
  91. public function getRequiredPhpVersion()
  92. {
  93. if ($this->isMagentoRoot()) {
  94. $allPlatformReqs = $this->getLocker()->getPlatformRequirements(true);
  95. $requiredPhpVersion = $allPlatformReqs['php']->getPrettyConstraint();
  96. } else {
  97. $packages = $this->getLocker()->getLockedRepository()->getPackages();
  98. /** @var CompletePackageInterface $package */
  99. foreach ($packages as $package) {
  100. if ($package instanceof CompletePackageInterface) {
  101. $packageName = $package->getPrettyName();
  102. if ($packageName === 'magento/product-community-edition') {
  103. $phpRequirementLink = $package->getRequires()['php'];
  104. if ($phpRequirementLink instanceof Link) {
  105. $requiredPhpVersion = $phpRequirementLink->getPrettyConstraint();
  106. }
  107. }
  108. }
  109. }
  110. }
  111. if (!isset($requiredPhpVersion)) {
  112. throw new \Exception('Cannot find php version requirement in \'composer.lock\' file');
  113. }
  114. return $requiredPhpVersion;
  115. }
  116. /**
  117. * Retrieve list of required extensions
  118. *
  119. * Collect required extensions from composer.lock file
  120. *
  121. * @return array
  122. * @throws \Exception If attributes are missing in composer.lock file.
  123. */
  124. public function getRequiredExtensions()
  125. {
  126. $requiredExtensions = [];
  127. $allPlatformReqs = array_keys($this->getLocker()->getPlatformRequirements(true));
  128. if (!$this->isMagentoRoot()) {
  129. /** @var CompletePackageInterface $package */
  130. foreach ($this->getLocker()->getLockedRepository()->getPackages() as $package) {
  131. $requires = array_keys($package->getRequires());
  132. $requires = array_merge($requires, array_keys($package->getDevRequires()));
  133. $allPlatformReqs = array_merge($allPlatformReqs, $requires);
  134. }
  135. }
  136. foreach ($allPlatformReqs as $reqIndex) {
  137. if (substr($reqIndex, 0, 4) === 'ext-') {
  138. $requiredExtensions[] = substr($reqIndex, 4);
  139. }
  140. }
  141. return array_unique($requiredExtensions);
  142. }
  143. /**
  144. * Retrieve list of suggested extensions
  145. *
  146. * Collect suggests from composer.lock file and modules composer.json files
  147. *
  148. * @return array
  149. */
  150. public function getSuggestedPackages()
  151. {
  152. $suggests = [];
  153. /** @var \Composer\Package\CompletePackage $package */
  154. foreach ($this->getLocker()->getLockedRepository()->getPackages() as $package) {
  155. $suggests += $package->getSuggests();
  156. }
  157. return array_unique($suggests);
  158. }
  159. /**
  160. * Collect required packages from root composer.lock file
  161. *
  162. * @return array
  163. */
  164. public function getRootRequiredPackages()
  165. {
  166. $packages = [];
  167. /** @var CompletePackageInterface $package */
  168. foreach ($this->getLocker()->getLockedRepository()->getPackages() as $package) {
  169. $packages[] = $package->getName();
  170. }
  171. return $packages;
  172. }
  173. /**
  174. * Collect required packages and types from root composer.lock file
  175. *
  176. * @return array
  177. */
  178. public function getRootRequiredPackageTypesByName()
  179. {
  180. $packages = [];
  181. /** @var CompletePackageInterface $package */
  182. foreach ($this->getLocker()->getLockedRepository()->getPackages() as $package) {
  183. $packages[$package->getName()] = $package->getType();
  184. }
  185. return $packages;
  186. }
  187. /**
  188. * Collect all installed Magento packages from composer.lock
  189. *
  190. * @return array
  191. */
  192. public function getInstalledMagentoPackages()
  193. {
  194. $packages = [];
  195. /** @var CompletePackageInterface $package */
  196. foreach ($this->getLocker()->getLockedRepository()->getPackages() as $package) {
  197. if ((in_array($package->getType(), self::$packageTypes))
  198. && (!$this->isSystemPackage($package->getPrettyName()))) {
  199. $packages[$package->getName()] = [
  200. 'name' => $package->getName(),
  201. 'type' => $package->getType(),
  202. 'version' => $package->getPrettyVersion()
  203. ];
  204. }
  205. }
  206. return $packages;
  207. }
  208. /**
  209. * Collect all system packages from composer.lock
  210. *
  211. * @return array
  212. */
  213. public function getSystemPackages()
  214. {
  215. $packages = [];
  216. /** @var CompletePackageInterface $package */
  217. foreach ($this->getLocker()->getLockedRepository()->getPackages() as $package) {
  218. if ($this->isSystemPackage($package->getName())) {
  219. $packages[$package->getName()] = [
  220. 'name' => $package->getName(),
  221. 'type' => $package->getType(),
  222. 'version' => $package->getPrettyVersion()
  223. ];
  224. }
  225. }
  226. return $packages;
  227. }
  228. /**
  229. * Checks if the passed packaged is system package
  230. *
  231. * @param string $packageName
  232. * @return bool
  233. */
  234. public function isSystemPackage($packageName = '')
  235. {
  236. if (preg_match('/magento\/product-*/', $packageName) == 1) {
  237. return true;
  238. }
  239. return false;
  240. }
  241. /**
  242. * Determines if Magento is the root package or it is included as a requirement.
  243. *
  244. * @return boolean
  245. */
  246. public function isMagentoRoot()
  247. {
  248. $rootPackage = $this->getComposer()->getPackage();
  249. return (boolean)preg_match('/magento\/magento2...?/', $rootPackage->getName());
  250. }
  251. /**
  252. * Get root package
  253. *
  254. * @return \Composer\Package\RootPackageInterface
  255. */
  256. public function getRootPackage()
  257. {
  258. return $this->getComposer()->getPackage();
  259. }
  260. /**
  261. * Check if a package is inside the root composer or not
  262. *
  263. * @param string $packageName
  264. * @return bool
  265. */
  266. public function isPackageInComposerJson($packageName)
  267. {
  268. return (in_array($packageName, array_keys($this->getComposer()->getPackage()->getRequires()))
  269. || in_array($packageName, array_keys($this->getComposer()->getPackage()->getDevRequires()))
  270. );
  271. }
  272. /**
  273. * @return array
  274. */
  275. public function getPackagesTypes()
  276. {
  277. return self::$packageTypes;
  278. }
  279. /**
  280. * @param string $name
  281. * @param string $version
  282. * @return array
  283. */
  284. public function getPackageRequirements($name, $version)
  285. {
  286. $package = $this->getComposer()->getRepositoryManager()->findPackage($name, $version);
  287. return $package->getRequires();
  288. }
  289. /**
  290. * Returns all repository URLs, except local and packagists.
  291. *
  292. * @return string[]
  293. */
  294. public function getRootRepositories()
  295. {
  296. $repositoryUrls = [];
  297. foreach ($this->getComposer()->getConfig()->getRepositories() as $key => $repository) {
  298. if ($key !== self::COMPOSER_DEFAULT_REPO_KEY) {
  299. $repositoryUrls[] = $repository['url'];
  300. }
  301. }
  302. return $repositoryUrls;
  303. }
  304. /**
  305. * Load composerFactory
  306. *
  307. * @return ComposerFactory
  308. * @deprecated
  309. */
  310. private function getComposerFactory()
  311. {
  312. if (!$this->composerFactory) {
  313. $this->composerFactory = ObjectManager::getInstance()->get(ComposerFactory::class);
  314. }
  315. return $this->composerFactory;
  316. }
  317. /**
  318. * Load composer
  319. *
  320. * @return \Composer\Composer
  321. */
  322. private function getComposer()
  323. {
  324. if (!$this->composer) {
  325. $this->composer = $this->getComposerFactory()->create();
  326. }
  327. return $this->composer;
  328. }
  329. /**
  330. * Load locker
  331. *
  332. * @return \Composer\Package\Locker
  333. */
  334. private function getLocker()
  335. {
  336. if (!$this->locker) {
  337. $this->locker = $this->getComposer()->getLocker();
  338. }
  339. return $this->locker;
  340. }
  341. }