PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 4.0.0
WP 2FA – Two-factor authentication for WordPress v4.0.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / vendor / composer / InstalledVersions.php
wp-2fa / vendor / composer Last commit date
ClassLoader.php 5 days ago InstalledVersions.php 5 days ago LICENSE 5 days ago autoload_classmap.php 5 days ago autoload_namespaces.php 5 days ago autoload_psr4.php 5 days ago autoload_real.php 5 days ago autoload_static.php 5 days ago installed.json 5 days ago installed.php 5 days ago
InstalledVersions.php
346 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 namespace Composer;
13
14 use Composer\Autoload\ClassLoader;
15 use 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('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