Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

InstalledVersions.php

Zuletzt modifiziert: 01.05.2026, 11:25 - Dateigröße: 16.99 KiB


001  <?php
002   
003  /*
004   * This file is part of Composer.
005   *
006   * (c) Nils Adermann <naderman@naderman.de>
007   *     Jordi Boggiano <j.boggiano@seld.be>
008   *
009   * For the full copyright and license information, please view the LICENSE
010   * file that was distributed with this source code.
011   */
012   
013  namespace Composer;
014   
015  use Composer\Autoload\ClassLoader;
016  use Composer\Semver\VersionParser;
017   
018  /**
019   * This class is copied in every Composer installed project and available to all
020   *
021   * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
022   *
023   * To require its presence, you can require `composer-runtime-api ^2.0`
024   *
025   * @final
026   */
027  class InstalledVersions
028  {
029      /**
030       * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
031       * @internal
032       */
033      private static $selfDir = null;
034   
035      /**
036       * @var mixed[]|null
037       * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
038       */
039      private static $installed;
040   
041      /**
042       * @var bool
043       */
044      private static $installedIsLocalDir;
045   
046      /**
047       * @var bool|null
048       */
049      private static $canGetVendors;
050   
051      /**
052       * @var array[]
053       * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
054       */
055      private static $installedByVendor = array();
056   
057      /**
058       * Returns a list of all package names which are present, either by being installed, replaced or provided
059       *
060       * @return string[]
061       * @psalm-return list<string>
062       */
063      public static function getInstalledPackages()
064      {
065          $packages = array();
066          foreach (self::getInstalled() as $installed) {
067              $packages[] = array_keys($installed['versions']);
068          }
069   
070          if (1 === \count($packages)) {
071              return $packages[0];
072          }
073   
074          return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
075      }
076   
077      /**
078       * Returns a list of all package names with a specific type e.g. 'library'
079       *
080       * @param  string   $type
081       * @return string[]
082       * @psalm-return list<string>
083       */
084      public static function getInstalledPackagesByType($type)
085      {
086          $packagesByType = array();
087   
088          foreach (self::getInstalled() as $installed) {
089              foreach ($installed['versions'] as $name => $package) {
090                  if (isset($package['type']) && $package['type'] === $type) {
091                      $packagesByType[] = $name;
092                  }
093              }
094          }
095   
096          return $packagesByType;
097      }
098   
099      /**
100       * Checks whether the given package is installed
101       *
102       * This also returns true if the package name is provided or replaced by another package
103       *
104       * @param  string $packageName
105       * @param  bool   $includeDevRequirements
106       * @return bool
107       */
108      public static function isInstalled($packageName, $includeDevRequirements = true)
109      {
110          foreach (self::getInstalled() as $installed) {
111              if (isset($installed['versions'][$packageName])) {
112                  return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
113              }
114          }
115   
116          return false;
117      }
118   
119      /**
120       * Checks whether the given package satisfies a version constraint
121       *
122       * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
123       *
124       *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
125       *
126       * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
127       * @param  string        $packageName
128       * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
129       * @return bool
130       */
131      public static function satisfies(VersionParser $parser, $packageName, $constraint)
132      {
133          $constraint = $parser->parseConstraints((string) $constraint);
134          $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
135   
136          return $provided->matches($constraint);
137      }
138   
139      /**
140       * Returns a version constraint representing all the range(s) which are installed for a given package
141       *
142       * It is easier to use this via isInstalled() with the $constraint argument if you need to check
143       * whether a given version of a package is installed, and not just whether it exists
144       *
145       * @param  string $packageName
146       * @return string Version constraint usable with composer/semver
147       */
148      public static function getVersionRanges($packageName)
149      {
150          foreach (self::getInstalled() as $installed) {
151              if (!isset($installed['versions'][$packageName])) {
152                  continue;
153              }
154   
155              $ranges = array();
156              if (isset($installed['versions'][$packageName]['pretty_version'])) {
157                  $ranges[] = $installed['versions'][$packageName]['pretty_version'];
158              }
159              if (array_key_exists('aliases', $installed['versions'][$packageName])) {
160                  $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
161              }
162              if (array_key_exists('replaced', $installed['versions'][$packageName])) {
163                  $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
164              }
165              if (array_key_exists('provided', $installed['versions'][$packageName])) {
166                  $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
167              }
168   
169              return implode(' || ', $ranges);
170          }
171   
172          throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
173      }
174   
175      /**
176       * @param  string      $packageName
177       * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
178       */
179      public static function getVersion($packageName)
180      {
181          foreach (self::getInstalled() as $installed) {
182              if (!isset($installed['versions'][$packageName])) {
183                  continue;
184              }
185   
186              if (!isset($installed['versions'][$packageName]['version'])) {
187                  return null;
188              }
189   
190              return $installed['versions'][$packageName]['version'];
191          }
192   
193          throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
194      }
195   
196      /**
197       * @param  string      $packageName
198       * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
199       */
200      public static function getPrettyVersion($packageName)
201      {
202          foreach (self::getInstalled() as $installed) {
203              if (!isset($installed['versions'][$packageName])) {
204                  continue;
205              }
206   
207              if (!isset($installed['versions'][$packageName]['pretty_version'])) {
208                  return null;
209              }
210   
211              return $installed['versions'][$packageName]['pretty_version'];
212          }
213   
214          throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
215      }
216   
217      /**
218       * @param  string      $packageName
219       * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
220       */
221      public static function getReference($packageName)
222      {
223          foreach (self::getInstalled() as $installed) {
224              if (!isset($installed['versions'][$packageName])) {
225                  continue;
226              }
227   
228              if (!isset($installed['versions'][$packageName]['reference'])) {
229                  return null;
230              }
231   
232              return $installed['versions'][$packageName]['reference'];
233          }
234   
235          throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
236      }
237   
238      /**
239       * @param  string      $packageName
240       * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
241       */
242      public static function getInstallPath($packageName)
243      {
244          foreach (self::getInstalled() as $installed) {
245              if (!isset($installed['versions'][$packageName])) {
246                  continue;
247              }
248   
249              return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
250          }
251   
252          throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
253      }
254   
255      /**
256       * @return array
257       * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
258       */
259      public static function getRootPackage()
260      {
261          $installed = self::getInstalled();
262   
263          return $installed[0]['root'];
264      }
265   
266      /**
267       * Returns the raw installed.php data for custom implementations
268       *
269       * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
270       * @return array[]
271       * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
272       */
273      public static function getRawData()
274      {
275          @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
276   
277          if (null === self::$installed) {
278              // only require the installed.php file if this file is loaded from its dumped location,
279              // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
280              if (substr(__DIR__, -8, 1) !== 'C') {
281                  self::$installed = include __DIR__ . '/installed.php';
282              } else {
283                  self::$installed = array();
284              }
285          }
286   
287          return self::$installed;
288      }
289   
290      /**
291       * Returns the raw data of all installed.php which are currently loaded for custom implementations
292       *
293       * @return array[]
294       * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
295       */
296      public static function getAllRawData()
297      {
298          return self::getInstalled();
299      }
300   
301      /**
302       * Lets you reload the static array from another file
303       *
304       * This is only useful for complex integrations in which a project needs to use
305       * this class but then also needs to execute another project's autoloader in process,
306       * and wants to ensure both projects have access to their version of installed.php.
307       *
308       * A typical case would be PHPUnit, where it would need to make sure it reads all
309       * the data it needs from this class, then call reload() with
310       * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
311       * the project in which it runs can then also use this class safely, without
312       * interference between PHPUnit's dependencies and the project's dependencies.
313       *
314       * @param  array[] $data A vendor/composer/installed.php data set
315       * @return void
316       *
317       * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
318       */
319      public static function reload($data)
320      {
321          self::$installed = $data;
322          self::$installedByVendor = array();
323   
324          // when using reload, we disable the duplicate protection to ensure that self::$installed data is
325          // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
326          // so we have to assume it does not, and that may result in duplicate data being returned when listing
327          // all installed packages for example
328          self::$installedIsLocalDir = false;
329      }
330   
331      /**
332       * @return string
333       */
334      private static function getSelfDir()
335      {
336          if (self::$selfDir === null) {
337              self::$selfDir = strtr(__DIR__, '\\', '/');
338          }
339   
340          return self::$selfDir;
341      }
342   
343      /**
344       * @return array[]
345       * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
346       */
347      private static function getInstalled()
348      {
349          if (null === self::$canGetVendors) {
350              self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
351          }
352   
353          $installed = array();
354          $copiedLocalDir = false;
355   
356          if (self::$canGetVendors) {
357              $selfDir = self::getSelfDir();
358              foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
359                  $vendorDir = strtr($vendorDir, '\\', '/');
360                  if (isset(self::$installedByVendor[$vendorDir])) {
361                      $installed[] = self::$installedByVendor[$vendorDir];
362                  } elseif (is_file($vendorDir.'/composer/installed.php')) {
363                      /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
364                      $required = require $vendorDir.'/composer/installed.php';
365                      self::$installedByVendor[$vendorDir] = $required;
366                      $installed[] = $required;
367                      if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
368                          self::$installed = $required;
369                          self::$installedIsLocalDir = true;
370                      }
371                  }
372                  if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
373                      $copiedLocalDir = true;
374                  }
375              }
376          }
377   
378          if (null === self::$installed) {
379              // only require the installed.php file if this file is loaded from its dumped location,
380              // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
381              if (substr(__DIR__, -8, 1) !== 'C') {
382                  /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
383                  $required = require __DIR__ . '/installed.php';
384                  self::$installed = $required;
385              } else {
386                  self::$installed = array();
387              }
388          }
389   
390          if (self::$installed !== array() && !$copiedLocalDir) {
391              $installed[] = self::$installed;
392          }
393   
394          return $installed;
395      }
396  }
397