PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.2.19
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.2.19
3.0.3 3.0.2 3.0.1 trunk 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.3.0 2.3.1 2.3.10 2.3.11 2.3.12 2.3.13 2.3.14 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.7.91 2.7.92 2.7.93 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0
commercebird / vendor / composer / InstalledVersions.php
commercebird / 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 index.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