PluginProbe
Metricool – Social media and site statistics / 2.1.1
Metricool – Social media and site statistics v2.1.1
2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.27 trunk
metricool / vendor / _scoped / composer / InstalledVersions.php

InstalledVersions.php in Metricool – Social media and site statistics 2.1.1, at vendor/_scoped/composer/InstalledVersions.php

346 lines 17.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
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 */
12 namespace Metricool\Vendor\Composer;
13
14 use Metricool\Vendor\Composer\Autoload\ClassLoader;
15 use Metricool\Vendor\Composer\Semver\VersionParser;
16 /**
17 * This class is copied in every Composer installed project and available to all
18 *
19 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
20 *
21 * To require its presence, you can require `composer-runtime-api ^2.0`
22 *
23 * @final
24 */
25 class InstalledVersions
26 {
27 /**
28 * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
29 * @internal
30 */
31 private static $selfDir = null;
32 /**
33 * @var mixed[]|null
34 * @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
35 */
36 private static $installed;
37 /**
38 * @var bool
39 */
40 private static $installedIsLocalDir;
41 /**
42 * @var bool|null
43 */
44 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();
50 /**
51 * Returns a list of all package names which are present, either by being installed, replaced or provided
52 *
53 * @return string[]
54 * @psalm-return list<string>
55 */
56 public static function getInstalledPackages()
57 {
58 $packages = array();
59 foreach (self::getInstalled() as $installed) {
60 $packages[] = array_keys($installed['versions']);
61 }
62 if (1 === \count($packages)) {
63 return $packages[0];
64 }
65 return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
66 }
67 /**
68 * Returns a list of all package names with a specific type e.g. 'library'
69 *
70 * @param string $type
71 * @return string[]
72 * @psalm-return list<string>
73 */
74 public static function getInstalledPackagesByType($type)
75 {
76 $packagesByType = array();
77 foreach (self::getInstalled() as $installed) {
78 foreach ($installed['versions'] as $name => $package) {
79 if (isset($package['type']) && $package['type'] === $type) {
80 $packagesByType[] = $name;
81 }
82 }
83 }
84 return $packagesByType;
85 }
86 /**
87 * Checks whether the given package is installed
88 *
89 * This also returns true if the package name is provided or replaced by another package
90 *
91 * @param string $packageName
92 * @param bool $includeDevRequirements
93 * @return bool
94 */
95 public static function isInstalled($packageName, $includeDevRequirements = \true)
96 {
97 foreach (self::getInstalled() as $installed) {
98 if (isset($installed['versions'][$packageName])) {
99 return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false;
100 }
101 }
102 return \false;
103 }
104 /**
105 * Checks whether the given package satisfies a version constraint
106 *
107 * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
108 *
109 * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
110 *
111 * @param VersionParser $parser Install composer/semver to have access to this class and functionality
112 * @param string $packageName
113 * @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
114 * @return bool
115 */
116 public static function satisfies(VersionParser $parser, $packageName, $constraint)
117 {
118 $constraint = $parser->parseConstraints((string) $constraint);
119 $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
120 return $provided->matches($constraint);
121 }
122 /**
123 * Returns a version constraint representing all the range(s) which are installed for a given package
124 *
125 * It is easier to use this via isInstalled() with the $constraint argument if you need to check
126 * whether a given version of a package is installed, and not just whether it exists
127 *
128 * @param string $packageName
129 * @return string Version constraint usable with composer/semver
130 */
131 public static function getVersionRanges($packageName)
132 {
133 foreach (self::getInstalled() as $installed) {
134 if (!isset($installed['versions'][$packageName])) {
135 continue;
136 }
137 $ranges = array();
138 if (isset($installed['versions'][$packageName]['pretty_version'])) {
139 $ranges[] = $installed['versions'][$packageName]['pretty_version'];
140 }
141 if (array_key_exists('aliases', $installed['versions'][$packageName])) {
142 $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
143 }
144 if (array_key_exists('replaced', $installed['versions'][$packageName])) {
145 $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
146 }
147 if (array_key_exists('provided', $installed['versions'][$packageName])) {
148 $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
149 }
150 return implode(' || ', $ranges);
151 }
152 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
153 }
154 /**
155 * @param string $packageName
156 * @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
157 */
158 public static function getVersion($packageName)
159 {
160 foreach (self::getInstalled() as $installed) {
161 if (!isset($installed['versions'][$packageName])) {
162 continue;
163 }
164 if (!isset($installed['versions'][$packageName]['version'])) {
165 return null;
166 }
167 return $installed['versions'][$packageName]['version'];
168 }
169 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
170 }
171 /**
172 * @param string $packageName
173 * @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
174 */
175 public static function getPrettyVersion($packageName)
176 {
177 foreach (self::getInstalled() as $installed) {
178 if (!isset($installed['versions'][$packageName])) {
179 continue;
180 }
181 if (!isset($installed['versions'][$packageName]['pretty_version'])) {
182 return null;
183 }
184 return $installed['versions'][$packageName]['pretty_version'];
185 }
186 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
187 }
188 /**
189 * @param string $packageName
190 * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
191 */
192 public static function getReference($packageName)
193 {
194 foreach (self::getInstalled() as $installed) {
195 if (!isset($installed['versions'][$packageName])) {
196 continue;
197 }
198 if (!isset($installed['versions'][$packageName]['reference'])) {
199 return null;
200 }
201 return $installed['versions'][$packageName]['reference'];
202 }
203 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
204 }
205 /**
206 * @param string $packageName
207 * @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.
208 */
209 public static function getInstallPath($packageName)
210 {
211 foreach (self::getInstalled() as $installed) {
212 if (!isset($installed['versions'][$packageName])) {
213 continue;
214 }
215 return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
216 }
217 throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
218 }
219 /**
220 * @return array
221 * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
222 */
223 public static function getRootPackage()
224 {
225 $installed = self::getInstalled();
226 return $installed[0]['root'];
227 }
228 /**
229 * Returns the raw installed.php data for custom implementations
230 *
231 * @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.
232 * @return array[]
233 * @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[]}>}
234 */
235 public static function getRawData()
236 {
237 @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);
238 if (null === self::$installed) {
239 // only require the installed.php file if this file is loaded from its dumped location,
240 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
241 if (substr(__DIR__, -8, 1) !== 'C') {
242 self::$installed = include __DIR__ . '/installed.php';
243 } else {
244 self::$installed = array();
245 }
246 }
247 return self::$installed;
248 }
249 /**
250 * Returns the raw data of all installed.php which are currently loaded for custom implementations
251 *
252 * @return array[]
253 * @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[]}>}>
254 */
255 public static function getAllRawData()
256 {
257 return self::getInstalled();
258 }
259 /**
260 * Lets you reload the static array from another file
261 *
262 * This is only useful for complex integrations in which a project needs to use
263 * this class but then also needs to execute another project's autoloader in process,
264 * and wants to ensure both projects have access to their version of installed.php.
265 *
266 * A typical case would be PHPUnit, where it would need to make sure it reads all
267 * the data it needs from this class, then call reload() with
268 * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
269 * the project in which it runs can then also use this class safely, without
270 * interference between PHPUnit's dependencies and the project's dependencies.
271 *
272 * @param array[] $data A vendor/composer/installed.php data set
273 * @return void
274 *
275 * @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
276 */
277 public static function reload($data)
278 {
279 self::$installed = $data;
280 self::$installedByVendor = array();
281 // when using reload, we disable the duplicate protection to ensure that self::$installed data is
282 // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
283 // so we have to assume it does not, and that may result in duplicate data being returned when listing
284 // all installed packages for example
285 self::$installedIsLocalDir = \false;
286 }
287 /**
288 * @return string
289 */
290 private static function getSelfDir()
291 {
292 if (self::$selfDir === null) {
293 self::$selfDir = strtr(__DIR__, '\\', '/');
294 }
295 return self::$selfDir;
296 }
297 /**
298 * @return array[]
299 * @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[]}>}>
300 */
301 private static function getInstalled()
302 {
303 if (null === self::$canGetVendors) {
304 self::$canGetVendors = method_exists('Metricool\Vendor\Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
305 }
306 $installed = array();
307 $copiedLocalDir = \false;
308 if (self::$canGetVendors) {
309 $selfDir = self::getSelfDir();
310 foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
311 $vendorDir = strtr($vendorDir, '\\', '/');
312 if (isset(self::$installedByVendor[$vendorDir])) {
313 $installed[] = self::$installedByVendor[$vendorDir];
314 } elseif (is_file($vendorDir . '/composer/installed.php')) {
315 /** @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 */
316 $required = require $vendorDir . '/composer/installed.php';
317 self::$installedByVendor[$vendorDir] = $required;
318 $installed[] = $required;
319 if (self::$installed === null && $vendorDir . '/composer' === $selfDir) {
320 self::$installed = $required;
321 self::$installedIsLocalDir = \true;
322 }
323 }
324 if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) {
325 $copiedLocalDir = \true;
326 }
327 }
328 }
329 if (null === self::$installed) {
330 // only require the installed.php file if this file is loaded from its dumped location,
331 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
332 if (substr(__DIR__, -8, 1) !== 'C') {
333 /** @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 */
334 $required = require __DIR__ . '/installed.php';
335 self::$installed = $required;
336 } else {
337 self::$installed = array();
338 }
339 }
340 if (self::$installed !== array() && !$copiedLocalDir) {
341 $installed[] = self::$installed;
342 }
343 return $installed;
344 }
345 }
346