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

/vendor/ocramius/package-versions/src/PackageVersions/Installer.php

https://codeberg.org/kampka/pixelfed-vendor
PHP | 209 lines | 129 code | 35 blank | 45 comment | 6 complexity | 735370ed23c95cdd85914122eeab9ec9 MD5 | raw file
Possible License(s): JSON, LGPL-2.1, BSD-3-Clause, BSD-2-Clause, MPL-2.0-no-copyleft-exception, MIT, Apache-2.0
  1. <?php
  2. declare(strict_types=1);
  3. namespace PackageVersions;
  4. use Composer\Composer;
  5. use Composer\Config;
  6. use Composer\EventDispatcher\EventSubscriberInterface;
  7. use Composer\IO\IOInterface;
  8. use Composer\Package\AliasPackage;
  9. use Composer\Package\Locker;
  10. use Composer\Package\PackageInterface;
  11. use Composer\Package\RootPackageInterface;
  12. use Composer\Plugin\PluginInterface;
  13. use Composer\Script\Event;
  14. use Composer\Script\ScriptEvents;
  15. use Generator;
  16. use RuntimeException;
  17. use function array_key_exists;
  18. use function array_merge;
  19. use function chmod;
  20. use function dirname;
  21. use function file_exists;
  22. use function file_put_contents;
  23. use function iterator_to_array;
  24. use function rename;
  25. use function sprintf;
  26. use function uniqid;
  27. use function var_export;
  28. final class Installer implements PluginInterface, EventSubscriberInterface
  29. {
  30. /** @var string */
  31. private static $generatedClassTemplate = <<<'PHP'
  32. <?php
  33. declare(strict_types=1);
  34. namespace PackageVersions;
  35. /**
  36. * This class is generated by ocramius/package-versions, specifically by
  37. * @see \PackageVersions\Installer
  38. *
  39. * This file is overwritten at every run of `composer install` or `composer update`.
  40. */
  41. %s
  42. {
  43. public const ROOT_PACKAGE_NAME = '%s';
  44. /**
  45. * Array of all available composer packages.
  46. * Dont read this array from your calling code, but use the \PackageVersions\Versions::getVersion() method instead.
  47. *
  48. * @var array<string, string>
  49. * @internal
  50. */
  51. public const VERSIONS = %s;
  52. private function __construct()
  53. {
  54. }
  55. /**
  56. * @throws \OutOfBoundsException If a version cannot be located.
  57. *
  58. * @psalm-param key-of<self::VERSIONS> $packageName
  59. */
  60. public static function getVersion(string $packageName) : string
  61. {
  62. if (isset(self::VERSIONS[$packageName])) {
  63. return self::VERSIONS[$packageName];
  64. }
  65. throw new \OutOfBoundsException(
  66. 'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'
  67. );
  68. }
  69. }
  70. PHP;
  71. /**
  72. * {@inheritDoc}
  73. */
  74. public function activate(Composer $composer, IOInterface $io) : void
  75. {
  76. // Nothing to do here, as all features are provided through event listeners
  77. }
  78. /**
  79. * {@inheritDoc}
  80. */
  81. public static function getSubscribedEvents() : array
  82. {
  83. return [ScriptEvents::POST_AUTOLOAD_DUMP => 'dumpVersionsClass'];
  84. }
  85. /**
  86. * @throws RuntimeException
  87. */
  88. public static function dumpVersionsClass(Event $composerEvent) : void
  89. {
  90. $composer = $composerEvent->getComposer();
  91. $rootPackage = $composer->getPackage();
  92. $versions = iterator_to_array(self::getVersions($composer->getLocker(), $rootPackage));
  93. if (! array_key_exists('ocramius/package-versions', $versions)) {
  94. //plugin must be globally installed - we only want to generate versions for projects which specifically
  95. //require ocramius/package-versions
  96. return;
  97. }
  98. $versionClass = self::generateVersionsClass($rootPackage->getName(), $versions);
  99. self::writeVersionClassToFile($versionClass, $composer, $composerEvent->getIO());
  100. }
  101. /**
  102. * @param string[] $versions
  103. */
  104. private static function generateVersionsClass(string $rootPackageName, array $versions) : string
  105. {
  106. return sprintf(
  107. self::$generatedClassTemplate,
  108. 'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-(
  109. $rootPackageName,
  110. var_export($versions, true)
  111. );
  112. }
  113. /**
  114. * @throws RuntimeException
  115. */
  116. private static function writeVersionClassToFile(string $versionClassSource, Composer $composer, IOInterface $io) : void
  117. {
  118. $installPath = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage())
  119. . '/src/PackageVersions/Versions.php';
  120. if (! file_exists(dirname($installPath))) {
  121. $io->write('<info>ocramius/package-versions:</info> Package not found (probably scheduled for removal); generation of version class skipped.');
  122. return;
  123. }
  124. $io->write('<info>ocramius/package-versions:</info> Generating version class...');
  125. $installPathTmp = $installPath . '_' . uniqid('tmp', true);
  126. file_put_contents($installPathTmp, $versionClassSource);
  127. chmod($installPathTmp, 0664);
  128. rename($installPathTmp, $installPath);
  129. $io->write('<info>ocramius/package-versions:</info> ...done generating version class');
  130. }
  131. /**
  132. * @throws RuntimeException
  133. */
  134. private static function locateRootPackageInstallPath(
  135. Config $composerConfig,
  136. RootPackageInterface $rootPackage
  137. ) : string {
  138. if (self::getRootPackageAlias($rootPackage)->getName() === 'ocramius/package-versions') {
  139. return dirname($composerConfig->get('vendor-dir'));
  140. }
  141. return $composerConfig->get('vendor-dir') . '/ocramius/package-versions';
  142. }
  143. private static function getRootPackageAlias(RootPackageInterface $rootPackage) : PackageInterface
  144. {
  145. $package = $rootPackage;
  146. while ($package instanceof AliasPackage) {
  147. $package = $package->getAliasOf();
  148. }
  149. return $package;
  150. }
  151. /**
  152. * @return Generator&string[]
  153. *
  154. * @psalm-return Generator<string, string>
  155. */
  156. private static function getVersions(Locker $locker, RootPackageInterface $rootPackage) : Generator
  157. {
  158. $lockData = $locker->getLockData();
  159. $lockData['packages-dev'] = $lockData['packages-dev'] ?? [];
  160. foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) {
  161. yield $package['name'] => $package['version'] . '@' . (
  162. $package['source']['reference']?? $package['dist']['reference'] ?? ''
  163. );
  164. }
  165. foreach ($rootPackage->getReplaces() as $replace) {
  166. $version = $replace->getPrettyConstraint();
  167. if ($version === 'self.version') {
  168. $version = $rootPackage->getPrettyVersion();
  169. }
  170. yield $replace->getTarget() => $version . '@' . $rootPackage->getSourceReference();
  171. }
  172. yield $rootPackage->getName() => $rootPackage->getPrettyVersion() . '@' . $rootPackage->getSourceReference();
  173. }
  174. }