0x1949 Team - FAZEMRX - MANAGER
Edit File: Installer.php
<?php declare(strict_types=1); namespace PackageVersions; use Composer\Composer; use Composer\Config; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; use Composer\Package\Locker; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; use Composer\Plugin\PluginInterface; use Composer\Script\Event; use Composer\Script\ScriptEvents; use Generator; use RuntimeException; use function array_key_exists; use function array_merge; use function chmod; use function dirname; use function file_exists; use function file_put_contents; use function is_writable; use function iterator_to_array; use function rename; use function sprintf; use function uniqid; use function var_export; final class Installer implements PluginInterface, EventSubscriberInterface { private static $generatedClassTemplate = <<<'PHP' <?php declare(strict_types=1); namespace PackageVersions; use Composer\InstalledVersions; use OutOfBoundsException; class_exists(InstalledVersions::class); /** * This class is generated by composer/package-versions-deprecated, specifically by * @see \PackageVersions\Installer * * This file is overwritten at every run of `composer install` or `composer update`. * * @deprecated in favor of the Composer\InstalledVersions class provided by Composer 2. Require composer-runtime-api:^2 to ensure it is present. */ %s { /** * @deprecated please use {@see self::rootPackageName()} instead. * This constant will be removed in version 2.0.0. */ const ROOT_PACKAGE_NAME = '%s'; /** * Array of all available composer packages. * Dont read this array from your calling code, but use the \PackageVersions\Versions::getVersion() method instead. * * @var array<string, string> * @internal */ const VERSIONS = %s; private function __construct() { } /** * @psalm-pure * * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not * cause any side effects here. */ public static function rootPackageName() : string { if (!self::composer2ApiUsable()) { return self::ROOT_PACKAGE_NAME; } return InstalledVersions::getRootPackage()['name']; } /** * @throws OutOfBoundsException If a version cannot be located. * * @psalm-param key-of<self::VERSIONS> $packageName * @psalm-pure * * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not * cause any side effects here. */ public static function getVersion(string $packageName): string { if (self::composer2ApiUsable()) { return InstalledVersions::getPrettyVersion($packageName) . '@' . InstalledVersions::getReference($packageName); } if (isset(self::VERSIONS[$packageName])) { return self::VERSIONS[$packageName]; } throw new OutOfBoundsException( 'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files' ); } private static function composer2ApiUsable(): bool { if (!class_exists(InstalledVersions::class, false)) { return false; } if (method_exists(InstalledVersions::class, 'getAllRawData')) { $rawData = InstalledVersions::getAllRawData(); if (count($rawData) === 1 && count($rawData[0]) === 0) { return false; } } else { $rawData = InstalledVersions::getRawData(); if ($rawData === null || $rawData === []) { return false; } } return true; } } PHP; public function activate(Composer $composer, IOInterface $io) { // Nothing to do here, as all features are provided through event listeners } public function deactivate(Composer $composer, IOInterface $io) { // Nothing to do here, as all features are provided through event listeners } public function uninstall(Composer $composer, IOInterface $io) { // Nothing to do here, as all features are provided through event listeners } /** * {@inheritDoc} */ public static function getSubscribedEvents(): array { return [ScriptEvents::POST_AUTOLOAD_DUMP => 'dumpVersionsClass']; } /** * @throws RuntimeException */ public static function dumpVersionsClass(Event $composerEvent) { $composer = $composerEvent->getComposer(); $rootPackage = $composer->getPackage(); $versions = iterator_to_array(self::getVersions($composer->getLocker(), $rootPackage)); if (! array_key_exists('composer/package-versions-deprecated', $versions)) { //plugin must be globally installed - we only want to generate versions for projects which specifically //require composer/package-versions-deprecated return; } $versionClass = self::generateVersionsClass($rootPackage->getName(), $versions); self::writeVersionClassToFile($versionClass, $composer, $composerEvent->getIO()); } /** * @param string[] $versions */ private static function generateVersionsClass(string $rootPackageName, array $versions): string { return sprintf( self::$generatedClassTemplate, 'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-( $rootPackageName, var_export($versions, true) ); } /** * @throws RuntimeException */ private static function writeVersionClassToFile(string $versionClassSource, Composer $composer, IOInterface $io) { $installPath = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage()) . '/src/PackageVersions/Versions.php'; $installDir = dirname($installPath); if (! file_exists($installDir)) { $io->write('<info>composer/package-versions-deprecated:</info> Package not found (probably scheduled for removal); generation of version class skipped.'); return; } if (! is_writable($installDir)) { $io->write( sprintf( '<info>composer/package-versions-deprecated:</info> %s is not writable; generation of version class skipped.', $installDir ) ); return; } $io->write('<info>composer/package-versions-deprecated:</info> Generating version class...'); $installPathTmp = $installPath . '_' . uniqid('tmp', true); file_put_contents($installPathTmp, $versionClassSource); chmod($installPathTmp, 0664); rename($installPathTmp, $installPath); $io->write('<info>composer/package-versions-deprecated:</info> ...done generating version class'); } /** * @throws RuntimeException */ private static function locateRootPackageInstallPath( Config $composerConfig, RootPackageInterface $rootPackage ): string { if (self::getRootPackageAlias($rootPackage)->getName() === 'composer/package-versions-deprecated') { return dirname($composerConfig->get('vendor-dir')); } return $composerConfig->get('vendor-dir') . '/composer/package-versions-deprecated'; } private static function getRootPackageAlias(RootPackageInterface $rootPackage): PackageInterface { $package = $rootPackage; while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } return $package; } /** * @return Generator&string[] * * @psalm-return Generator<string, string> */ private static function getVersions(Locker $locker, RootPackageInterface $rootPackage): Generator { $lockData = $locker->getLockData(); $lockData['packages-dev'] = $lockData['packages-dev'] ?? []; $packages = $lockData['packages']; if (getenv('COMPOSER_DEV_MODE') !== '0') { $packages = array_merge($packages, $lockData['packages-dev']); } foreach ($packages as $package) { yield $package['name'] => $package['version'] . '@' . ( $package['source']['reference'] ?? $package['dist']['reference'] ?? '' ); } foreach ($rootPackage->getReplaces() as $replace) { $version = $replace->getPrettyConstraint(); if ($version === 'self.version') { $version = $rootPackage->getPrettyVersion(); } yield $replace->getTarget() => $version . '@' . $rootPackage->getSourceReference(); } yield $rootPackage->getName() => $rootPackage->getPrettyVersion() . '@' . $rootPackage->getSourceReference(); } }