Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Installer.php
001 <?php
002
003 declare(strict_types=1);
004
005 namespace PackageVersions;
006
007 use Composer\Composer;
008 use Composer\Config;
009 use Composer\EventDispatcher\EventSubscriberInterface;
010 use Composer\IO\IOInterface;
011 use Composer\Package\AliasPackage;
012 use Composer\Package\Locker;
013 use Composer\Package\PackageInterface;
014 use Composer\Package\RootPackageInterface;
015 use Composer\Plugin\PluginInterface;
016 use Composer\Script\Event;
017 use Composer\Script\ScriptEvents;
018 use Generator;
019 use RuntimeException;
020
021 use function array_key_exists;
022 use function array_merge;
023 use function chmod;
024 use function dirname;
025 use function file_exists;
026 use function file_put_contents;
027 use function is_writable;
028 use function iterator_to_array;
029 use function rename;
030 use function sprintf;
031 use function uniqid;
032 use function var_export;
033
034 final class Installer implements PluginInterface, EventSubscriberInterface
035 {
036 private static $generatedClassTemplate = <<<'PHP'
037 <?php
038
039 declare(strict_types=1);
040
041 namespace PackageVersions;
042
043 use Composer\InstalledVersions;
044 use OutOfBoundsException;
045
046 class_exists(InstalledVersions::class);
047
048 /**
049 * This class is generated by composer/package-versions-deprecated, specifically by
050 * @see \PackageVersions\Installer
051 *
052 * This file is overwritten at every run of `composer install` or `composer update`.
053 *
054 * @deprecated in favor of the Composer\InstalledVersions class provided by Composer 2. Require composer-runtime-api:^2 to ensure it is present.
055 */
056 %s
057 {
058 /**
059 * @deprecated please use {@see self::rootPackageName()} instead.
060 * This constant will be removed in version 2.0.0.
061 */
062 const ROOT_PACKAGE_NAME = '%s';
063
064 /**
065 * Array of all available composer packages.
066 * Dont read this array from your calling code, but use the \PackageVersions\Versions::getVersion() method instead.
067 *
068 * @var array<string, string>
069 * @internal
070 */
071 const VERSIONS = %s;
072
073 private function __construct()
074 {
075 }
076
077 /**
078 * @psalm-pure
079 *
080 * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not
081 * cause any side effects here.
082 */
083 public static function rootPackageName() : string
084 {
085 if (!self::composer2ApiUsable()) {
086 return self::ROOT_PACKAGE_NAME;
087 }
088
089 return InstalledVersions::getRootPackage()['name'];
090 }
091
092 /**
093 * @throws OutOfBoundsException If a version cannot be located.
094 *
095 * @psalm-param key-of<self::VERSIONS> $packageName
096 * @psalm-pure
097 *
098 * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not
099 * cause any side effects here.
100 */
101 public static function getVersion(string $packageName): string
102 {
103 if (self::composer2ApiUsable()) {
104 return InstalledVersions::getPrettyVersion($packageName)
105 . '@' . InstalledVersions::getReference($packageName);
106 }
107
108 if (isset(self::VERSIONS[$packageName])) {
109 return self::VERSIONS[$packageName];
110 }
111
112 throw new OutOfBoundsException(
113 'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'
114 );
115 }
116
117 private static function composer2ApiUsable(): bool
118 {
119 if (!class_exists(InstalledVersions::class, false)) {
120 return false;
121 }
122
123 if (method_exists(InstalledVersions::class, 'getAllRawData')) {
124 $rawData = InstalledVersions::getAllRawData();
125 if (count($rawData) === 1 && count($rawData[0]) === 0) {
126 return false;
127 }
128 } else {
129 $rawData = InstalledVersions::getRawData();
130 if ($rawData === null || $rawData === []) {
131 return false;
132 }
133 }
134
135 return true;
136 }
137 }
138
139 PHP;
140
141
142 public function activate(Composer $composer, IOInterface $io)
143 {
144 // Nothing to do here, as all features are provided through event listeners
145 }
146
147 public function deactivate(Composer $composer, IOInterface $io)
148 {
149 // Nothing to do here, as all features are provided through event listeners
150 }
151
152 public function uninstall(Composer $composer, IOInterface $io)
153 {
154 // Nothing to do here, as all features are provided through event listeners
155 }
156
157 /**
158 * {@inheritDoc}
159 */
160 public static function getSubscribedEvents(): array
161 {
162 return [ScriptEvents::POST_AUTOLOAD_DUMP => 'dumpVersionsClass'];
163 }
164
165 /**
166 * @throws RuntimeException
167 */
168 public static function dumpVersionsClass(Event $composerEvent)
169 {
170 $composer = $composerEvent->getComposer();
171 $rootPackage = $composer->getPackage();
172 $versions = iterator_to_array(self::getVersions($composer->getLocker(), $rootPackage));
173
174 if (! array_key_exists('composer/package-versions-deprecated', $versions)) {
175 //plugin must be globally installed - we only want to generate versions for projects which specifically
176 //require composer/package-versions-deprecated
177 return;
178 }
179
180 $versionClass = self::generateVersionsClass($rootPackage->getName(), $versions);
181
182 self::writeVersionClassToFile($versionClass, $composer, $composerEvent->getIO());
183 }
184
185 /**
186 * @param string[] $versions
187 */
188 private static function generateVersionsClass(string $rootPackageName, array $versions): string
189 {
190 return sprintf(
191 self::$generatedClassTemplate,
192 'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-(
193 $rootPackageName,
194 var_export($versions, true)
195 );
196 }
197
198 /**
199 * @throws RuntimeException
200 */
201 private static function writeVersionClassToFile(string $versionClassSource, Composer $composer, IOInterface $io)
202 {
203 $installPath = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage())
204 . '/src/PackageVersions/Versions.php';
205
206 $installDir = dirname($installPath);
207 if (! file_exists($installDir)) {
208 $io->write('<info>composer/package-versions-deprecated:</info> Package not found (probably scheduled for removal); generation of version class skipped.');
209
210 return;
211 }
212
213 if (! is_writable($installDir)) {
214 $io->write(
215 sprintf(
216 '<info>composer/package-versions-deprecated:</info> %s is not writable; generation of version class skipped.',
217 $installDir
218 )
219 );
220
221 return;
222 }
223
224 $io->write('<info>composer/package-versions-deprecated:</info> Generating version class...');
225
226 $installPathTmp = $installPath . '_' . uniqid('tmp', true);
227 file_put_contents($installPathTmp, $versionClassSource);
228 chmod($installPathTmp, 0664);
229 rename($installPathTmp, $installPath);
230
231 $io->write('<info>composer/package-versions-deprecated:</info> ...done generating version class');
232 }
233
234 /**
235 * @throws RuntimeException
236 */
237 private static function locateRootPackageInstallPath(
238 Config $composerConfig,
239 RootPackageInterface $rootPackage
240 ): string {
241 if (self::getRootPackageAlias($rootPackage)->getName() === 'composer/package-versions-deprecated') {
242 return dirname($composerConfig->get('vendor-dir'));
243 }
244
245 return $composerConfig->get('vendor-dir') . '/composer/package-versions-deprecated';
246 }
247
248 private static function getRootPackageAlias(RootPackageInterface $rootPackage): PackageInterface
249 {
250 $package = $rootPackage;
251
252 while ($package instanceof AliasPackage) {
253 $package = $package->getAliasOf();
254 }
255
256 return $package;
257 }
258
259 /**
260 * @return Generator&string[]
261 *
262 * @psalm-return Generator<string, string>
263 */
264 private static function getVersions(Locker $locker, RootPackageInterface $rootPackage): Generator
265 {
266 $lockData = $locker->getLockData();
267
268 $lockData['packages-dev'] = $lockData['packages-dev'] ?? [];
269
270 $packages = $lockData['packages'];
271 if (getenv('COMPOSER_DEV_MODE') !== '0') {
272 $packages = array_merge($packages, $lockData['packages-dev']);
273 }
274 foreach ($packages as $package) {
275 yield $package['name'] => $package['version'] . '@' . (
276 $package['source']['reference'] ?? $package['dist']['reference'] ?? ''
277 );
278 }
279
280 foreach ($rootPackage->getReplaces() as $replace) {
281 $version = $replace->getPrettyConstraint();
282 if ($version === 'self.version') {
283 $version = $rootPackage->getPrettyVersion();
284 }
285
286 yield $replace->getTarget() => $version . '@' . $rootPackage->getSourceReference();
287 }
288
289 yield $rootPackage->getName() => $rootPackage->getPrettyVersion() . '@' . $rootPackage->getSourceReference();
290 }
291 }
292