public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Trace
data/web/inc/lib/vendor/composer/InstalledVersions.php
Trace helps you understand code history line by line. See who changed each line, when it changed, and which commit introduced it.
Author
Date
Commit
Line
Code
1
<?php
3
/*
4
* This file is part of Composer.
5
*
6
* (c) Nils Adermann <[email protected]>
7
* Jordi Boggiano <[email protected]>
8
*
9
* For the full copyright and license information, please view the LICENSE
10
* file that was distributed with this source code.
11
*/
13
namespace Composer;
15
use Composer\Autoload\ClassLoader;
16
use Composer\Semver\VersionParser;
18
/**
19
* This class is copied in every Composer installed project and available to all
20
*
21
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
22
*
23
* To require its presence, you can require `composer-runtime-api ^2.0`
24
*
25
* @final
26
*/
27
class InstalledVersions
28
{
29
/**
30
* @var mixed[]|null
31
* @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
32
*/
33
private static $installed;
35
/**
36
* @var bool
37
*/
38
private static $installedIsLocalDir;
40
/**
41
* @var bool|null
42
*/
43
private static $canGetVendors;
45
/**
46
* @var array[]
47
* @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[]}>}>
48
*/
49
private static $installedByVendor = array();
51
/**
52
* Returns a list of all package names which are present, either by being installed, replaced or provided
53
*
54
* @return string[]
55
* @psalm-return list<string>
56
*/
57
public static function getInstalledPackages()
58
{
59
$packages = array();
60
foreach (self::getInstalled() as $installed) {
61
$packages[] = array_keys($installed['versions']);
62
}
64
if (1 === \count($packages)) {
65
return $packages[0];
66
}
68
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
69
}
71
/**
72
* Returns a list of all package names with a specific type e.g. 'library'
73
*
74
* @param string $type
75
* @return string[]
76
* @psalm-return list<string>
77
*/
78
public static function getInstalledPackagesByType($type)
79
{
80
$packagesByType = array();
82
foreach (self::getInstalled() as $installed) {
83
foreach ($installed['versions'] as $name => $package) {
84
if (isset($package['type']) && $package['type'] === $type) {
85
$packagesByType[] = $name;
86
}
87
}
88
}
90
return $packagesByType;
91
}
93
/**
94
* Checks whether the given package is installed
95
*
96
* This also returns true if the package name is provided or replaced by another package
97
*
98
* @param string $packageName
99
* @param bool $includeDevRequirements
100
* @return bool
101
*/
102
public static function isInstalled($packageName, $includeDevRequirements = true)
103
{
104
foreach (self::getInstalled() as $installed) {
105
if (isset($installed['versions'][$packageName])) {
106
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
107
}
108
}
110
return false;
111
}
113
/**
114
* Checks whether the given package satisfies a version constraint
115
*
116
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
117
*
118
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
119
*
120
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
121
* @param string $packageName
122
* @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
123
* @return bool
124
*/
125
public static function satisfies(VersionParser $parser, $packageName, $constraint)
126
{
127
$constraint = $parser->parseConstraints((string) $constraint);
128
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
130
return $provided->matches($constraint);
131
}
133
/**
134
* Returns a version constraint representing all the range(s) which are installed for a given package
135
*
136
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
137
* whether a given version of a package is installed, and not just whether it exists
138
*
139
* @param string $packageName
140
* @return string Version constraint usable with composer/semver
141
*/
142
public static function getVersionRanges($packageName)
143
{
144
foreach (self::getInstalled() as $installed) {
145
if (!isset($installed['versions'][$packageName])) {
146
continue;
147
}
149
$ranges = array();
150
if (isset($installed['versions'][$packageName]['pretty_version'])) {
151
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
152
}
153
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
154
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
155
}
156
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
157
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
158
}
159
if (array_key_exists('provided', $installed['versions'][$packageName])) {
160
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
161
}
163
return implode(' || ', $ranges);
164
}
166
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
167
}
169
/**
170
* @param string $packageName
171
* @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
172
*/
173
public static function getVersion($packageName)
174
{
175
foreach (self::getInstalled() as $installed) {
176
if (!isset($installed['versions'][$packageName])) {
177
continue;
178
}
180
if (!isset($installed['versions'][$packageName]['version'])) {
181
return null;
182
}
184
return $installed['versions'][$packageName]['version'];
185
}
187
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
188
}
190
/**
191
* @param string $packageName
192
* @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
193
*/
194
public static function getPrettyVersion($packageName)
195
{
196
foreach (self::getInstalled() as $installed) {
197
if (!isset($installed['versions'][$packageName])) {
198
continue;
199
}
201
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
202
return null;
203
}
205
return $installed['versions'][$packageName]['pretty_version'];
206
}
208
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
209
}
211
/**
212
* @param string $packageName
213
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
214
*/
215
public static function getReference($packageName)
216
{
217
foreach (self::getInstalled() as $installed) {
218
if (!isset($installed['versions'][$packageName])) {
219
continue;
220
}
222
if (!isset($installed['versions'][$packageName]['reference'])) {
223
return null;
224
}
226
return $installed['versions'][$packageName]['reference'];
227
}
229
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
230
}
232
/**
233
* @param string $packageName
234
* @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.
235
*/
236
public static function getInstallPath($packageName)
237
{
238
foreach (self::getInstalled() as $installed) {
239
if (!isset($installed['versions'][$packageName])) {
240
continue;
241
}
243
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
244
}
246
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
247
}
249
/**
250
* @return array
251
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
252
*/
253
public static function getRootPackage()
254
{
255
$installed = self::getInstalled();
257
return $installed[0]['root'];
258
}
260
/**
261
* Returns the raw installed.php data for custom implementations
262
*
263
* @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.
264
* @return array[]
265
* @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[]}>}
266
*/
267
public static function getRawData()
268
{
269
@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);
271
if (null === self::$installed) {
272
// only require the installed.php file if this file is loaded from its dumped location,
273
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
274
if (substr(__DIR__, -8, 1) !== 'C') {
275
self::$installed = include __DIR__ . '/installed.php';
276
} else {
277
self::$installed = array();
278
}
279
}
281
return self::$installed;
282
}
284
/**
285
* Returns the raw data of all installed.php which are currently loaded for custom implementations
286
*
287
* @return array[]
288
* @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[]}>}>
289
*/
290
public static function getAllRawData()
291
{
292
return self::getInstalled();
293
}
295
/**
296
* Lets you reload the static array from another file
297
*
298
* This is only useful for complex integrations in which a project needs to use
299
* this class but then also needs to execute another project's autoloader in process,
300
* and wants to ensure both projects have access to their version of installed.php.
301
*
302
* A typical case would be PHPUnit, where it would need to make sure it reads all
303
* the data it needs from this class, then call reload() with
304
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
305
* the project in which it runs can then also use this class safely, without
306
* interference between PHPUnit's dependencies and the project's dependencies.
307
*
308
* @param array[] $data A vendor/composer/installed.php data set
309
* @return void
310
*
311
* @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
312
*/
313
public static function reload($data)
314
{
315
self::$installed = $data;
316
self::$installedByVendor = array();
318
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
319
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
320
// so we have to assume it does not, and that may result in duplicate data being returned when listing
321
// all installed packages for example
322
self::$installedIsLocalDir = false;
323
}
325
/**
326
* @return array[]
327
* @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[]}>}>
328
*/
329
private static function getInstalled()
330
{
331
if (null === self::$canGetVendors) {
332
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
333
}
335
$installed = array();
336
$copiedLocalDir = false;
338
if (self::$canGetVendors) {
339
$selfDir = strtr(__DIR__, '\\', '/');
340
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
341
$vendorDir = strtr($vendorDir, '\\', '/');
342
if (isset(self::$installedByVendor[$vendorDir])) {
343
$installed[] = self::$installedByVendor[$vendorDir];
344
} elseif (is_file($vendorDir.'/composer/installed.php')) {
345
/** @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 */
346
$required = require $vendorDir.'/composer/installed.php';
347
self::$installedByVendor[$vendorDir] = $required;
348
$installed[] = $required;
349
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
350
self::$installed = $required;
351
self::$installedIsLocalDir = true;
352
}
353
}
354
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
355
$copiedLocalDir = true;
356
}
357
}
358
}
360
if (null === self::$installed) {
361
// only require the installed.php file if this file is loaded from its dumped location,
362
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
363
if (substr(__DIR__, -8, 1) !== 'C') {
364
/** @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 */
365
$required = require __DIR__ . '/installed.php';
366
self::$installed = $required;
367
} else {
368
self::$installed = array();
369
}
370
}
372
if (self::$installed !== array() && !$copiedLocalDir) {
373
$installed[] = self::$installed;
374
}
376
return $installed;
377
}
378
}