PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.5.4
Secure Custom Fields v6.5.4
6.9.2 6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / vendor / composer / InstalledVersions.php
secure-custom-fields / vendor / composer Last commit date
ClassLoader.php 1 year ago InstalledVersions.php 1 year ago LICENSE 1 year ago autoload_classmap.php 1 year ago autoload_namespaces.php 1 year ago autoload_psr4.php 1 year ago autoload_real.php 1 year ago autoload_static.php 1 year ago installed.json 1 year ago installed.php 1 year ago platform_check.php 1 year ago
InstalledVersions.php
379 lines
1 <?php
2
3 /*
4 * This file is part of Composer.
5 *
6 * (c) Nils Adermann <naderman@naderman.de>
7 * Jordi Boggiano <j.boggiano@seld.be>
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13 namespace Composer;
14
15 use Composer\Autoload\ClassLoader;
16 use Composer\Semver\VersionParser;
17
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;
34
35 /**
36 * @var bool
37 */
38 private static $installedIsLocalDir;
39
40 /**
41 * @var bool|null
42 */
43 private static $canGetVendors;
44
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();
50
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 }
63
64 if (1 === \count($packages)) {
65 return $packages[0];
66 }
67
68 return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
69 }
70
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();
81
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 }
89
90 return $packagesByType;
91 }
92
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 }
109
110 return false;
111 }
112
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));
129
130 return $provided->matches($constraint);
131 }
132
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 }
148
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 }
162
163 return implode(' || ', $ranges);
164 }
165
166 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
167 }
168
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 }
179
180 if (!isset($installed['versions'][$packageName]['version'])) {
181 return null;
182 }
183
184 return $installed['versions'][$packageName]['version'];
185 }
186
187 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
188 }
189
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 }
200
201 if (!isset($installed['versions'][$packageName]['pretty_version'])) {
202 return null;
203 }
204
205 return $installed['versions'][$packageName]['pretty_version'];
206 }
207
208 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
209 }
210
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 }
221
222 if (!isset($installed['versions'][$packageName]['reference'])) {
223 return null;
224 }
225
226 return $installed['versions'][$packageName]['reference'];
227 }
228
229 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
230 }
231
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 }
242
243 return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
244 }
245
246 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
247 }
248
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();
256
257 return $installed[0]['root'];
258 }
259
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);
270
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 }
280
281 return self::$installed;
282 }
283
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 }
294
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();
317
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 }
324
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 }
334
335 $installed = array();
336 $copiedLocalDir = false;
337
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 }
359
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 }
371
372 if (self::$installed !== array() && !$copiedLocalDir) {
373 $installed[] = self::$installed;
374 }
375
376 return $installed;
377 }
378 }
379